Implement NtAccessCheck.
[wine/gsoc-2012-control.git] / dlls / user / win.c
blobd1ad153b0c6888b0548f67ddf3118908252bb94f
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wine/winbase16.h"
31 #include "wine/winuser16.h"
32 #include "wownt32.h"
33 #include "wine/server.h"
34 #include "wine/unicode.h"
35 #include "win.h"
36 #include "user_private.h"
37 #include "controls.h"
38 #include "cursoricon.h"
39 #include "winpos.h"
40 #include "winerror.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(win);
44 WINE_DECLARE_DEBUG_CHANNEL(msg);
46 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
47 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
49 /**********************************************************************/
51 /* Desktop window */
52 static HWND hwndDesktop;
54 static WORD wDragWidth = 4;
55 static WORD wDragHeight= 3;
57 static void *user_handles[NB_USER_HANDLES];
59 /***********************************************************************
60 * create_window_handle
62 * Create a window handle with the server.
64 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
65 HINSTANCE instance, WINDOWPROCTYPE type )
67 WORD index;
68 WND *win;
69 struct tagCLASS *class = NULL;
70 user_handle_t handle = 0;
71 int extra_bytes = 0;
73 /* if 16-bit instance, map to module handle */
74 if (instance && !HIWORD(instance))
75 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
77 SERVER_START_REQ( create_window )
79 req->parent = parent;
80 req->owner = owner;
81 req->atom = atom;
82 req->instance = instance;
83 if (!wine_server_call_err( req ))
85 handle = reply->handle;
86 extra_bytes = reply->extra;
87 class = reply->class_ptr;
90 SERVER_END_REQ;
92 if (!handle)
94 WARN( "error %ld creating window\n", GetLastError() );
95 return NULL;
98 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
100 SERVER_START_REQ( destroy_window )
102 req->handle = handle;
103 wine_server_call( req );
105 SERVER_END_REQ;
106 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
107 return NULL;
110 USER_Lock();
112 index = USER_HANDLE_TO_INDEX(handle);
113 assert( index < NB_USER_HANDLES );
114 user_handles[index] = win;
115 win->hwndSelf = handle;
116 win->dwMagic = WND_MAGIC;
117 win->cbWndExtra = extra_bytes;
118 memset( win->wExtra, 0, extra_bytes );
119 CLASS_AddWindow( class, win, type );
120 return win;
124 /***********************************************************************
125 * free_window_handle
127 * Free a window handle.
129 static WND *free_window_handle( HWND hwnd )
131 WND *ptr;
132 WORD index = USER_HANDLE_TO_INDEX(hwnd);
134 if (index >= NB_USER_HANDLES) return NULL;
135 USER_Lock();
136 if ((ptr = user_handles[index]))
138 SERVER_START_REQ( destroy_window )
140 req->handle = hwnd;
141 if (!wine_server_call_err( req ))
143 user_handles[index] = NULL;
144 ptr->dwMagic = 0;
146 else
147 ptr = NULL;
149 SERVER_END_REQ;
151 USER_Unlock();
152 HeapFree( GetProcessHeap(), 0, ptr );
153 return ptr;
157 /*******************************************************************
158 * list_window_children
160 * Build an array of the children of a given window. The array must be
161 * freed with HeapFree. Returns NULL when no windows are found.
163 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
165 HWND *list;
166 int size = 32;
168 for (;;)
170 int count = 0;
172 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
174 SERVER_START_REQ( get_window_children )
176 req->parent = hwnd;
177 req->atom = atom;
178 req->tid = tid;
179 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
180 if (!wine_server_call( req )) count = reply->count;
182 SERVER_END_REQ;
183 if (count && count < size)
185 list[count] = 0;
186 return list;
188 HeapFree( GetProcessHeap(), 0, list );
189 if (!count) break;
190 size = count + 1; /* restart with a large enough buffer */
192 return NULL;
196 /*******************************************************************
197 * list_window_parents
199 * Build an array of all parents of a given window, starting with
200 * the immediate parent. The array must be freed with HeapFree.
201 * Returns NULL if window is a top-level window.
203 static HWND *list_window_parents( HWND hwnd )
205 WND *win;
206 HWND current, *list;
207 int pos = 0, size = 16, count = 0;
209 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
211 current = hwnd;
212 for (;;)
214 if (!(win = WIN_GetPtr( current ))) goto empty;
215 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
216 if (win == WND_DESKTOP)
218 if (!pos) goto empty;
219 list[pos] = 0;
220 return list;
222 list[pos] = current = win->parent;
223 WIN_ReleasePtr( win );
224 if (++pos == size - 1)
226 /* need to grow the list */
227 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
228 if (!new_list) goto empty;
229 list = new_list;
230 size += 16;
234 /* at least one parent belongs to another process, have to query the server */
236 for (;;)
238 count = 0;
239 SERVER_START_REQ( get_window_parents )
241 req->handle = hwnd;
242 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
243 if (!wine_server_call( req )) count = reply->count;
245 SERVER_END_REQ;
246 if (!count) goto empty;
247 if (size > count)
249 list[count] = 0;
250 return list;
252 HeapFree( GetProcessHeap(), 0, list );
253 size = count + 1;
254 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
257 empty:
258 HeapFree( GetProcessHeap(), 0, list );
259 return NULL;
263 /*******************************************************************
264 * send_parent_notify
266 static void send_parent_notify( HWND hwnd, UINT msg )
268 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
269 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
270 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
271 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
275 /*******************************************************************
276 * get_server_window_text
278 * Retrieve the window text from the server.
280 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
282 size_t len = 0;
284 SERVER_START_REQ( get_window_text )
286 req->handle = hwnd;
287 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
288 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
290 SERVER_END_REQ;
291 text[len / sizeof(WCHAR)] = 0;
295 /***********************************************************************
296 * WIN_GetPtr
298 * Return a pointer to the WND structure if local to the process,
299 * or WND_OTHER_PROCESS if handle may be valid in other process.
300 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
302 WND *WIN_GetPtr( HWND hwnd )
304 WND * ptr;
305 WORD index = USER_HANDLE_TO_INDEX(hwnd);
307 if (index >= NB_USER_HANDLES) return NULL;
309 USER_Lock();
310 if ((ptr = user_handles[index]))
312 if (ptr->dwMagic == WND_MAGIC &&
313 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
314 return ptr;
315 ptr = NULL;
317 else if (index == USER_HANDLE_TO_INDEX(hwndDesktop))
319 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
320 else ptr = NULL;
322 else ptr = WND_OTHER_PROCESS;
323 USER_Unlock();
324 return ptr;
328 /***********************************************************************
329 * WIN_IsCurrentProcess
331 * Check whether a given window belongs to the current process (and return the full handle).
333 HWND WIN_IsCurrentProcess( HWND hwnd )
335 WND *ptr;
336 HWND ret;
338 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
339 ret = ptr->hwndSelf;
340 WIN_ReleasePtr( ptr );
341 return ret;
345 /***********************************************************************
346 * WIN_IsCurrentThread
348 * Check whether a given window belongs to the current thread (and return the full handle).
350 HWND WIN_IsCurrentThread( HWND hwnd )
352 WND *ptr;
353 HWND ret = 0;
355 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
356 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
357 WIN_ReleasePtr( ptr );
358 return ret;
362 /***********************************************************************
363 * WIN_Handle32
365 * Convert a 16-bit window handle to a full 32-bit handle.
367 HWND WIN_Handle32( HWND16 hwnd16 )
369 WND *ptr;
370 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
372 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
373 /* do sign extension for -2 and -3 */
374 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
376 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
378 if (ptr == WND_DESKTOP) return GetDesktopWindow();
380 if (ptr != WND_OTHER_PROCESS)
382 hwnd = ptr->hwndSelf;
383 WIN_ReleasePtr( ptr );
385 else /* may belong to another process */
387 SERVER_START_REQ( get_window_info )
389 req->handle = hwnd;
390 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
392 SERVER_END_REQ;
394 return hwnd;
398 /***********************************************************************
399 * WIN_SetOwner
401 * Change the owner of a window.
403 HWND WIN_SetOwner( HWND hwnd, HWND owner )
405 WND *win = WIN_GetPtr( hwnd );
406 HWND ret = 0;
408 if (!win || win == WND_DESKTOP) return 0;
409 if (win == WND_OTHER_PROCESS)
411 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
412 return 0;
414 SERVER_START_REQ( set_window_owner )
416 req->handle = hwnd;
417 req->owner = owner;
418 if (!wine_server_call( req ))
420 win->owner = reply->full_owner;
421 ret = reply->prev_owner;
424 SERVER_END_REQ;
425 WIN_ReleasePtr( win );
426 return ret;
430 /***********************************************************************
431 * WIN_SetStyle
433 * Change the style of a window.
435 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
437 BOOL ok;
438 ULONG new_style, old_style = 0;
439 WND *win = WIN_GetPtr( hwnd );
441 if (!win || win == WND_DESKTOP) return 0;
442 if (win == WND_OTHER_PROCESS)
444 if (IsWindow(hwnd))
445 ERR( "cannot set style %lx/%lx on other process window %p\n",
446 set_bits, clear_bits, hwnd );
447 return 0;
449 new_style = (win->dwStyle | set_bits) & ~clear_bits;
450 if (new_style == win->dwStyle)
452 WIN_ReleasePtr( win );
453 return new_style;
455 SERVER_START_REQ( set_window_info )
457 req->handle = hwnd;
458 req->flags = SET_WIN_STYLE;
459 req->style = new_style;
460 req->extra_offset = -1;
461 if ((ok = !wine_server_call( req )))
463 old_style = reply->old_style;
464 win->dwStyle = new_style;
467 SERVER_END_REQ;
468 WIN_ReleasePtr( win );
469 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, old_style );
470 return old_style;
474 /***********************************************************************
475 * WIN_GetRectangles
477 * Get the window and client rectangles.
479 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
481 WND *win = WIN_GetPtr( hwnd );
482 BOOL ret = TRUE;
484 if (!win) return FALSE;
485 if (win == WND_DESKTOP)
487 RECT rect;
488 rect.left = rect.top = 0;
489 rect.right = GetSystemMetrics(SM_CXSCREEN);
490 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
491 if (rectWindow) *rectWindow = rect;
492 if (rectClient) *rectClient = rect;
494 else if (win == WND_OTHER_PROCESS)
496 SERVER_START_REQ( get_window_rectangles )
498 req->handle = hwnd;
499 if ((ret = !wine_server_call( req )))
501 if (rectWindow)
503 rectWindow->left = reply->window.left;
504 rectWindow->top = reply->window.top;
505 rectWindow->right = reply->window.right;
506 rectWindow->bottom = reply->window.bottom;
508 if (rectClient)
510 rectClient->left = reply->client.left;
511 rectClient->top = reply->client.top;
512 rectClient->right = reply->client.right;
513 rectClient->bottom = reply->client.bottom;
517 SERVER_END_REQ;
519 else
521 if (rectWindow) *rectWindow = win->rectWindow;
522 if (rectClient) *rectClient = win->rectClient;
523 WIN_ReleasePtr( win );
525 return ret;
529 /***********************************************************************
530 * WIN_DestroyWindow
532 * Destroy storage associated to a window. "Internals" p.358
534 LRESULT WIN_DestroyWindow( HWND hwnd )
536 WND *wndPtr;
537 HWND *list;
538 HMENU menu = 0, sys_menu;
540 TRACE("%p\n", hwnd );
542 /* free child windows */
543 if ((list = WIN_ListChildren( hwnd )))
545 int i;
546 for (i = 0; list[i]; i++)
548 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
549 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
551 HeapFree( GetProcessHeap(), 0, list );
554 /* Unlink now so we won't bother with the children later on */
555 SERVER_START_REQ( set_parent )
557 req->handle = hwnd;
558 req->parent = 0;
559 wine_server_call( req );
561 SERVER_END_REQ;
564 * Send the WM_NCDESTROY to the window being destroyed.
566 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
568 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
570 WINPOS_CheckInternalPos( hwnd );
572 /* free resources associated with the window */
574 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
575 if (!(wndPtr->dwStyle & WS_CHILD)) menu = (HMENU)wndPtr->wIDmenu;
576 sys_menu = wndPtr->hSysMenu;
577 WIN_ReleasePtr( wndPtr );
579 if (menu) DestroyMenu( menu );
580 if (sys_menu) DestroyMenu( sys_menu );
582 if (USER_Driver.pDestroyWindow) USER_Driver.pDestroyWindow( hwnd );
584 free_window_handle( hwnd );
585 return 0;
588 /***********************************************************************
589 * WIN_DestroyThreadWindows
591 * Destroy all children of 'wnd' owned by the current thread.
592 * Return TRUE if something was done.
594 void WIN_DestroyThreadWindows( HWND hwnd )
596 HWND *list;
597 int i;
599 if (!(list = WIN_ListChildren( hwnd ))) return;
600 for (i = 0; list[i]; i++)
602 if (WIN_IsCurrentThread( list[i] ))
603 DestroyWindow( list[i] );
604 else
605 WIN_DestroyThreadWindows( list[i] );
607 HeapFree( GetProcessHeap(), 0, list );
610 /***********************************************************************
611 * WIN_CreateDesktopWindow
613 * Create the desktop window.
615 BOOL WIN_CreateDesktopWindow(void)
617 CREATESTRUCTA cs;
619 TRACE("Creating desktop window\n");
621 if (!WINPOS_CreateInternalPosAtom()) return FALSE;
623 SERVER_START_REQ( create_window )
625 req->parent = 0;
626 req->owner = 0;
627 req->atom = LOWORD(DESKTOP_CLASS_ATOM);
628 req->instance = 0;
629 if (!wine_server_call_err( req )) hwndDesktop = reply->handle;
631 SERVER_END_REQ;
633 if (!hwndDesktop)
635 ERR( "error %ld creating desktop window\n", GetLastError() );
636 return FALSE;
639 cs.lpCreateParams = NULL;
640 cs.hInstance = 0;
641 cs.hMenu = 0;
642 cs.hwndParent = 0;
643 cs.x = 0;
644 cs.y = 0;
645 cs.cx = GetSystemMetrics( SM_CXSCREEN );
646 cs.cy = GetSystemMetrics( SM_CYSCREEN );
647 cs.style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
648 cs.dwExStyle = 0;
649 cs.lpszName = NULL;
650 cs.lpszClass = DESKTOP_CLASS_ATOM;
652 return USER_Driver.pCreateWindow( hwndDesktop, &cs, TRUE );
656 /***********************************************************************
657 * WIN_FixCoordinates
659 * Fix the coordinates - Helper for WIN_CreateWindowEx.
660 * returns default show mode in sw.
661 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
663 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
665 POINT pos[2];
667 if (cs->dwExStyle & WS_EX_MDICHILD)
669 UINT id = 0;
671 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
672 if (!(cs->style & WS_POPUP)) cs->hMenu = (HMENU)id;
674 TRACE("MDI child id %04x\n", id);
677 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
678 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
680 if (cs->style & (WS_CHILD | WS_POPUP))
682 if (cs->dwExStyle & WS_EX_MDICHILD)
684 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
686 cs->x = pos[0].x;
687 cs->y = pos[0].y;
689 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
690 cs->cx = pos[1].x;
691 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
692 cs->cy = pos[1].y;
694 else
696 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
697 cs->x = cs->y = 0;
698 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
699 cs->cx = cs->cy = 0;
702 else /* overlapped window */
704 STARTUPINFOW info;
706 GetStartupInfoW( &info );
708 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
710 /* Never believe Microsoft's documentation... CreateWindowEx doc says
711 * that if an overlapped window is created with WS_VISIBLE style bit
712 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
713 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
714 * reveals that
716 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
717 * 2) it does not ignore the y parameter as the docs claim; instead, it
718 * uses it as second parameter to ShowWindow() unless y is either
719 * CW_USEDEFAULT or CW_USEDEFAULT16.
721 * The fact that we didn't do 2) caused bogus windows pop up when wine
722 * was running apps that were using this obscure feature. Example -
723 * calc.exe that comes with Win98 (only Win98, it's different from
724 * the one that comes with Win95 and NT)
726 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
727 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
728 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
731 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
733 if (info.dwFlags & STARTF_USESIZE)
735 cs->cx = info.dwXSize;
736 cs->cy = info.dwYSize;
738 else /* if no other hint from the app, pick 3/4 of the screen real estate */
740 RECT r;
741 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
742 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
743 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
746 /* Handle case where only the cy values is set to default */
747 else if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16)
749 RECT r;
750 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
751 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
755 else
757 /* neither x nor cx are default. Check the y values .
758 * In the trace we see Outlook and Outlook Express using
759 * cy set to CW_USEDEFAULT when opening the address book.
761 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
762 RECT r;
763 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
764 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
765 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
770 /***********************************************************************
771 * dump_window_styles
773 static void dump_window_styles( DWORD style, DWORD exstyle )
775 TRACE( "style:" );
776 if(style & WS_POPUP) TRACE(" WS_POPUP");
777 if(style & WS_CHILD) TRACE(" WS_CHILD");
778 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
779 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
780 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
781 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
782 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
783 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
784 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
785 else
787 if(style & WS_BORDER) TRACE(" WS_BORDER");
788 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
790 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
791 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
792 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
793 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
794 if(style & WS_GROUP) TRACE(" WS_GROUP");
795 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
796 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
797 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
799 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
800 #define DUMPED_STYLES \
801 (WS_POPUP | \
802 WS_CHILD | \
803 WS_MINIMIZE | \
804 WS_VISIBLE | \
805 WS_DISABLED | \
806 WS_CLIPSIBLINGS | \
807 WS_CLIPCHILDREN | \
808 WS_MAXIMIZE | \
809 WS_BORDER | \
810 WS_DLGFRAME | \
811 WS_VSCROLL | \
812 WS_HSCROLL | \
813 WS_SYSMENU | \
814 WS_THICKFRAME | \
815 WS_GROUP | \
816 WS_TABSTOP | \
817 WS_MINIMIZEBOX | \
818 WS_MAXIMIZEBOX)
820 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
821 TRACE("\n");
822 #undef DUMPED_STYLES
824 TRACE( "exstyle:" );
825 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
826 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
827 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
828 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
829 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
830 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
831 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
832 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
833 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
834 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
835 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
836 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
837 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
838 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
839 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
840 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
841 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
842 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
844 #define DUMPED_EX_STYLES \
845 (WS_EX_DLGMODALFRAME | \
846 WS_EX_DRAGDETECT | \
847 WS_EX_NOPARENTNOTIFY | \
848 WS_EX_TOPMOST | \
849 WS_EX_ACCEPTFILES | \
850 WS_EX_TRANSPARENT | \
851 WS_EX_MDICHILD | \
852 WS_EX_TOOLWINDOW | \
853 WS_EX_WINDOWEDGE | \
854 WS_EX_CLIENTEDGE | \
855 WS_EX_CONTEXTHELP | \
856 WS_EX_RIGHT | \
857 WS_EX_RTLREADING | \
858 WS_EX_LEFTSCROLLBAR | \
859 WS_EX_CONTROLPARENT | \
860 WS_EX_STATICEDGE | \
861 WS_EX_APPWINDOW | \
862 WS_EX_LAYERED)
864 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
865 TRACE("\n");
866 #undef DUMPED_EX_STYLES
870 /***********************************************************************
871 * WIN_CreateWindowEx
873 * Implementation of CreateWindowEx().
875 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
876 WINDOWPROCTYPE type )
878 INT sw = SW_SHOW;
879 WND *wndPtr;
880 HWND hwnd, parent, owner, top_child = 0;
881 BOOL unicode = (type == WIN_PROC_32W);
883 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
884 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
885 (type == WIN_PROC_32W) ? debugstr_w((LPWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
886 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
887 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
889 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
891 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
892 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
894 /* Fix the styles for MDI children */
895 if (cs->dwExStyle & WS_EX_MDICHILD)
897 MDICREATESTRUCTA mdi_cs;
898 UINT flags = 0;
900 wndPtr = WIN_GetPtr(cs->hwndParent);
901 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
903 flags = wndPtr->flags;
904 WIN_ReleasePtr(wndPtr);
907 if (!(flags & WIN_ISMDICLIENT))
909 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
910 return 0;
913 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
914 * MDICREATESTRUCT members have the originally passed values.
916 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
917 * have the same layout.
919 mdi_cs.szClass = cs->lpszClass;
920 mdi_cs.szTitle = cs->lpszName;
921 mdi_cs.hOwner = cs->hInstance;
922 mdi_cs.x = cs->x;
923 mdi_cs.y = cs->y;
924 mdi_cs.cx = cs->cx;
925 mdi_cs.cy = cs->cy;
926 mdi_cs.style = cs->style;
927 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
929 cs->lpCreateParams = (LPVOID)&mdi_cs;
931 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
933 if (cs->style & WS_POPUP)
935 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
936 return 0;
938 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
940 else
942 cs->style &= ~WS_POPUP;
943 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
944 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
947 top_child = GetWindow(cs->hwndParent, GW_CHILD);
949 if (top_child)
951 /* Restore current maximized child */
952 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
954 TRACE("Restoring current maximized child %p\n", top_child);
955 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
956 ShowWindow(top_child, SW_RESTORE);
957 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
962 /* Find the parent window */
964 parent = GetDesktopWindow();
965 owner = 0;
967 if (cs->hwndParent == HWND_MESSAGE)
969 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
970 * message window (style: WS_POPUP|WS_DISABLED)
972 FIXME("Parent is HWND_MESSAGE\n");
974 else if (cs->hwndParent)
976 /* Make sure parent is valid */
977 if (!IsWindow( cs->hwndParent ))
979 WARN("Bad parent %p\n", cs->hwndParent );
980 return 0;
982 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
983 parent = WIN_GetFullHandle(cs->hwndParent);
984 else
985 owner = GetAncestor( cs->hwndParent, GA_ROOT );
987 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
989 WARN("No parent for child window\n" );
990 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
993 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
995 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
996 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
997 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
998 cs->dwExStyle |= WS_EX_WINDOWEDGE;
999 else
1000 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1002 /* Create the window structure */
1004 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
1006 TRACE("out of memory\n" );
1007 return 0;
1009 hwnd = wndPtr->hwndSelf;
1011 /* Fill the window structure */
1013 wndPtr->tid = GetCurrentThreadId();
1014 wndPtr->owner = owner;
1015 wndPtr->parent = parent;
1016 wndPtr->hInstance = cs->hInstance;
1017 wndPtr->text = NULL;
1018 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1019 wndPtr->dwExStyle = cs->dwExStyle;
1020 wndPtr->wIDmenu = 0;
1021 wndPtr->helpContext = 0;
1022 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1023 wndPtr->pVScroll = NULL;
1024 wndPtr->pHScroll = NULL;
1025 wndPtr->userdata = 0;
1026 wndPtr->hIcon = 0;
1027 wndPtr->hIconSmall = 0;
1028 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, (HMENU)-1 ) : 0;
1031 * Correct the window styles.
1033 * It affects only the style loaded into the WIN structure.
1036 if (!(wndPtr->dwStyle & WS_CHILD))
1038 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1039 if (!(wndPtr->dwStyle & WS_POPUP))
1040 wndPtr->dwStyle |= WS_CAPTION;
1044 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1045 * why does the user get to set it?
1048 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1049 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1050 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1051 else
1052 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1054 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1055 wndPtr->flags |= WIN_NEED_SIZE;
1057 SERVER_START_REQ( set_window_info )
1059 req->handle = hwnd;
1060 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1061 req->style = wndPtr->dwStyle;
1062 req->ex_style = wndPtr->dwExStyle;
1063 req->instance = (void *)wndPtr->hInstance;
1064 req->extra_offset = -1;
1065 wine_server_call( req );
1067 SERVER_END_REQ;
1069 /* Set the window menu */
1071 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1072 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1074 if (cs->hMenu) MENU_SetMenu(hwnd, cs->hMenu);
1075 else
1077 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1078 if (menuName)
1080 if (HIWORD(cs->hInstance))
1081 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1082 else
1083 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1085 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1089 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1090 WIN_ReleasePtr( wndPtr );
1092 if (!USER_Driver.pCreateWindow || !USER_Driver.pCreateWindow( hwnd, cs, unicode))
1094 WIN_DestroyWindow( hwnd );
1095 return 0;
1098 /* Notify the parent window only */
1100 send_parent_notify( hwnd, WM_CREATE );
1101 if (!IsWindow( hwnd )) return 0;
1103 if (cs->style & WS_VISIBLE)
1105 if (cs->style & WS_MAXIMIZE)
1106 sw = SW_SHOWMAXIMIZED;
1107 else if (cs->style & WS_MINIMIZE)
1108 sw = SW_SHOWMINIMIZED;
1110 ShowWindow( hwnd, sw );
1111 if (cs->dwExStyle & WS_EX_MDICHILD)
1113 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1114 /* ShowWindow won't activate child windows */
1115 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1119 /* Call WH_SHELL hook */
1121 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1122 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1124 TRACE("created window %p\n", hwnd);
1125 return hwnd;
1129 /***********************************************************************
1130 * CreateWindow (USER.41)
1132 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1133 DWORD style, INT16 x, INT16 y, INT16 width,
1134 INT16 height, HWND16 parent, HMENU16 menu,
1135 HINSTANCE16 instance, LPVOID data )
1137 return CreateWindowEx16( 0, className, windowName, style,
1138 x, y, width, height, parent, menu, instance, data );
1142 /***********************************************************************
1143 * CreateWindowEx (USER.452)
1145 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1146 LPCSTR windowName, DWORD style, INT16 x,
1147 INT16 y, INT16 width, INT16 height,
1148 HWND16 parent, HMENU16 menu,
1149 HINSTANCE16 instance, LPVOID data )
1151 ATOM classAtom;
1152 CREATESTRUCTA cs;
1153 char buffer[256];
1155 /* Find the class atom */
1157 if (HIWORD(className))
1159 if (!(classAtom = GlobalFindAtomA( className )))
1161 ERR( "bad class name %s\n", debugstr_a(className) );
1162 return 0;
1165 else
1167 classAtom = LOWORD(className);
1168 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1170 ERR( "bad atom %x\n", classAtom);
1171 return 0;
1173 className = buffer;
1176 /* Fix the coordinates */
1178 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1179 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1180 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1181 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1183 /* Create the window */
1185 cs.lpCreateParams = data;
1186 cs.hInstance = HINSTANCE_32(instance);
1187 cs.hMenu = HMENU_32(menu);
1188 cs.hwndParent = WIN_Handle32( parent );
1189 cs.style = style;
1190 cs.lpszName = windowName;
1191 cs.lpszClass = className;
1192 cs.dwExStyle = exStyle;
1194 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1198 /***********************************************************************
1199 * CreateWindowExA (USER32.@)
1201 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1202 LPCSTR windowName, DWORD style, INT x,
1203 INT y, INT width, INT height,
1204 HWND parent, HMENU menu,
1205 HINSTANCE instance, LPVOID data )
1207 ATOM classAtom;
1208 CREATESTRUCTA cs;
1209 char buffer[256];
1211 /* Find the class atom */
1213 if (HIWORD(className))
1215 if (!(classAtom = GlobalFindAtomA( className )))
1217 ERR( "bad class name %s\n", debugstr_a(className) );
1218 return 0;
1221 else
1223 classAtom = LOWORD(className);
1224 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1226 ERR( "bad atom %x\n", classAtom);
1227 return 0;
1229 className = buffer;
1232 /* Create the window */
1234 cs.lpCreateParams = data;
1235 cs.hInstance = instance;
1236 cs.hMenu = menu;
1237 cs.hwndParent = parent;
1238 cs.x = x;
1239 cs.y = y;
1240 cs.cx = width;
1241 cs.cy = height;
1242 cs.style = style;
1243 cs.lpszName = windowName;
1244 cs.lpszClass = className;
1245 cs.dwExStyle = exStyle;
1247 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1251 /***********************************************************************
1252 * CreateWindowExW (USER32.@)
1254 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1255 LPCWSTR windowName, DWORD style, INT x,
1256 INT y, INT width, INT height,
1257 HWND parent, HMENU menu,
1258 HINSTANCE instance, LPVOID data )
1260 ATOM classAtom;
1261 CREATESTRUCTW cs;
1262 WCHAR buffer[256];
1264 /* Find the class atom */
1266 if (HIWORD(className))
1268 if (!(classAtom = GlobalFindAtomW( className )))
1270 ERR( "bad class name %s\n", debugstr_w(className) );
1271 return 0;
1274 else
1276 classAtom = LOWORD(className);
1277 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1279 ERR( "bad atom %x\n", classAtom);
1280 return 0;
1282 className = buffer;
1285 /* Create the window */
1287 cs.lpCreateParams = data;
1288 cs.hInstance = instance;
1289 cs.hMenu = menu;
1290 cs.hwndParent = parent;
1291 cs.x = x;
1292 cs.y = y;
1293 cs.cx = width;
1294 cs.cy = height;
1295 cs.style = style;
1296 cs.lpszName = windowName;
1297 cs.lpszClass = className;
1298 cs.dwExStyle = exStyle;
1300 /* Note: we rely on the fact that CREATESTRUCTA and */
1301 /* CREATESTRUCTW have the same layout. */
1302 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1306 /***********************************************************************
1307 * WIN_SendDestroyMsg
1309 static void WIN_SendDestroyMsg( HWND hwnd )
1311 GUITHREADINFO info;
1313 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1315 if (hwnd == info.hwndCaret) DestroyCaret();
1316 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1318 if (USER_Driver.pResetSelectionOwner)
1319 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1322 * Send the WM_DESTROY to the window.
1324 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1327 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1328 * make sure that the window still exists when we come back.
1330 if (IsWindow(hwnd))
1332 HWND* pWndArray;
1333 int i;
1335 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1337 for (i = 0; pWndArray[i]; i++)
1339 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1341 HeapFree( GetProcessHeap(), 0, pWndArray );
1343 else
1344 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1348 /***********************************************************************
1349 * DestroyWindow (USER32.@)
1351 BOOL WINAPI DestroyWindow( HWND hwnd )
1353 BOOL is_child;
1355 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1357 SetLastError( ERROR_ACCESS_DENIED );
1358 return FALSE;
1361 TRACE("(%p)\n", hwnd);
1363 /* Call hooks */
1365 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1367 if (MENU_IsMenuActive() == hwnd)
1368 EndMenu();
1370 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1372 if (is_child)
1374 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1375 send_parent_notify( hwnd, WM_DESTROY );
1377 else if (!GetWindow( hwnd, GW_OWNER ))
1379 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1380 /* FIXME: clean up palette - see "Internals" p.352 */
1383 if (!IsWindow(hwnd)) return TRUE;
1385 if (USER_Driver.pResetSelectionOwner)
1386 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1388 /* Hide the window */
1389 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1391 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1392 if (is_child)
1393 ShowWindow( hwnd, SW_HIDE );
1394 else
1395 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1396 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1399 if (!IsWindow(hwnd)) return TRUE;
1401 /* Recursively destroy owned windows */
1403 if (!is_child)
1405 for (;;)
1407 int i, got_one = 0;
1408 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1409 if (list)
1411 for (i = 0; list[i]; i++)
1413 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1414 if (WIN_IsCurrentThread( list[i] ))
1416 DestroyWindow( list[i] );
1417 got_one = 1;
1418 continue;
1420 WIN_SetOwner( list[i], 0 );
1422 HeapFree( GetProcessHeap(), 0, list );
1424 if (!got_one) break;
1428 /* Send destroy messages */
1430 WIN_SendDestroyMsg( hwnd );
1431 if (!IsWindow( hwnd )) return TRUE;
1433 if (GetClipboardOwner() == hwnd)
1434 CLIPBOARD_ReleaseOwner();
1436 /* Destroy the window storage */
1438 WIN_DestroyWindow( hwnd );
1439 return TRUE;
1443 /***********************************************************************
1444 * CloseWindow (USER32.@)
1446 BOOL WINAPI CloseWindow( HWND hwnd )
1448 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1449 ShowWindow( hwnd, SW_MINIMIZE );
1450 return TRUE;
1454 /***********************************************************************
1455 * OpenIcon (USER32.@)
1457 BOOL WINAPI OpenIcon( HWND hwnd )
1459 if (!IsIconic( hwnd )) return FALSE;
1460 ShowWindow( hwnd, SW_SHOWNORMAL );
1461 return TRUE;
1465 /***********************************************************************
1466 * WIN_FindWindow
1468 * Implementation of FindWindow() and FindWindowEx().
1470 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1472 HWND *list = NULL;
1473 HWND retvalue = 0;
1474 int i = 0, len = 0;
1475 WCHAR *buffer = NULL;
1477 if (!parent) parent = GetDesktopWindow();
1478 if (title)
1480 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1481 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1484 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1486 if (child)
1488 child = WIN_GetFullHandle( child );
1489 while (list[i] && list[i] != child) i++;
1490 if (!list[i]) goto done;
1491 i++; /* start from next window */
1494 if (title)
1496 while (list[i])
1498 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1499 i++;
1502 retvalue = list[i];
1504 done:
1505 HeapFree( GetProcessHeap(), 0, list );
1506 HeapFree( GetProcessHeap(), 0, buffer );
1507 return retvalue;
1512 /***********************************************************************
1513 * FindWindowA (USER32.@)
1515 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1517 HWND ret = FindWindowExA( 0, 0, className, title );
1518 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1519 return ret;
1523 /***********************************************************************
1524 * FindWindowExA (USER32.@)
1526 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1527 LPCSTR className, LPCSTR title )
1529 ATOM atom = 0;
1530 LPWSTR buffer;
1531 HWND hwnd;
1532 INT len;
1534 if (className)
1536 /* If the atom doesn't exist, then no class */
1537 /* with this name exists either. */
1538 if (!(atom = GlobalFindAtomA( className )))
1540 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1541 return 0;
1544 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1546 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1547 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1548 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1549 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1550 HeapFree( GetProcessHeap(), 0, buffer );
1551 return hwnd;
1555 /***********************************************************************
1556 * FindWindowExW (USER32.@)
1558 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1559 LPCWSTR className, LPCWSTR title )
1561 ATOM atom = 0;
1563 if (className)
1565 /* If the atom doesn't exist, then no class */
1566 /* with this name exists either. */
1567 if (!(atom = GlobalFindAtomW( className )))
1569 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1570 return 0;
1573 return WIN_FindWindow( parent, child, atom, title );
1577 /***********************************************************************
1578 * FindWindowW (USER32.@)
1580 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1582 return FindWindowExW( 0, 0, className, title );
1586 /**********************************************************************
1587 * GetDesktopWindow (USER32.@)
1589 HWND WINAPI GetDesktopWindow(void)
1591 if (hwndDesktop) return hwndDesktop;
1592 ERR( "Wine init error: either you're trying to use an invalid native USER.EXE config, or some graphics/GUI libraries or DLLs didn't initialize properly. Aborting.\n" );
1593 ExitProcess(1);
1594 return 0;
1598 /*******************************************************************
1599 * EnableWindow (USER32.@)
1601 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1603 BOOL retvalue;
1604 HWND full_handle;
1606 if (is_broadcast(hwnd))
1608 SetLastError( ERROR_INVALID_PARAMETER );
1609 return FALSE;
1612 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1613 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1615 hwnd = full_handle;
1617 TRACE("( %p, %d )\n", hwnd, enable);
1619 retvalue = !IsWindowEnabled( hwnd );
1621 if (enable && retvalue)
1623 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1624 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1626 else if (!enable && !retvalue)
1628 HWND capture_wnd;
1630 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1632 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1634 if (hwnd == GetFocus())
1635 SetFocus( 0 ); /* A disabled window can't have the focus */
1637 capture_wnd = GetCapture();
1638 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1639 ReleaseCapture(); /* A disabled window can't capture the mouse */
1641 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1643 return retvalue;
1647 /***********************************************************************
1648 * IsWindowEnabled (USER32.@)
1650 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1652 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1656 /***********************************************************************
1657 * IsWindowUnicode (USER32.@)
1659 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1661 WND * wndPtr;
1662 BOOL retvalue;
1664 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return FALSE;
1665 if (wndPtr == WND_DESKTOP) return TRUE;
1666 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1667 WIN_ReleasePtr( wndPtr );
1668 return retvalue;
1672 /**********************************************************************
1673 * GetWindowWord (USER32.@)
1675 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1677 if (offset >= 0)
1679 WORD retvalue = 0;
1680 WND *wndPtr = WIN_GetPtr( hwnd );
1681 if (!wndPtr)
1683 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1684 return 0;
1686 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1688 SERVER_START_REQ( set_window_info )
1690 req->handle = hwnd;
1691 req->flags = 0; /* don't set anything, just retrieve */
1692 req->extra_offset = offset;
1693 req->extra_size = sizeof(retvalue);
1694 if (!wine_server_call_err( req ))
1695 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1697 SERVER_END_REQ;
1698 return retvalue;
1700 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1702 WARN("Invalid offset %d\n", offset );
1703 SetLastError( ERROR_INVALID_INDEX );
1705 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1706 WIN_ReleasePtr( wndPtr );
1707 return retvalue;
1710 switch(offset)
1712 case GWLP_HWNDPARENT:
1713 return GetWindowLongPtrW( hwnd, offset );
1714 case GWLP_ID:
1715 case GWLP_HINSTANCE:
1717 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1718 if (HIWORD(ret))
1719 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1720 return LOWORD(ret);
1722 default:
1723 WARN("Invalid offset %d\n", offset );
1724 return 0;
1729 /**********************************************************************
1730 * SetWindowWord (USER32.@)
1732 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1734 WORD retval = 0;
1735 WND * wndPtr;
1737 switch(offset)
1739 case GWLP_ID:
1740 case GWLP_HINSTANCE:
1741 case GWLP_HWNDPARENT:
1742 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1743 default:
1744 if (offset < 0)
1746 WARN("Invalid offset %d\n", offset );
1747 SetLastError( ERROR_INVALID_INDEX );
1748 return 0;
1752 wndPtr = WIN_GetPtr( hwnd );
1753 if (wndPtr == WND_DESKTOP)
1755 SetLastError( ERROR_ACCESS_DENIED );
1756 return 0;
1758 if (wndPtr == WND_OTHER_PROCESS)
1760 if (IsWindow(hwnd))
1761 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1762 offset, newval, hwnd );
1763 wndPtr = NULL;
1765 if (!wndPtr)
1767 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1768 return 0;
1771 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1773 WARN("Invalid offset %d\n", offset );
1774 WIN_ReleasePtr(wndPtr);
1775 SetLastError( ERROR_INVALID_INDEX );
1776 return 0;
1779 SERVER_START_REQ( set_window_info )
1781 req->handle = hwnd;
1782 req->flags = SET_WIN_EXTRA;
1783 req->extra_offset = offset;
1784 req->extra_size = sizeof(newval);
1785 memcpy( &req->extra_value, &newval, sizeof(newval) );
1786 if (!wine_server_call_err( req ))
1788 void *ptr = (char *)wndPtr->wExtra + offset;
1789 memcpy( &retval, ptr, sizeof(retval) );
1790 memcpy( ptr, &newval, sizeof(newval) );
1793 SERVER_END_REQ;
1794 WIN_ReleasePtr( wndPtr );
1795 return retval;
1799 /**********************************************************************
1800 * WIN_GetWindowLong
1802 * Helper function for GetWindowLong().
1804 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1806 LONG_PTR retvalue = 0;
1807 WND *wndPtr;
1809 if (offset == GWLP_HWNDPARENT)
1811 HWND parent = GetAncestor( hwnd, GA_PARENT );
1812 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1813 return (ULONG_PTR)parent;
1816 if (!(wndPtr = WIN_GetPtr( hwnd )))
1818 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1819 return 0;
1822 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1824 if (offset == GWLP_WNDPROC)
1826 SetLastError( ERROR_ACCESS_DENIED );
1827 return 0;
1829 SERVER_START_REQ( set_window_info )
1831 req->handle = hwnd;
1832 req->flags = 0; /* don't set anything, just retrieve */
1833 req->extra_offset = (offset >= 0) ? offset : -1;
1834 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1835 if (!wine_server_call_err( req ))
1837 switch(offset)
1839 case GWL_STYLE: retvalue = reply->old_style; break;
1840 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1841 case GWLP_ID: retvalue = reply->old_id; break;
1842 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1843 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1844 default:
1845 if (offset >= 0) retvalue = reply->old_extra_value;
1846 else SetLastError( ERROR_INVALID_INDEX );
1847 break;
1851 SERVER_END_REQ;
1852 return retvalue;
1855 /* now we have a valid wndPtr */
1857 if (offset >= 0)
1859 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1862 * Some programs try to access last element from 16 bit
1863 * code using illegal offset value. Hopefully this is
1864 * what those programs really expect.
1866 if (type == WIN_PROC_16 &&
1867 wndPtr->cbWndExtra >= 4 &&
1868 offset == wndPtr->cbWndExtra - sizeof(WORD))
1870 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1872 ERR( "- replaced invalid offset %d with %d\n",
1873 offset, offset2 );
1875 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset2);
1876 WIN_ReleasePtr( wndPtr );
1877 return retvalue;
1879 WARN("Invalid offset %d\n", offset );
1880 WIN_ReleasePtr( wndPtr );
1881 SetLastError( ERROR_INVALID_INDEX );
1882 return 0;
1884 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset);
1885 /* Special case for dialog window procedure */
1886 if ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1887 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, type );
1888 WIN_ReleasePtr( wndPtr );
1889 return retvalue;
1892 switch(offset)
1894 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1895 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1896 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1897 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1898 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type ); break;
1899 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1900 default:
1901 WARN("Unknown offset %d\n", offset );
1902 SetLastError( ERROR_INVALID_INDEX );
1903 break;
1905 WIN_ReleasePtr(wndPtr);
1906 return retvalue;
1910 /**********************************************************************
1911 * WIN_SetWindowLong
1913 * Helper function for SetWindowLong().
1915 * 0 is the failure code. However, in the case of failure SetLastError
1916 * must be set to distinguish between a 0 return value and a failure.
1918 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval,
1919 WINDOWPROCTYPE type )
1921 STYLESTRUCT style;
1922 BOOL ok;
1923 LONG_PTR retval = 0;
1924 WND *wndPtr;
1926 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1928 if (is_broadcast(hwnd))
1930 SetLastError( ERROR_INVALID_PARAMETER );
1931 return FALSE;
1934 if (!(wndPtr = WIN_GetPtr( hwnd )))
1936 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1937 return 0;
1939 if (wndPtr == WND_DESKTOP)
1941 /* can't change anything on the desktop window */
1942 SetLastError( ERROR_ACCESS_DENIED );
1943 return 0;
1945 if (wndPtr == WND_OTHER_PROCESS)
1947 if (offset == GWLP_WNDPROC)
1949 SetLastError( ERROR_ACCESS_DENIED );
1950 return 0;
1952 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1955 /* first some special cases */
1956 switch( offset )
1958 case GWL_STYLE:
1959 case GWL_EXSTYLE:
1960 style.styleOld =
1961 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1962 style.styleNew = newval;
1963 WIN_ReleasePtr( wndPtr );
1964 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1965 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1966 newval = style.styleNew;
1967 break;
1968 case GWLP_HWNDPARENT:
1969 if (wndPtr->parent == GetDesktopWindow())
1971 WIN_ReleasePtr( wndPtr );
1972 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1974 else
1976 WIN_ReleasePtr( wndPtr );
1977 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1979 case GWLP_WNDPROC:
1980 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type );
1981 wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, type );
1982 WIN_ReleasePtr( wndPtr );
1983 return retval;
1984 case GWLP_ID:
1985 case GWLP_HINSTANCE:
1986 case GWLP_USERDATA:
1987 break;
1988 case DWLP_DLGPROC:
1989 if ((wndPtr->cbWndExtra + sizeof(LONG_PTR) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1991 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1992 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, type );
1993 *ptr = WINPROC_AllocProc( (WNDPROC)newval, type );
1994 WIN_ReleasePtr( wndPtr );
1995 return retval;
1997 /* fall through */
1998 default:
1999 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG_PTR)))
2001 WARN("Invalid offset %d\n", offset );
2002 WIN_ReleasePtr( wndPtr );
2003 SetLastError( ERROR_INVALID_INDEX );
2004 return 0;
2006 else
2008 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
2009 if (*ptr == newval) /* already set to the same value */
2011 WIN_ReleasePtr( wndPtr );
2012 return newval;
2015 break;
2018 SERVER_START_REQ( set_window_info )
2020 req->handle = hwnd;
2021 req->extra_offset = -1;
2022 switch(offset)
2024 case GWL_STYLE:
2025 req->flags = SET_WIN_STYLE;
2026 req->style = newval;
2027 break;
2028 case GWL_EXSTYLE:
2029 req->flags = SET_WIN_EXSTYLE;
2030 req->ex_style = newval;
2031 break;
2032 case GWLP_ID:
2033 req->flags = SET_WIN_ID;
2034 req->id = newval;
2035 break;
2036 case GWLP_HINSTANCE:
2037 req->flags = SET_WIN_INSTANCE;
2038 req->instance = (void *)newval;
2039 break;
2040 case GWLP_USERDATA:
2041 req->flags = SET_WIN_USERDATA;
2042 req->user_data = (void *)newval;
2043 break;
2044 default:
2045 req->flags = SET_WIN_EXTRA;
2046 req->extra_offset = offset;
2047 req->extra_size = sizeof(newval);
2048 memcpy( &req->extra_value, &newval, sizeof(newval) );
2050 if ((ok = !wine_server_call_err( req )))
2052 switch(offset)
2054 case GWL_STYLE:
2055 wndPtr->dwStyle = newval;
2056 retval = reply->old_style;
2057 break;
2058 case GWL_EXSTYLE:
2059 wndPtr->dwExStyle = newval;
2060 retval = reply->old_ex_style;
2061 break;
2062 case GWLP_ID:
2063 wndPtr->wIDmenu = newval;
2064 retval = reply->old_id;
2065 break;
2066 case GWLP_HINSTANCE:
2067 wndPtr->hInstance = (HINSTANCE)newval;
2068 retval = (ULONG_PTR)reply->old_instance;
2069 break;
2070 case GWLP_USERDATA:
2071 wndPtr->userdata = newval;
2072 retval = (ULONG_PTR)reply->old_user_data;
2073 break;
2074 default:
2076 void *ptr = (char *)wndPtr->wExtra + offset;
2077 memcpy( &retval, ptr, sizeof(retval) );
2078 memcpy( ptr, &newval, sizeof(newval) );
2080 break;
2084 SERVER_END_REQ;
2085 WIN_ReleasePtr( wndPtr );
2087 if (!ok) return 0;
2089 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2090 USER_Driver.pSetWindowStyle( hwnd, retval );
2092 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2093 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2095 return retval;
2099 /**********************************************************************
2100 * GetWindowLong (USER.135)
2102 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2104 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2108 /**********************************************************************
2109 * GetWindowLongA (USER32.@)
2111 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2113 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2117 /**********************************************************************
2118 * GetWindowLongW (USER32.@)
2120 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2122 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2126 /**********************************************************************
2127 * SetWindowLong (USER.136)
2129 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2131 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2135 /**********************************************************************
2136 * SetWindowLongA (USER32.@)
2138 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2140 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2144 /**********************************************************************
2145 * SetWindowLongW (USER32.@) Set window attribute
2147 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2148 * value in a window's extra memory.
2150 * The _hwnd_ parameter specifies the window. is the handle to a
2151 * window that has extra memory. The _newval_ parameter contains the
2152 * new attribute or extra memory value. If positive, the _offset_
2153 * parameter is the byte-addressed location in the window's extra
2154 * memory to set. If negative, _offset_ specifies the window
2155 * attribute to set, and should be one of the following values:
2157 * GWL_EXSTYLE The window's extended window style
2159 * GWL_STYLE The window's window style.
2161 * GWLP_WNDPROC Pointer to the window's window procedure.
2163 * GWLP_HINSTANCE The window's pplication instance handle.
2165 * GWLP_ID The window's identifier.
2167 * GWLP_USERDATA The window's user-specified data.
2169 * If the window is a dialog box, the _offset_ parameter can be one of
2170 * the following values:
2172 * DWLP_DLGPROC The address of the window's dialog box procedure.
2174 * DWLP_MSGRESULT The return value of a message
2175 * that the dialog box procedure processed.
2177 * DWLP_USER Application specific information.
2179 * RETURNS
2181 * If successful, returns the previous value located at _offset_. Otherwise,
2182 * returns 0.
2184 * NOTES
2186 * Extra memory for a window class is specified by a nonzero cbWndExtra
2187 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2188 * time of class creation.
2190 * Using GWL_WNDPROC to set a new window procedure effectively creates
2191 * a window subclass. Use CallWindowProc() in the new windows procedure
2192 * to pass messages to the superclass's window procedure.
2194 * The user data is reserved for use by the application which created
2195 * the window.
2197 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2198 * instead, call the EnableWindow() function to change the window's
2199 * disabled state.
2201 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2202 * SetParent() instead.
2204 * Win95:
2205 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2206 * it sends WM_STYLECHANGING before changing the settings
2207 * and WM_STYLECHANGED afterwards.
2208 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2210 LONG WINAPI SetWindowLongW(
2211 HWND hwnd, /* [in] window to alter */
2212 INT offset, /* [in] offset, in bytes, of location to alter */
2213 LONG newval /* [in] new value of location */
2215 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2219 /*******************************************************************
2220 * GetWindowTextA (USER32.@)
2222 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2224 WCHAR *buffer;
2226 if (!lpString) return 0;
2228 if (WIN_IsCurrentProcess( hwnd ))
2229 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2231 /* when window belongs to other process, don't send a message */
2232 if (nMaxCount <= 0) return 0;
2233 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2234 get_server_window_text( hwnd, buffer, nMaxCount );
2235 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2236 lpString[nMaxCount-1] = 0;
2237 HeapFree( GetProcessHeap(), 0, buffer );
2238 return strlen(lpString);
2242 /*******************************************************************
2243 * InternalGetWindowText (USER32.@)
2245 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2247 WND *win;
2249 if (nMaxCount <= 0) return 0;
2250 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2251 if (win == WND_DESKTOP) lpString[0] = 0;
2252 else if (win != WND_OTHER_PROCESS)
2254 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2255 else lpString[0] = 0;
2256 WIN_ReleasePtr( win );
2258 else
2260 get_server_window_text( hwnd, lpString, nMaxCount );
2262 return strlenW(lpString);
2266 /*******************************************************************
2267 * GetWindowTextW (USER32.@)
2269 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2271 if (!lpString) return 0;
2273 if (WIN_IsCurrentProcess( hwnd ))
2274 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2276 /* when window belongs to other process, don't send a message */
2277 if (nMaxCount <= 0) return 0;
2278 get_server_window_text( hwnd, lpString, nMaxCount );
2279 return strlenW(lpString);
2283 /*******************************************************************
2284 * SetWindowText (USER32.@)
2285 * SetWindowTextA (USER32.@)
2287 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2289 if (is_broadcast(hwnd))
2291 SetLastError( ERROR_INVALID_PARAMETER );
2292 return FALSE;
2294 if (!WIN_IsCurrentProcess( hwnd ))
2296 FIXME( "cannot set text %s of other process window %p\n", debugstr_a(lpString), hwnd );
2297 SetLastError( ERROR_ACCESS_DENIED );
2298 return FALSE;
2300 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2304 /*******************************************************************
2305 * SetWindowTextW (USER32.@)
2307 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2309 if (is_broadcast(hwnd))
2311 SetLastError( ERROR_INVALID_PARAMETER );
2312 return FALSE;
2314 if (!WIN_IsCurrentProcess( hwnd ))
2316 FIXME( "cannot set text %s of other process window %p\n", debugstr_w(lpString), hwnd );
2317 SetLastError( ERROR_ACCESS_DENIED );
2318 return FALSE;
2320 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2324 /*******************************************************************
2325 * GetWindowTextLengthA (USER32.@)
2327 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2329 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2332 /*******************************************************************
2333 * GetWindowTextLengthW (USER32.@)
2335 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2337 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2341 /*******************************************************************
2342 * IsWindow (USER32.@)
2344 BOOL WINAPI IsWindow( HWND hwnd )
2346 WND *ptr;
2347 BOOL ret;
2349 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2350 if (ptr == WND_DESKTOP) return TRUE;
2352 if (ptr != WND_OTHER_PROCESS)
2354 WIN_ReleasePtr( ptr );
2355 return TRUE;
2358 /* check other processes */
2359 SERVER_START_REQ( get_window_info )
2361 req->handle = hwnd;
2362 ret = !wine_server_call_err( req );
2364 SERVER_END_REQ;
2365 return ret;
2369 /***********************************************************************
2370 * GetWindowThreadProcessId (USER32.@)
2372 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2374 WND *ptr;
2375 DWORD tid = 0;
2377 if (!(ptr = WIN_GetPtr( hwnd )))
2379 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2380 return 0;
2383 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2385 /* got a valid window */
2386 tid = ptr->tid;
2387 if (process) *process = GetCurrentProcessId();
2388 WIN_ReleasePtr( ptr );
2389 return tid;
2392 /* check other processes */
2393 SERVER_START_REQ( get_window_info )
2395 req->handle = hwnd;
2396 if (!wine_server_call_err( req ))
2398 tid = (DWORD)reply->tid;
2399 if (process) *process = (DWORD)reply->pid;
2402 SERVER_END_REQ;
2403 return tid;
2407 /*****************************************************************
2408 * GetParent (USER32.@)
2410 HWND WINAPI GetParent( HWND hwnd )
2412 WND *wndPtr;
2413 HWND retvalue = 0;
2415 if (!(wndPtr = WIN_GetPtr( hwnd )))
2417 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2418 return 0;
2420 if (wndPtr == WND_DESKTOP) return 0;
2421 if (wndPtr == WND_OTHER_PROCESS)
2423 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2424 if (style & (WS_POPUP | WS_CHILD))
2426 SERVER_START_REQ( get_window_tree )
2428 req->handle = hwnd;
2429 if (!wine_server_call_err( req ))
2431 if (style & WS_POPUP) retvalue = reply->owner;
2432 else if (style & WS_CHILD) retvalue = reply->parent;
2435 SERVER_END_REQ;
2438 else
2440 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2441 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2442 WIN_ReleasePtr( wndPtr );
2444 return retvalue;
2448 /*****************************************************************
2449 * GetAncestor (USER32.@)
2451 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2453 WND *win;
2454 HWND *list, ret = 0;
2456 switch(type)
2458 case GA_PARENT:
2459 if (!(win = WIN_GetPtr( hwnd )))
2461 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2462 return 0;
2464 if (win == WND_DESKTOP) return 0;
2465 if (win != WND_OTHER_PROCESS)
2467 ret = win->parent;
2468 WIN_ReleasePtr( win );
2470 else /* need to query the server */
2472 SERVER_START_REQ( get_window_tree )
2474 req->handle = hwnd;
2475 if (!wine_server_call_err( req )) ret = reply->parent;
2477 SERVER_END_REQ;
2479 break;
2481 case GA_ROOT:
2482 if (!(list = list_window_parents( hwnd ))) return 0;
2484 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2485 else
2487 int count = 2;
2488 while (list[count]) count++;
2489 ret = list[count - 2]; /* get the one before the desktop */
2491 HeapFree( GetProcessHeap(), 0, list );
2492 break;
2494 case GA_ROOTOWNER:
2495 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2496 for (;;)
2498 HWND parent = GetParent( ret );
2499 if (!parent) break;
2500 ret = parent;
2502 break;
2504 return ret;
2508 /*****************************************************************
2509 * SetParent (USER32.@)
2511 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2513 HWND full_handle;
2515 if (is_broadcast(hwnd) || is_broadcast(parent))
2517 SetLastError(ERROR_INVALID_PARAMETER);
2518 return 0;
2521 if (!parent) parent = GetDesktopWindow();
2522 else parent = WIN_GetFullHandle( parent );
2524 if (!IsWindow( parent ))
2526 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2527 return 0;
2530 /* Some applications try to set a child as a parent */
2531 if (IsChild(hwnd, parent))
2533 SetLastError( ERROR_INVALID_PARAMETER );
2534 return 0;
2537 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2538 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2540 if (USER_Driver.pSetParent)
2541 return USER_Driver.pSetParent( full_handle, parent );
2543 return 0;
2547 /*******************************************************************
2548 * IsChild (USER32.@)
2550 BOOL WINAPI IsChild( HWND parent, HWND child )
2552 HWND *list = list_window_parents( child );
2553 int i;
2554 BOOL ret;
2556 if (!list) return FALSE;
2557 parent = WIN_GetFullHandle( parent );
2558 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2559 ret = (list[i] != 0);
2560 HeapFree( GetProcessHeap(), 0, list );
2561 return ret;
2565 /***********************************************************************
2566 * IsWindowVisible (USER32.@)
2568 BOOL WINAPI IsWindowVisible( HWND hwnd )
2570 HWND *list;
2571 BOOL retval;
2572 int i;
2574 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2575 if (!(list = list_window_parents( hwnd ))) return TRUE;
2576 for (i = 0; list[i]; i++)
2577 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2578 retval = !list[i];
2579 HeapFree( GetProcessHeap(), 0, list );
2580 return retval;
2584 /***********************************************************************
2585 * WIN_IsWindowDrawable
2587 * hwnd is drawable when it is visible, all parents are not
2588 * minimized, and it is itself not minimized unless we are
2589 * trying to draw its default class icon.
2591 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2593 HWND *list;
2594 BOOL retval;
2595 int i;
2596 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2598 if (!(style & WS_VISIBLE)) return FALSE;
2599 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2601 if (!(list = list_window_parents( hwnd ))) return TRUE;
2602 for (i = 0; list[i]; i++)
2603 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2604 break;
2605 retval = !list[i];
2606 HeapFree( GetProcessHeap(), 0, list );
2607 return retval;
2611 /*******************************************************************
2612 * GetTopWindow (USER32.@)
2614 HWND WINAPI GetTopWindow( HWND hwnd )
2616 if (!hwnd) hwnd = GetDesktopWindow();
2617 return GetWindow( hwnd, GW_CHILD );
2621 /*******************************************************************
2622 * GetWindow (USER32.@)
2624 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2626 HWND retval = 0;
2628 if (rel == GW_OWNER) /* this one may be available locally */
2630 WND *wndPtr = WIN_GetPtr( hwnd );
2631 if (!wndPtr)
2633 SetLastError( ERROR_INVALID_HANDLE );
2634 return 0;
2636 if (wndPtr == WND_DESKTOP) return 0;
2637 if (wndPtr != WND_OTHER_PROCESS)
2639 retval = wndPtr->owner;
2640 WIN_ReleasePtr( wndPtr );
2641 return retval;
2643 /* else fall through to server call */
2646 SERVER_START_REQ( get_window_tree )
2648 req->handle = hwnd;
2649 if (!wine_server_call_err( req ))
2651 switch(rel)
2653 case GW_HWNDFIRST:
2654 retval = reply->first_sibling;
2655 break;
2656 case GW_HWNDLAST:
2657 retval = reply->last_sibling;
2658 break;
2659 case GW_HWNDNEXT:
2660 retval = reply->next_sibling;
2661 break;
2662 case GW_HWNDPREV:
2663 retval = reply->prev_sibling;
2664 break;
2665 case GW_OWNER:
2666 retval = reply->owner;
2667 break;
2668 case GW_CHILD:
2669 retval = reply->first_child;
2670 break;
2674 SERVER_END_REQ;
2675 return retval;
2679 /*******************************************************************
2680 * ShowOwnedPopups (USER32.@)
2682 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2684 int count = 0;
2685 WND *pWnd;
2686 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2688 if (!win_array) return TRUE;
2690 while (win_array[count]) count++;
2691 while (--count >= 0)
2693 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2694 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2695 if (pWnd == WND_OTHER_PROCESS) continue;
2697 if (pWnd->dwStyle & WS_POPUP)
2699 if (fShow)
2701 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2703 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2704 WIN_ReleasePtr( pWnd );
2705 /* In Windows, ShowOwnedPopups(TRUE) generates
2706 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2707 * regardless of the state of the owner
2709 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2710 continue;
2713 else
2715 if (pWnd->dwStyle & WS_VISIBLE)
2717 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2718 WIN_ReleasePtr( pWnd );
2719 /* In Windows, ShowOwnedPopups(FALSE) generates
2720 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2721 * regardless of the state of the owner
2723 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2724 continue;
2728 WIN_ReleasePtr( pWnd );
2730 HeapFree( GetProcessHeap(), 0, win_array );
2731 return TRUE;
2735 /*******************************************************************
2736 * GetLastActivePopup (USER32.@)
2738 HWND WINAPI GetLastActivePopup( HWND hwnd )
2740 HWND retval = hwnd;
2742 SERVER_START_REQ( get_window_info )
2744 req->handle = hwnd;
2745 if (!wine_server_call_err( req )) retval = reply->last_active;
2747 SERVER_END_REQ;
2748 return retval;
2752 /*******************************************************************
2753 * WIN_ListChildren
2755 * Build an array of the children of a given window. The array must be
2756 * freed with HeapFree. Returns NULL when no windows are found.
2758 HWND *WIN_ListChildren( HWND hwnd )
2760 return list_window_children( hwnd, 0, 0 );
2764 /*******************************************************************
2765 * EnumWindows (USER32.@)
2767 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2769 HWND *list;
2770 BOOL ret = TRUE;
2771 int i;
2773 USER_CheckNotLock();
2775 /* We have to build a list of all windows first, to avoid */
2776 /* unpleasant side-effects, for instance if the callback */
2777 /* function changes the Z-order of the windows. */
2779 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2781 /* Now call the callback function for every window */
2783 for (i = 0; list[i]; i++)
2785 /* Make sure that the window still exists */
2786 if (!IsWindow( list[i] )) continue;
2787 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2789 HeapFree( GetProcessHeap(), 0, list );
2790 return ret;
2794 /**********************************************************************
2795 * EnumThreadWindows (USER32.@)
2797 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2799 HWND *list;
2800 int i;
2802 USER_CheckNotLock();
2804 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2806 /* Now call the callback function for every window */
2808 for (i = 0; list[i]; i++)
2809 if (!func( list[i], lParam )) break;
2810 HeapFree( GetProcessHeap(), 0, list );
2811 return TRUE;
2815 /**********************************************************************
2816 * WIN_EnumChildWindows
2818 * Helper function for EnumChildWindows().
2820 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2822 HWND *childList;
2823 BOOL ret = FALSE;
2825 for ( ; *list; list++)
2827 /* Make sure that the window still exists */
2828 if (!IsWindow( *list )) continue;
2829 /* skip owned windows */
2830 if (GetWindow( *list, GW_OWNER )) continue;
2831 /* Build children list first */
2832 childList = WIN_ListChildren( *list );
2834 ret = func( *list, lParam );
2836 if (childList)
2838 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2839 HeapFree( GetProcessHeap(), 0, childList );
2841 if (!ret) return FALSE;
2843 return TRUE;
2847 /**********************************************************************
2848 * EnumChildWindows (USER32.@)
2850 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2852 HWND *list;
2854 USER_CheckNotLock();
2856 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2857 WIN_EnumChildWindows( list, func, lParam );
2858 HeapFree( GetProcessHeap(), 0, list );
2859 return TRUE;
2863 /*******************************************************************
2864 * AnyPopup (USER.52)
2866 BOOL16 WINAPI AnyPopup16(void)
2868 return AnyPopup();
2872 /*******************************************************************
2873 * AnyPopup (USER32.@)
2875 BOOL WINAPI AnyPopup(void)
2877 int i;
2878 BOOL retvalue;
2879 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2881 if (!list) return FALSE;
2882 for (i = 0; list[i]; i++)
2884 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2886 retvalue = (list[i] != 0);
2887 HeapFree( GetProcessHeap(), 0, list );
2888 return retvalue;
2892 /*******************************************************************
2893 * FlashWindow (USER32.@)
2895 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2897 WND *wndPtr;
2899 TRACE("%p\n", hWnd);
2901 if (IsIconic( hWnd ))
2903 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2905 wndPtr = WIN_GetPtr(hWnd);
2906 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2907 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2909 wndPtr->flags |= WIN_NCACTIVATED;
2911 else
2913 wndPtr->flags &= ~WIN_NCACTIVATED;
2915 WIN_ReleasePtr( wndPtr );
2916 return TRUE;
2918 else
2920 WPARAM wparam;
2922 wndPtr = WIN_GetPtr(hWnd);
2923 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2924 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2926 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2927 else wparam = (hWnd == GetForegroundWindow());
2929 WIN_ReleasePtr( wndPtr );
2930 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2931 return wparam;
2935 /*******************************************************************
2936 * FlashWindowEx (USER32.@)
2938 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
2940 FIXME("%p\n", pfwi);
2941 return TRUE;
2944 /*******************************************************************
2945 * GetWindowContextHelpId (USER32.@)
2947 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2949 DWORD retval;
2950 WND *wnd = WIN_GetPtr( hwnd );
2951 if (!wnd || wnd == WND_DESKTOP) return 0;
2952 if (wnd == WND_OTHER_PROCESS)
2954 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2955 return 0;
2957 retval = wnd->helpContext;
2958 WIN_ReleasePtr( wnd );
2959 return retval;
2963 /*******************************************************************
2964 * SetWindowContextHelpId (USER32.@)
2966 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2968 WND *wnd = WIN_GetPtr( hwnd );
2969 if (!wnd || wnd == WND_DESKTOP) return FALSE;
2970 if (wnd == WND_OTHER_PROCESS)
2972 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2973 return 0;
2975 wnd->helpContext = id;
2976 WIN_ReleasePtr( wnd );
2977 return TRUE;
2981 /*******************************************************************
2982 * DragDetect (USER32.@)
2984 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
2986 MSG msg;
2987 RECT rect;
2989 rect.left = pt.x - wDragWidth;
2990 rect.right = pt.x + wDragWidth;
2992 rect.top = pt.y - wDragHeight;
2993 rect.bottom = pt.y + wDragHeight;
2995 SetCapture(hWnd);
2997 while(1)
2999 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3001 if( msg.message == WM_LBUTTONUP )
3003 ReleaseCapture();
3004 return 0;
3006 if( msg.message == WM_MOUSEMOVE )
3008 POINT tmp;
3009 tmp.x = LOWORD(msg.lParam);
3010 tmp.y = HIWORD(msg.lParam);
3011 if( !PtInRect( &rect, tmp ))
3013 ReleaseCapture();
3014 return 1;
3018 WaitMessage();
3020 return 0;
3023 /******************************************************************************
3024 * GetWindowModuleFileNameA (USER32.@)
3026 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3028 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3029 hwnd, lpszFileName, cchFileNameMax);
3030 return 0;
3033 /******************************************************************************
3034 * GetWindowModuleFileNameW (USER32.@)
3036 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3038 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3039 hwnd, lpszFileName, cchFileNameMax);
3040 return 0;
3043 /******************************************************************************
3044 * GetWindowInfo (USER32.@)
3046 * Note: tests show that Windows doesn't check cbSize of the structure.
3048 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3050 if (!pwi) return FALSE;
3051 if (!IsWindow(hwnd)) return FALSE;
3053 GetWindowRect(hwnd, &pwi->rcWindow);
3054 GetClientRect(hwnd, &pwi->rcClient);
3055 /* translate to screen coordinates */
3056 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3058 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3059 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3060 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3062 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3063 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3065 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3066 pwi->wCreatorVersion = 0x0400;
3068 return TRUE;
3071 /******************************************************************************
3072 * SwitchDesktop (USER32.@)
3074 * NOTES: Sets the current input or interactive desktop.
3076 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3078 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3079 return TRUE;