mshtml: Added wrapper of nsIURI interface.
[wine/wine-kai.git] / dlls / user / win.c
blob237deeb90e74463ba0f33c352e420ab6af93a6c8
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 "winpos.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 /**********************************************************************/
50 static void *user_handles[NB_USER_HANDLES];
52 /***********************************************************************
53 * create_window_handle
55 * Create a window handle with the server.
57 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
58 HINSTANCE instance, WINDOWPROCTYPE type )
60 WORD index;
61 WND *win;
62 struct tagCLASS *class = NULL;
63 user_handle_t handle = 0;
64 int extra_bytes = 0;
66 /* if 16-bit instance, map to module handle */
67 if (instance && !HIWORD(instance))
68 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
70 SERVER_START_REQ( create_window )
72 req->parent = parent;
73 req->owner = owner;
74 req->atom = atom;
75 req->instance = instance;
76 if (!wine_server_call_err( req ))
78 handle = reply->handle;
79 extra_bytes = reply->extra;
80 class = reply->class_ptr;
83 SERVER_END_REQ;
85 if (!handle)
87 WARN( "error %ld creating window\n", GetLastError() );
88 return NULL;
91 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
93 SERVER_START_REQ( destroy_window )
95 req->handle = handle;
96 wine_server_call( req );
98 SERVER_END_REQ;
99 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
100 return NULL;
103 USER_Lock();
105 index = USER_HANDLE_TO_INDEX(handle);
106 assert( index < NB_USER_HANDLES );
107 user_handles[index] = win;
108 win->hwndSelf = handle;
109 win->dwMagic = WND_MAGIC;
110 win->cbWndExtra = extra_bytes;
111 memset( win->wExtra, 0, extra_bytes );
112 CLASS_AddWindow( class, win, type );
113 return win;
117 /***********************************************************************
118 * free_window_handle
120 * Free a window handle.
122 static WND *free_window_handle( HWND hwnd )
124 WND *ptr;
125 WORD index = USER_HANDLE_TO_INDEX(hwnd);
127 if (index >= NB_USER_HANDLES) return NULL;
128 USER_Lock();
129 if ((ptr = user_handles[index]))
131 SERVER_START_REQ( destroy_window )
133 req->handle = hwnd;
134 if (!wine_server_call_err( req ))
136 user_handles[index] = NULL;
137 ptr->dwMagic = 0;
139 else
140 ptr = NULL;
142 SERVER_END_REQ;
144 USER_Unlock();
145 HeapFree( GetProcessHeap(), 0, ptr );
146 return ptr;
150 /*******************************************************************
151 * list_window_children
153 * Build an array of the children of a given window. The array must be
154 * freed with HeapFree. Returns NULL when no windows are found.
156 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
158 HWND *list;
159 int size = 32;
161 for (;;)
163 int count = 0;
165 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
167 SERVER_START_REQ( get_window_children )
169 req->parent = hwnd;
170 req->atom = atom;
171 req->tid = tid;
172 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
173 if (!wine_server_call( req )) count = reply->count;
175 SERVER_END_REQ;
176 if (count && count < size)
178 list[count] = 0;
179 return list;
181 HeapFree( GetProcessHeap(), 0, list );
182 if (!count) break;
183 size = count + 1; /* restart with a large enough buffer */
185 return NULL;
189 /*******************************************************************
190 * list_window_parents
192 * Build an array of all parents of a given window, starting with
193 * the immediate parent. The array must be freed with HeapFree.
194 * Returns NULL if window is a top-level window.
196 static HWND *list_window_parents( HWND hwnd )
198 WND *win;
199 HWND current, *list;
200 int pos = 0, size = 16, count = 0;
202 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
204 current = hwnd;
205 for (;;)
207 if (!(win = WIN_GetPtr( current ))) goto empty;
208 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
209 if (win == WND_DESKTOP)
211 if (!pos) goto empty;
212 list[pos] = 0;
213 return list;
215 list[pos] = current = win->parent;
216 WIN_ReleasePtr( win );
217 if (++pos == size - 1)
219 /* need to grow the list */
220 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
221 if (!new_list) goto empty;
222 list = new_list;
223 size += 16;
227 /* at least one parent belongs to another process, have to query the server */
229 for (;;)
231 count = 0;
232 SERVER_START_REQ( get_window_parents )
234 req->handle = hwnd;
235 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
236 if (!wine_server_call( req )) count = reply->count;
238 SERVER_END_REQ;
239 if (!count) goto empty;
240 if (size > count)
242 list[count] = 0;
243 return list;
245 HeapFree( GetProcessHeap(), 0, list );
246 size = count + 1;
247 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
250 empty:
251 HeapFree( GetProcessHeap(), 0, list );
252 return NULL;
256 /*******************************************************************
257 * send_parent_notify
259 static void send_parent_notify( HWND hwnd, UINT msg )
261 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
262 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
263 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
264 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
268 /*******************************************************************
269 * get_server_window_text
271 * Retrieve the window text from the server.
273 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
275 size_t len = 0;
277 SERVER_START_REQ( get_window_text )
279 req->handle = hwnd;
280 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
281 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
283 SERVER_END_REQ;
284 text[len / sizeof(WCHAR)] = 0;
288 /***********************************************************************
289 * WIN_GetPtr
291 * Return a pointer to the WND structure if local to the process,
292 * or WND_OTHER_PROCESS if handle may be valid in other process.
293 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
295 WND *WIN_GetPtr( HWND hwnd )
297 WND * ptr;
298 WORD index = USER_HANDLE_TO_INDEX(hwnd);
300 if (index >= NB_USER_HANDLES) return NULL;
302 USER_Lock();
303 if ((ptr = user_handles[index]))
305 if (ptr->dwMagic == WND_MAGIC &&
306 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
307 return ptr;
308 ptr = NULL;
310 else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
312 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
313 else ptr = NULL;
315 else ptr = WND_OTHER_PROCESS;
316 USER_Unlock();
317 return ptr;
321 /***********************************************************************
322 * WIN_IsCurrentProcess
324 * Check whether a given window belongs to the current process (and return the full handle).
326 HWND WIN_IsCurrentProcess( HWND hwnd )
328 WND *ptr;
329 HWND ret;
331 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
332 ret = ptr->hwndSelf;
333 WIN_ReleasePtr( ptr );
334 return ret;
338 /***********************************************************************
339 * WIN_IsCurrentThread
341 * Check whether a given window belongs to the current thread (and return the full handle).
343 HWND WIN_IsCurrentThread( HWND hwnd )
345 WND *ptr;
346 HWND ret = 0;
348 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
349 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
350 WIN_ReleasePtr( ptr );
351 return ret;
355 /***********************************************************************
356 * WIN_Handle32
358 * Convert a 16-bit window handle to a full 32-bit handle.
360 HWND WIN_Handle32( HWND16 hwnd16 )
362 WND *ptr;
363 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
365 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
366 /* do sign extension for -2 and -3 */
367 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
369 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
371 if (ptr == WND_DESKTOP) return GetDesktopWindow();
373 if (ptr != WND_OTHER_PROCESS)
375 hwnd = ptr->hwndSelf;
376 WIN_ReleasePtr( ptr );
378 else /* may belong to another process */
380 SERVER_START_REQ( get_window_info )
382 req->handle = hwnd;
383 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
385 SERVER_END_REQ;
387 return hwnd;
391 /***********************************************************************
392 * WIN_SetOwner
394 * Change the owner of a window.
396 HWND WIN_SetOwner( HWND hwnd, HWND owner )
398 WND *win = WIN_GetPtr( hwnd );
399 HWND ret = 0;
401 if (!win || win == WND_DESKTOP) return 0;
402 if (win == WND_OTHER_PROCESS)
404 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
405 return 0;
407 SERVER_START_REQ( set_window_owner )
409 req->handle = hwnd;
410 req->owner = owner;
411 if (!wine_server_call( req ))
413 win->owner = reply->full_owner;
414 ret = reply->prev_owner;
417 SERVER_END_REQ;
418 WIN_ReleasePtr( win );
419 return ret;
423 /***********************************************************************
424 * WIN_SetStyle
426 * Change the style of a window.
428 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
430 BOOL ok;
431 ULONG new_style, old_style = 0;
432 WND *win = WIN_GetPtr( hwnd );
434 if (!win || win == WND_DESKTOP) return 0;
435 if (win == WND_OTHER_PROCESS)
437 if (IsWindow(hwnd))
438 ERR( "cannot set style %lx/%lx on other process window %p\n",
439 set_bits, clear_bits, hwnd );
440 return 0;
442 new_style = (win->dwStyle | set_bits) & ~clear_bits;
443 if (new_style == win->dwStyle)
445 WIN_ReleasePtr( win );
446 return new_style;
448 SERVER_START_REQ( set_window_info )
450 req->handle = hwnd;
451 req->flags = SET_WIN_STYLE;
452 req->style = new_style;
453 req->extra_offset = -1;
454 if ((ok = !wine_server_call( req )))
456 old_style = reply->old_style;
457 win->dwStyle = new_style;
460 SERVER_END_REQ;
461 WIN_ReleasePtr( win );
462 if (ok) USER_Driver->pSetWindowStyle( hwnd, old_style );
463 return old_style;
467 /***********************************************************************
468 * WIN_GetRectangles
470 * Get the window and client rectangles.
472 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
474 WND *win = WIN_GetPtr( hwnd );
475 BOOL ret = TRUE;
477 if (!win) return FALSE;
478 if (win == WND_DESKTOP)
480 RECT rect;
481 rect.left = rect.top = 0;
482 rect.right = GetSystemMetrics(SM_CXSCREEN);
483 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
484 if (rectWindow) *rectWindow = rect;
485 if (rectClient) *rectClient = rect;
487 else if (win == WND_OTHER_PROCESS)
489 SERVER_START_REQ( get_window_rectangles )
491 req->handle = hwnd;
492 if ((ret = !wine_server_call( req )))
494 if (rectWindow)
496 rectWindow->left = reply->window.left;
497 rectWindow->top = reply->window.top;
498 rectWindow->right = reply->window.right;
499 rectWindow->bottom = reply->window.bottom;
501 if (rectClient)
503 rectClient->left = reply->client.left;
504 rectClient->top = reply->client.top;
505 rectClient->right = reply->client.right;
506 rectClient->bottom = reply->client.bottom;
510 SERVER_END_REQ;
512 else
514 if (rectWindow) *rectWindow = win->rectWindow;
515 if (rectClient) *rectClient = win->rectClient;
516 WIN_ReleasePtr( win );
518 return ret;
522 /***********************************************************************
523 * WIN_DestroyWindow
525 * Destroy storage associated to a window. "Internals" p.358
527 LRESULT WIN_DestroyWindow( HWND hwnd )
529 WND *wndPtr;
530 HWND *list;
531 HMENU menu = 0, sys_menu;
533 TRACE("%p\n", hwnd );
535 /* free child windows */
536 if ((list = WIN_ListChildren( hwnd )))
538 int i;
539 for (i = 0; list[i]; i++)
541 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
542 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
544 HeapFree( GetProcessHeap(), 0, list );
547 /* Unlink now so we won't bother with the children later on */
548 SERVER_START_REQ( set_parent )
550 req->handle = hwnd;
551 req->parent = 0;
552 wine_server_call( req );
554 SERVER_END_REQ;
557 * Send the WM_NCDESTROY to the window being destroyed.
559 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
561 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
563 WINPOS_CheckInternalPos( hwnd );
565 /* free resources associated with the window */
567 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
568 if (!(wndPtr->dwStyle & WS_CHILD)) menu = (HMENU)wndPtr->wIDmenu;
569 sys_menu = wndPtr->hSysMenu;
570 WIN_ReleasePtr( wndPtr );
572 if (menu) DestroyMenu( menu );
573 if (sys_menu) DestroyMenu( sys_menu );
575 USER_Driver->pDestroyWindow( hwnd );
577 free_window_handle( hwnd );
578 return 0;
581 /***********************************************************************
582 * WIN_DestroyThreadWindows
584 * Destroy all children of 'wnd' owned by the current thread.
585 * Return TRUE if something was done.
587 void WIN_DestroyThreadWindows( HWND hwnd )
589 HWND *list;
590 int i;
592 if (!(list = WIN_ListChildren( hwnd ))) return;
593 for (i = 0; list[i]; i++)
595 if (WIN_IsCurrentThread( list[i] ))
596 DestroyWindow( list[i] );
597 else
598 WIN_DestroyThreadWindows( list[i] );
600 HeapFree( GetProcessHeap(), 0, list );
604 /***********************************************************************
605 * WIN_FixCoordinates
607 * Fix the coordinates - Helper for WIN_CreateWindowEx.
608 * returns default show mode in sw.
609 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
611 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
613 POINT pos[2];
615 if (cs->dwExStyle & WS_EX_MDICHILD)
617 UINT id = 0;
619 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
620 if (!(cs->style & WS_POPUP)) cs->hMenu = (HMENU)id;
622 TRACE("MDI child id %04x\n", id);
625 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
626 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
628 if (cs->style & (WS_CHILD | WS_POPUP))
630 if (cs->dwExStyle & WS_EX_MDICHILD)
632 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
634 cs->x = pos[0].x;
635 cs->y = pos[0].y;
637 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
638 cs->cx = pos[1].x;
639 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
640 cs->cy = pos[1].y;
642 else
644 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
645 cs->x = cs->y = 0;
646 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
647 cs->cx = cs->cy = 0;
650 else /* overlapped window */
652 STARTUPINFOW info;
654 GetStartupInfoW( &info );
656 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
658 /* Never believe Microsoft's documentation... CreateWindowEx doc says
659 * that if an overlapped window is created with WS_VISIBLE style bit
660 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
661 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
662 * reveals that
664 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
665 * 2) it does not ignore the y parameter as the docs claim; instead, it
666 * uses it as second parameter to ShowWindow() unless y is either
667 * CW_USEDEFAULT or CW_USEDEFAULT16.
669 * The fact that we didn't do 2) caused bogus windows pop up when wine
670 * was running apps that were using this obscure feature. Example -
671 * calc.exe that comes with Win98 (only Win98, it's different from
672 * the one that comes with Win95 and NT)
674 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
675 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
676 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
679 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
681 if (info.dwFlags & STARTF_USESIZE)
683 cs->cx = info.dwXSize;
684 cs->cy = info.dwYSize;
686 else /* if no other hint from the app, pick 3/4 of the screen real estate */
688 RECT r;
689 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
690 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
691 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
694 /* Handle case where only the cy values is set to default */
695 else if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16)
697 RECT r;
698 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
699 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
703 else
705 /* neither x nor cx are default. Check the y values .
706 * In the trace we see Outlook and Outlook Express using
707 * cy set to CW_USEDEFAULT when opening the address book.
709 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
710 RECT r;
711 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
712 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
713 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
718 /***********************************************************************
719 * dump_window_styles
721 static void dump_window_styles( DWORD style, DWORD exstyle )
723 TRACE( "style:" );
724 if(style & WS_POPUP) TRACE(" WS_POPUP");
725 if(style & WS_CHILD) TRACE(" WS_CHILD");
726 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
727 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
728 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
729 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
730 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
731 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
732 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
733 else
735 if(style & WS_BORDER) TRACE(" WS_BORDER");
736 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
738 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
739 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
740 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
741 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
742 if (style & WS_CHILD)
744 if(style & WS_GROUP) TRACE(" WS_GROUP");
745 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
747 else
749 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
750 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
753 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
754 #define DUMPED_STYLES \
755 (WS_POPUP | \
756 WS_CHILD | \
757 WS_MINIMIZE | \
758 WS_VISIBLE | \
759 WS_DISABLED | \
760 WS_CLIPSIBLINGS | \
761 WS_CLIPCHILDREN | \
762 WS_MAXIMIZE | \
763 WS_BORDER | \
764 WS_DLGFRAME | \
765 WS_VSCROLL | \
766 WS_HSCROLL | \
767 WS_SYSMENU | \
768 WS_THICKFRAME | \
769 WS_GROUP | \
770 WS_TABSTOP | \
771 WS_MINIMIZEBOX | \
772 WS_MAXIMIZEBOX)
774 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
775 TRACE("\n");
776 #undef DUMPED_STYLES
778 TRACE( "exstyle:" );
779 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
780 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
781 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
782 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
783 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
784 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
785 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
786 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
787 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
788 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
789 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
790 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
791 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
792 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
793 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
794 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
795 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
796 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
798 #define DUMPED_EX_STYLES \
799 (WS_EX_DLGMODALFRAME | \
800 WS_EX_DRAGDETECT | \
801 WS_EX_NOPARENTNOTIFY | \
802 WS_EX_TOPMOST | \
803 WS_EX_ACCEPTFILES | \
804 WS_EX_TRANSPARENT | \
805 WS_EX_MDICHILD | \
806 WS_EX_TOOLWINDOW | \
807 WS_EX_WINDOWEDGE | \
808 WS_EX_CLIENTEDGE | \
809 WS_EX_CONTEXTHELP | \
810 WS_EX_RIGHT | \
811 WS_EX_RTLREADING | \
812 WS_EX_LEFTSCROLLBAR | \
813 WS_EX_CONTROLPARENT | \
814 WS_EX_STATICEDGE | \
815 WS_EX_APPWINDOW | \
816 WS_EX_LAYERED)
818 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
819 TRACE("\n");
820 #undef DUMPED_EX_STYLES
824 /***********************************************************************
825 * WIN_CreateWindowEx
827 * Implementation of CreateWindowEx().
829 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
830 WINDOWPROCTYPE type )
832 INT sw = SW_SHOW;
833 WND *wndPtr;
834 HWND hwnd, parent, owner, top_child = 0;
835 BOOL unicode = (type == WIN_PROC_32W);
836 MDICREATESTRUCTA mdi_cs;
838 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
839 (type == WIN_PROC_32W) ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
840 (type == WIN_PROC_32W) ? debugstr_w((LPCWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
841 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
842 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
844 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
846 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
847 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
849 /* Fix the styles for MDI children */
850 if (cs->dwExStyle & WS_EX_MDICHILD)
852 UINT flags = 0;
854 wndPtr = WIN_GetPtr(cs->hwndParent);
855 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
857 flags = wndPtr->flags;
858 WIN_ReleasePtr(wndPtr);
861 if (!(flags & WIN_ISMDICLIENT))
863 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
864 return 0;
867 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
868 * MDICREATESTRUCT members have the originally passed values.
870 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
871 * have the same layout.
873 mdi_cs.szClass = cs->lpszClass;
874 mdi_cs.szTitle = cs->lpszName;
875 mdi_cs.hOwner = cs->hInstance;
876 mdi_cs.x = cs->x;
877 mdi_cs.y = cs->y;
878 mdi_cs.cx = cs->cx;
879 mdi_cs.cy = cs->cy;
880 mdi_cs.style = cs->style;
881 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
883 cs->lpCreateParams = (LPVOID)&mdi_cs;
885 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
887 if (cs->style & WS_POPUP)
889 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
890 return 0;
892 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
894 else
896 cs->style &= ~WS_POPUP;
897 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
898 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
901 top_child = GetWindow(cs->hwndParent, GW_CHILD);
903 if (top_child)
905 /* Restore current maximized child */
906 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
908 TRACE("Restoring current maximized child %p\n", top_child);
909 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
910 ShowWindow(top_child, SW_RESTORE);
911 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
916 /* Find the parent window */
918 parent = GetDesktopWindow();
919 owner = 0;
921 if (cs->hwndParent == HWND_MESSAGE)
923 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
924 * message window (style: WS_POPUP|WS_DISABLED)
926 FIXME("Parent is HWND_MESSAGE\n");
928 else if (cs->hwndParent)
930 /* Make sure parent is valid */
931 if (!IsWindow( cs->hwndParent ))
933 WARN("Bad parent %p\n", cs->hwndParent );
934 return 0;
936 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
937 parent = WIN_GetFullHandle(cs->hwndParent);
938 else
939 owner = GetAncestor( cs->hwndParent, GA_ROOT );
941 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
943 WARN("No parent for child window\n" );
944 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
947 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
949 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
950 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
951 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
952 cs->dwExStyle |= WS_EX_WINDOWEDGE;
953 else
954 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
956 /* Create the window structure */
958 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
960 TRACE("out of memory\n" );
961 return 0;
963 hwnd = wndPtr->hwndSelf;
965 /* Fill the window structure */
967 wndPtr->tid = GetCurrentThreadId();
968 wndPtr->owner = owner;
969 wndPtr->parent = parent;
970 wndPtr->hInstance = cs->hInstance;
971 wndPtr->text = NULL;
972 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
973 wndPtr->dwExStyle = cs->dwExStyle;
974 wndPtr->wIDmenu = 0;
975 wndPtr->helpContext = 0;
976 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
977 wndPtr->pVScroll = NULL;
978 wndPtr->pHScroll = NULL;
979 wndPtr->userdata = 0;
980 wndPtr->hIcon = 0;
981 wndPtr->hIconSmall = 0;
982 wndPtr->hSysMenu = 0;
984 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
987 * Correct the window styles.
989 * It affects only the style loaded into the WIN structure.
992 if (!(wndPtr->dwStyle & WS_CHILD))
994 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
995 if (!(wndPtr->dwStyle & WS_POPUP))
996 wndPtr->dwStyle |= WS_CAPTION;
1000 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1001 * why does the user get to set it?
1004 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1005 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1006 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1007 else
1008 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1010 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1011 wndPtr->flags |= WIN_NEED_SIZE;
1013 SERVER_START_REQ( set_window_info )
1015 req->handle = hwnd;
1016 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1017 req->style = wndPtr->dwStyle;
1018 req->ex_style = wndPtr->dwExStyle;
1019 req->instance = (void *)wndPtr->hInstance;
1020 req->is_unicode = (type == WIN_PROC_32W);
1021 req->extra_offset = -1;
1022 wine_server_call( req );
1024 SERVER_END_REQ;
1026 /* Set the window menu */
1028 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1029 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1031 if (cs->hMenu)
1033 if (!MENU_SetMenu(hwnd, cs->hMenu))
1035 WIN_ReleasePtr( wndPtr );
1036 free_window_handle( hwnd );
1037 return 0;
1040 else
1042 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1043 if (menuName)
1045 if (!cs->hInstance || HIWORD(cs->hInstance))
1046 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1047 else
1048 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1050 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1054 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1055 WIN_ReleasePtr( wndPtr );
1057 if (!USER_Driver->pCreateWindow( hwnd, cs, unicode))
1059 WIN_DestroyWindow( hwnd );
1060 return 0;
1063 /* Notify the parent window only */
1065 send_parent_notify( hwnd, WM_CREATE );
1066 if (!IsWindow( hwnd )) return 0;
1068 if (cs->style & WS_VISIBLE)
1070 if (cs->style & WS_MAXIMIZE)
1071 sw = SW_SHOW;
1072 else if (cs->style & WS_MINIMIZE)
1073 sw = SW_SHOWMINIMIZED;
1075 ShowWindow( hwnd, sw );
1076 if (cs->dwExStyle & WS_EX_MDICHILD)
1078 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1079 /* ShowWindow won't activate child windows */
1080 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1084 /* Call WH_SHELL hook */
1086 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1087 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1089 TRACE("created window %p\n", hwnd);
1090 return hwnd;
1094 /***********************************************************************
1095 * CreateWindow (USER.41)
1097 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1098 DWORD style, INT16 x, INT16 y, INT16 width,
1099 INT16 height, HWND16 parent, HMENU16 menu,
1100 HINSTANCE16 instance, LPVOID data )
1102 return CreateWindowEx16( 0, className, windowName, style,
1103 x, y, width, height, parent, menu, instance, data );
1107 /***********************************************************************
1108 * CreateWindowEx (USER.452)
1110 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1111 LPCSTR windowName, DWORD style, INT16 x,
1112 INT16 y, INT16 width, INT16 height,
1113 HWND16 parent, HMENU16 menu,
1114 HINSTANCE16 instance, LPVOID data )
1116 ATOM classAtom;
1117 CREATESTRUCTA cs;
1118 char buffer[256];
1120 /* Find the class atom */
1122 if (HIWORD(className))
1124 if (!(classAtom = GlobalFindAtomA( className )))
1126 ERR( "bad class name %s\n", debugstr_a(className) );
1127 return 0;
1130 else
1132 classAtom = LOWORD(className);
1133 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1135 ERR( "bad atom %x\n", classAtom);
1136 return 0;
1138 className = buffer;
1141 /* Fix the coordinates */
1143 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1144 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1145 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1146 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1148 /* Create the window */
1150 cs.lpCreateParams = data;
1151 cs.hInstance = HINSTANCE_32(instance);
1152 cs.hMenu = HMENU_32(menu);
1153 cs.hwndParent = WIN_Handle32( parent );
1154 cs.style = style;
1155 cs.lpszName = windowName;
1156 cs.lpszClass = className;
1157 cs.dwExStyle = exStyle;
1159 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1163 /***********************************************************************
1164 * CreateWindowExA (USER32.@)
1166 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1167 LPCSTR windowName, DWORD style, INT x,
1168 INT y, INT width, INT height,
1169 HWND parent, HMENU menu,
1170 HINSTANCE instance, LPVOID data )
1172 ATOM classAtom;
1173 CREATESTRUCTA cs;
1174 char buffer[256];
1176 /* Find the class atom */
1178 if (HIWORD(className))
1180 if (!(classAtom = GlobalFindAtomA( className )))
1182 ERR( "bad class name %s\n", debugstr_a(className) );
1183 return 0;
1186 else
1188 classAtom = LOWORD(className);
1189 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1191 ERR( "bad atom %x\n", classAtom);
1192 return 0;
1194 className = buffer;
1197 /* Create the window */
1199 cs.lpCreateParams = data;
1200 cs.hInstance = instance;
1201 cs.hMenu = menu;
1202 cs.hwndParent = parent;
1203 cs.x = x;
1204 cs.y = y;
1205 cs.cx = width;
1206 cs.cy = height;
1207 cs.style = style;
1208 cs.lpszName = windowName;
1209 cs.lpszClass = className;
1210 cs.dwExStyle = exStyle;
1212 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1216 /***********************************************************************
1217 * CreateWindowExW (USER32.@)
1219 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1220 LPCWSTR windowName, DWORD style, INT x,
1221 INT y, INT width, INT height,
1222 HWND parent, HMENU menu,
1223 HINSTANCE instance, LPVOID data )
1225 ATOM classAtom;
1226 CREATESTRUCTW cs;
1227 WCHAR buffer[256];
1229 /* Find the class atom */
1231 if (HIWORD(className))
1233 if (!(classAtom = GlobalFindAtomW( className )))
1235 ERR( "bad class name %s\n", debugstr_w(className) );
1236 return 0;
1239 else
1241 classAtom = LOWORD(className);
1242 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1244 ERR( "bad atom %x\n", classAtom);
1245 return 0;
1247 className = buffer;
1250 /* Create the window */
1252 cs.lpCreateParams = data;
1253 cs.hInstance = instance;
1254 cs.hMenu = menu;
1255 cs.hwndParent = parent;
1256 cs.x = x;
1257 cs.y = y;
1258 cs.cx = width;
1259 cs.cy = height;
1260 cs.style = style;
1261 cs.lpszName = windowName;
1262 cs.lpszClass = className;
1263 cs.dwExStyle = exStyle;
1265 /* Note: we rely on the fact that CREATESTRUCTA and */
1266 /* CREATESTRUCTW have the same layout. */
1267 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1271 /***********************************************************************
1272 * WIN_SendDestroyMsg
1274 static void WIN_SendDestroyMsg( HWND hwnd )
1276 GUITHREADINFO info;
1278 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1280 if (hwnd == info.hwndCaret) DestroyCaret();
1281 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1283 USER_Driver->pResetSelectionOwner( hwnd, TRUE );
1286 * Send the WM_DESTROY to the window.
1288 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1291 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1292 * make sure that the window still exists when we come back.
1294 if (IsWindow(hwnd))
1296 HWND* pWndArray;
1297 int i;
1299 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1301 for (i = 0; pWndArray[i]; i++)
1303 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1305 HeapFree( GetProcessHeap(), 0, pWndArray );
1307 else
1308 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1312 /***********************************************************************
1313 * DestroyWindow (USER32.@)
1315 BOOL WINAPI DestroyWindow( HWND hwnd )
1317 BOOL is_child;
1319 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1321 SetLastError( ERROR_ACCESS_DENIED );
1322 return FALSE;
1325 TRACE("(%p)\n", hwnd);
1327 /* Call hooks */
1329 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1331 if (MENU_IsMenuActive() == hwnd)
1332 EndMenu();
1334 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1336 if (is_child)
1338 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1339 send_parent_notify( hwnd, WM_DESTROY );
1341 else if (!GetWindow( hwnd, GW_OWNER ))
1343 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1344 /* FIXME: clean up palette - see "Internals" p.352 */
1347 if (!IsWindow(hwnd)) return TRUE;
1349 USER_Driver->pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1351 /* Hide the window */
1352 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1354 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1355 if (is_child)
1356 ShowWindow( hwnd, SW_HIDE );
1357 else
1358 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1359 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1362 if (!IsWindow(hwnd)) return TRUE;
1364 /* Recursively destroy owned windows */
1366 if (!is_child)
1368 for (;;)
1370 int i, got_one = 0;
1371 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1372 if (list)
1374 for (i = 0; list[i]; i++)
1376 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1377 if (WIN_IsCurrentThread( list[i] ))
1379 DestroyWindow( list[i] );
1380 got_one = 1;
1381 continue;
1383 WIN_SetOwner( list[i], 0 );
1385 HeapFree( GetProcessHeap(), 0, list );
1387 if (!got_one) break;
1391 /* Send destroy messages */
1393 WIN_SendDestroyMsg( hwnd );
1394 if (!IsWindow( hwnd )) return TRUE;
1396 if (GetClipboardOwner() == hwnd)
1397 CLIPBOARD_ReleaseOwner();
1399 /* Destroy the window storage */
1401 WIN_DestroyWindow( hwnd );
1402 return TRUE;
1406 /***********************************************************************
1407 * CloseWindow (USER32.@)
1409 BOOL WINAPI CloseWindow( HWND hwnd )
1411 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1412 ShowWindow( hwnd, SW_MINIMIZE );
1413 return TRUE;
1417 /***********************************************************************
1418 * OpenIcon (USER32.@)
1420 BOOL WINAPI OpenIcon( HWND hwnd )
1422 if (!IsIconic( hwnd )) return FALSE;
1423 ShowWindow( hwnd, SW_SHOWNORMAL );
1424 return TRUE;
1428 /***********************************************************************
1429 * WIN_FindWindow
1431 * Implementation of FindWindow() and FindWindowEx().
1433 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1435 HWND *list = NULL;
1436 HWND retvalue = 0;
1437 int i = 0, len = 0;
1438 WCHAR *buffer = NULL;
1440 if (!parent) parent = GetDesktopWindow();
1441 if (title)
1443 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1444 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1447 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1449 if (child)
1451 child = WIN_GetFullHandle( child );
1452 while (list[i] && list[i] != child) i++;
1453 if (!list[i]) goto done;
1454 i++; /* start from next window */
1457 if (title)
1459 while (list[i])
1461 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1462 i++;
1465 retvalue = list[i];
1467 done:
1468 HeapFree( GetProcessHeap(), 0, list );
1469 HeapFree( GetProcessHeap(), 0, buffer );
1470 return retvalue;
1475 /***********************************************************************
1476 * FindWindowA (USER32.@)
1478 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1480 HWND ret = FindWindowExA( 0, 0, className, title );
1481 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1482 return ret;
1486 /***********************************************************************
1487 * FindWindowExA (USER32.@)
1489 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1490 LPCSTR className, LPCSTR title )
1492 ATOM atom = 0;
1493 LPWSTR buffer;
1494 HWND hwnd;
1495 INT len;
1497 if (className)
1499 /* If the atom doesn't exist, then no class */
1500 /* with this name exists either. */
1501 if (!(atom = GlobalFindAtomA( className )))
1503 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1504 return 0;
1507 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1509 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1510 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1511 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1512 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1513 HeapFree( GetProcessHeap(), 0, buffer );
1514 return hwnd;
1518 /***********************************************************************
1519 * FindWindowExW (USER32.@)
1521 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1522 LPCWSTR className, LPCWSTR title )
1524 ATOM atom = 0;
1526 if (className)
1528 /* If the atom doesn't exist, then no class */
1529 /* with this name exists either. */
1530 if (!(atom = GlobalFindAtomW( className )))
1532 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1533 return 0;
1536 return WIN_FindWindow( parent, child, atom, title );
1540 /***********************************************************************
1541 * FindWindowW (USER32.@)
1543 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1545 return FindWindowExW( 0, 0, className, title );
1549 /**********************************************************************
1550 * GetDesktopWindow (USER32.@)
1552 HWND WINAPI GetDesktopWindow(void)
1554 struct user_thread_info *thread_info = get_user_thread_info();
1556 if (!thread_info->desktop)
1558 SERVER_START_REQ( get_desktop_window )
1560 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1562 SERVER_END_REQ;
1563 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1564 ERR( "failed to create desktop window\n" );
1566 return thread_info->desktop;
1570 /*******************************************************************
1571 * EnableWindow (USER32.@)
1573 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1575 BOOL retvalue;
1576 HWND full_handle;
1578 if (is_broadcast(hwnd))
1580 SetLastError( ERROR_INVALID_PARAMETER );
1581 return FALSE;
1584 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1585 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1587 hwnd = full_handle;
1589 TRACE("( %p, %d )\n", hwnd, enable);
1591 retvalue = !IsWindowEnabled( hwnd );
1593 if (enable && retvalue)
1595 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1596 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1598 else if (!enable && !retvalue)
1600 HWND capture_wnd;
1602 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1604 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1606 if (hwnd == GetFocus())
1607 SetFocus( 0 ); /* A disabled window can't have the focus */
1609 capture_wnd = GetCapture();
1610 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1611 ReleaseCapture(); /* A disabled window can't capture the mouse */
1613 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1615 return retvalue;
1619 /***********************************************************************
1620 * IsWindowEnabled (USER32.@)
1622 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1624 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1628 /***********************************************************************
1629 * IsWindowUnicode (USER32.@)
1631 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1633 WND * wndPtr;
1634 BOOL retvalue = FALSE;
1636 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1638 if (wndPtr == WND_DESKTOP) return TRUE;
1640 if (wndPtr != WND_OTHER_PROCESS)
1642 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1643 WIN_ReleasePtr( wndPtr );
1645 else
1647 SERVER_START_REQ( get_window_info )
1649 req->handle = hwnd;
1650 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1652 SERVER_END_REQ;
1654 return retvalue;
1658 /**********************************************************************
1659 * GetWindowWord (USER32.@)
1661 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1663 if (offset >= 0)
1665 WORD retvalue = 0;
1666 WND *wndPtr = WIN_GetPtr( hwnd );
1667 if (!wndPtr)
1669 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1670 return 0;
1672 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1674 SERVER_START_REQ( set_window_info )
1676 req->handle = hwnd;
1677 req->flags = 0; /* don't set anything, just retrieve */
1678 req->extra_offset = offset;
1679 req->extra_size = sizeof(retvalue);
1680 if (!wine_server_call_err( req ))
1681 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1683 SERVER_END_REQ;
1684 return retvalue;
1686 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1688 WARN("Invalid offset %d\n", offset );
1689 SetLastError( ERROR_INVALID_INDEX );
1691 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1692 WIN_ReleasePtr( wndPtr );
1693 return retvalue;
1696 switch(offset)
1698 case GWLP_HWNDPARENT:
1699 return GetWindowLongPtrW( hwnd, offset );
1700 case GWLP_ID:
1701 case GWLP_HINSTANCE:
1703 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1704 if (HIWORD(ret))
1705 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1706 return LOWORD(ret);
1708 default:
1709 WARN("Invalid offset %d\n", offset );
1710 return 0;
1715 /**********************************************************************
1716 * SetWindowWord (USER32.@)
1718 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1720 WORD retval = 0;
1721 WND * wndPtr;
1723 switch(offset)
1725 case GWLP_ID:
1726 case GWLP_HINSTANCE:
1727 case GWLP_HWNDPARENT:
1728 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1729 default:
1730 if (offset < 0)
1732 WARN("Invalid offset %d\n", offset );
1733 SetLastError( ERROR_INVALID_INDEX );
1734 return 0;
1738 wndPtr = WIN_GetPtr( hwnd );
1739 if (wndPtr == WND_DESKTOP)
1741 SetLastError( ERROR_ACCESS_DENIED );
1742 return 0;
1744 if (wndPtr == WND_OTHER_PROCESS)
1746 if (IsWindow(hwnd))
1747 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1748 offset, newval, hwnd );
1749 wndPtr = NULL;
1751 if (!wndPtr)
1753 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1754 return 0;
1757 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1759 WARN("Invalid offset %d\n", offset );
1760 WIN_ReleasePtr(wndPtr);
1761 SetLastError( ERROR_INVALID_INDEX );
1762 return 0;
1765 SERVER_START_REQ( set_window_info )
1767 req->handle = hwnd;
1768 req->flags = SET_WIN_EXTRA;
1769 req->extra_offset = offset;
1770 req->extra_size = sizeof(newval);
1771 memcpy( &req->extra_value, &newval, sizeof(newval) );
1772 if (!wine_server_call_err( req ))
1774 void *ptr = (char *)wndPtr->wExtra + offset;
1775 memcpy( &retval, ptr, sizeof(retval) );
1776 memcpy( ptr, &newval, sizeof(newval) );
1779 SERVER_END_REQ;
1780 WIN_ReleasePtr( wndPtr );
1781 return retval;
1785 /**********************************************************************
1786 * WIN_GetWindowLong
1788 * Helper function for GetWindowLong().
1790 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1792 LONG_PTR retvalue = 0;
1793 WND *wndPtr;
1795 if (offset == GWLP_HWNDPARENT)
1797 HWND parent = GetAncestor( hwnd, GA_PARENT );
1798 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1799 return (ULONG_PTR)parent;
1802 if (!(wndPtr = WIN_GetPtr( hwnd )))
1804 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1805 return 0;
1808 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1810 if (offset == GWLP_WNDPROC)
1812 SetLastError( ERROR_ACCESS_DENIED );
1813 return 0;
1815 SERVER_START_REQ( set_window_info )
1817 req->handle = hwnd;
1818 req->flags = 0; /* don't set anything, just retrieve */
1819 req->extra_offset = (offset >= 0) ? offset : -1;
1820 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1821 if (!wine_server_call_err( req ))
1823 switch(offset)
1825 case GWL_STYLE: retvalue = reply->old_style; break;
1826 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1827 case GWLP_ID: retvalue = reply->old_id; break;
1828 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1829 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1830 default:
1831 if (offset >= 0) retvalue = reply->old_extra_value;
1832 else SetLastError( ERROR_INVALID_INDEX );
1833 break;
1837 SERVER_END_REQ;
1838 return retvalue;
1841 /* now we have a valid wndPtr */
1843 if (offset >= 0)
1845 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1848 * Some programs try to access last element from 16 bit
1849 * code using illegal offset value. Hopefully this is
1850 * what those programs really expect.
1852 if (type == WIN_PROC_16 &&
1853 wndPtr->cbWndExtra >= 4 &&
1854 offset == wndPtr->cbWndExtra - sizeof(WORD))
1856 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1858 ERR( "- replaced invalid offset %d with %d\n",
1859 offset, offset2 );
1861 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset2);
1862 WIN_ReleasePtr( wndPtr );
1863 return retvalue;
1865 WARN("Invalid offset %d\n", offset );
1866 WIN_ReleasePtr( wndPtr );
1867 SetLastError( ERROR_INVALID_INDEX );
1868 return 0;
1870 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset);
1871 /* Special case for dialog window procedure */
1872 if ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1873 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, type );
1874 WIN_ReleasePtr( wndPtr );
1875 return retvalue;
1878 switch(offset)
1880 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1881 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1882 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1883 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1884 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type ); break;
1885 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1886 default:
1887 WARN("Unknown offset %d\n", offset );
1888 SetLastError( ERROR_INVALID_INDEX );
1889 break;
1891 WIN_ReleasePtr(wndPtr);
1892 return retvalue;
1896 /**********************************************************************
1897 * WIN_SetWindowLong
1899 * Helper function for SetWindowLong().
1901 * 0 is the failure code. However, in the case of failure SetLastError
1902 * must be set to distinguish between a 0 return value and a failure.
1904 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval,
1905 WINDOWPROCTYPE type )
1907 STYLESTRUCT style;
1908 BOOL ok;
1909 LONG_PTR retval = 0;
1910 WND *wndPtr;
1912 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1914 if (is_broadcast(hwnd))
1916 SetLastError( ERROR_INVALID_PARAMETER );
1917 return FALSE;
1920 if (!(wndPtr = WIN_GetPtr( hwnd )))
1922 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1923 return 0;
1925 if (wndPtr == WND_DESKTOP)
1927 /* can't change anything on the desktop window */
1928 SetLastError( ERROR_ACCESS_DENIED );
1929 return 0;
1931 if (wndPtr == WND_OTHER_PROCESS)
1933 if (offset == GWLP_WNDPROC)
1935 SetLastError( ERROR_ACCESS_DENIED );
1936 return 0;
1938 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1941 /* first some special cases */
1942 switch( offset )
1944 case GWL_STYLE:
1945 case GWL_EXSTYLE:
1946 style.styleOld =
1947 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1948 style.styleNew = newval;
1949 WIN_ReleasePtr( wndPtr );
1950 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1951 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1952 newval = style.styleNew;
1953 break;
1954 case GWLP_HWNDPARENT:
1955 if (wndPtr->parent == GetDesktopWindow())
1957 WIN_ReleasePtr( wndPtr );
1958 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1960 else
1962 WIN_ReleasePtr( wndPtr );
1963 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1965 case GWLP_WNDPROC:
1967 WINDOWPROCTYPE old_type = WINPROC_GetProcType( wndPtr->winproc );
1968 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type );
1969 wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, type );
1970 if (old_type == type)
1972 WIN_ReleasePtr( wndPtr );
1973 return retval;
1975 /* update is_unicode flag on the server side */
1976 break;
1978 case GWLP_ID:
1979 case GWLP_HINSTANCE:
1980 case GWLP_USERDATA:
1981 break;
1982 case DWLP_DLGPROC:
1983 if ((wndPtr->cbWndExtra + sizeof(LONG_PTR) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1985 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1986 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, type );
1987 *ptr = WINPROC_AllocProc( (WNDPROC)newval, type );
1988 WIN_ReleasePtr( wndPtr );
1989 return retval;
1991 /* fall through */
1992 default:
1993 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG_PTR)))
1995 WARN("Invalid offset %d\n", offset );
1996 WIN_ReleasePtr( wndPtr );
1997 SetLastError( ERROR_INVALID_INDEX );
1998 return 0;
2000 else
2002 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
2003 if (*ptr == newval) /* already set to the same value */
2005 WIN_ReleasePtr( wndPtr );
2006 return newval;
2009 break;
2012 SERVER_START_REQ( set_window_info )
2014 req->handle = hwnd;
2015 req->extra_offset = -1;
2016 switch(offset)
2018 case GWL_STYLE:
2019 req->flags = SET_WIN_STYLE;
2020 req->style = newval;
2021 break;
2022 case GWL_EXSTYLE:
2023 req->flags = SET_WIN_EXSTYLE;
2024 req->ex_style = newval;
2025 break;
2026 case GWLP_ID:
2027 req->flags = SET_WIN_ID;
2028 req->id = newval;
2029 break;
2030 case GWLP_HINSTANCE:
2031 req->flags = SET_WIN_INSTANCE;
2032 req->instance = (void *)newval;
2033 break;
2034 case GWLP_WNDPROC:
2035 req->flags = SET_WIN_UNICODE;
2036 req->is_unicode = (type == WIN_PROC_32W);
2037 break;
2038 case GWLP_USERDATA:
2039 req->flags = SET_WIN_USERDATA;
2040 req->user_data = (void *)newval;
2041 break;
2042 default:
2043 req->flags = SET_WIN_EXTRA;
2044 req->extra_offset = offset;
2045 req->extra_size = sizeof(newval);
2046 memcpy( &req->extra_value, &newval, sizeof(newval) );
2048 if ((ok = !wine_server_call_err( req )))
2050 switch(offset)
2052 case GWL_STYLE:
2053 wndPtr->dwStyle = newval;
2054 retval = reply->old_style;
2055 break;
2056 case GWL_EXSTYLE:
2057 wndPtr->dwExStyle = newval;
2058 retval = reply->old_ex_style;
2059 break;
2060 case GWLP_ID:
2061 wndPtr->wIDmenu = newval;
2062 retval = reply->old_id;
2063 break;
2064 case GWLP_HINSTANCE:
2065 wndPtr->hInstance = (HINSTANCE)newval;
2066 retval = (ULONG_PTR)reply->old_instance;
2067 break;
2068 case GWLP_WNDPROC:
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( hwnd, retval );
2091 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2092 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2094 return retval;
2098 /**********************************************************************
2099 * GetWindowLong (USER.135)
2101 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2103 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2107 /**********************************************************************
2108 * GetWindowLongA (USER32.@)
2110 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2112 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2116 /**********************************************************************
2117 * GetWindowLongW (USER32.@)
2119 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2121 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2125 /**********************************************************************
2126 * SetWindowLong (USER.136)
2128 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2130 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2134 /**********************************************************************
2135 * SetWindowLongA (USER32.@)
2137 * See SetWindowLongW.
2139 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2141 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2145 /**********************************************************************
2146 * SetWindowLongW (USER32.@) Set window attribute
2148 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2149 * value in a window's extra memory.
2151 * The _hwnd_ parameter specifies the window. is the handle to a
2152 * window that has extra memory. The _newval_ parameter contains the
2153 * new attribute or extra memory value. If positive, the _offset_
2154 * parameter is the byte-addressed location in the window's extra
2155 * memory to set. If negative, _offset_ specifies the window
2156 * attribute to set, and should be one of the following values:
2158 * GWL_EXSTYLE The window's extended window style
2160 * GWL_STYLE The window's window style.
2162 * GWLP_WNDPROC Pointer to the window's window procedure.
2164 * GWLP_HINSTANCE The window's pplication instance handle.
2166 * GWLP_ID The window's identifier.
2168 * GWLP_USERDATA The window's user-specified data.
2170 * If the window is a dialog box, the _offset_ parameter can be one of
2171 * the following values:
2173 * DWLP_DLGPROC The address of the window's dialog box procedure.
2175 * DWLP_MSGRESULT The return value of a message
2176 * that the dialog box procedure processed.
2178 * DWLP_USER Application specific information.
2180 * RETURNS
2182 * If successful, returns the previous value located at _offset_. Otherwise,
2183 * returns 0.
2185 * NOTES
2187 * Extra memory for a window class is specified by a nonzero cbWndExtra
2188 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2189 * time of class creation.
2191 * Using GWL_WNDPROC to set a new window procedure effectively creates
2192 * a window subclass. Use CallWindowProc() in the new windows procedure
2193 * to pass messages to the superclass's window procedure.
2195 * The user data is reserved for use by the application which created
2196 * the window.
2198 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2199 * instead, call the EnableWindow() function to change the window's
2200 * disabled state.
2202 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2203 * SetParent() instead.
2205 * Win95:
2206 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2207 * it sends WM_STYLECHANGING before changing the settings
2208 * and WM_STYLECHANGED afterwards.
2209 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2211 LONG WINAPI SetWindowLongW(
2212 HWND hwnd, /* [in] window to alter */
2213 INT offset, /* [in] offset, in bytes, of location to alter */
2214 LONG newval /* [in] new value of location */
2216 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2220 /*******************************************************************
2221 * GetWindowTextA (USER32.@)
2223 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2225 WCHAR *buffer;
2227 if (!lpString) return 0;
2229 if (WIN_IsCurrentProcess( hwnd ))
2230 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2232 /* when window belongs to other process, don't send a message */
2233 if (nMaxCount <= 0) return 0;
2234 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2235 get_server_window_text( hwnd, buffer, nMaxCount );
2236 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2237 lpString[nMaxCount-1] = 0;
2238 HeapFree( GetProcessHeap(), 0, buffer );
2239 return strlen(lpString);
2243 /*******************************************************************
2244 * InternalGetWindowText (USER32.@)
2246 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2248 WND *win;
2250 if (nMaxCount <= 0) return 0;
2251 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2252 if (win == WND_DESKTOP) lpString[0] = 0;
2253 else if (win != WND_OTHER_PROCESS)
2255 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2256 else lpString[0] = 0;
2257 WIN_ReleasePtr( win );
2259 else
2261 get_server_window_text( hwnd, lpString, nMaxCount );
2263 return strlenW(lpString);
2267 /*******************************************************************
2268 * GetWindowTextW (USER32.@)
2270 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2272 if (!lpString) return 0;
2274 if (WIN_IsCurrentProcess( hwnd ))
2275 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2277 /* when window belongs to other process, don't send a message */
2278 if (nMaxCount <= 0) return 0;
2279 get_server_window_text( hwnd, lpString, nMaxCount );
2280 return strlenW(lpString);
2284 /*******************************************************************
2285 * SetWindowTextA (USER32.@)
2286 * SetWindowText (USER32.@)
2288 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2290 if (is_broadcast(hwnd))
2292 SetLastError( ERROR_INVALID_PARAMETER );
2293 return FALSE;
2295 if (!WIN_IsCurrentProcess( hwnd ))
2296 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2297 debugstr_a(lpString), hwnd );
2298 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2302 /*******************************************************************
2303 * SetWindowTextW (USER32.@)
2305 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2307 if (is_broadcast(hwnd))
2309 SetLastError( ERROR_INVALID_PARAMETER );
2310 return FALSE;
2312 if (!WIN_IsCurrentProcess( hwnd ))
2313 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2314 debugstr_w(lpString), hwnd );
2315 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2319 /*******************************************************************
2320 * GetWindowTextLengthA (USER32.@)
2322 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2324 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2327 /*******************************************************************
2328 * GetWindowTextLengthW (USER32.@)
2330 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2332 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2336 /*******************************************************************
2337 * IsWindow (USER32.@)
2339 BOOL WINAPI IsWindow( HWND hwnd )
2341 WND *ptr;
2342 BOOL ret;
2344 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2345 if (ptr == WND_DESKTOP) return TRUE;
2347 if (ptr != WND_OTHER_PROCESS)
2349 WIN_ReleasePtr( ptr );
2350 return TRUE;
2353 /* check other processes */
2354 SERVER_START_REQ( get_window_info )
2356 req->handle = hwnd;
2357 ret = !wine_server_call_err( req );
2359 SERVER_END_REQ;
2360 return ret;
2364 /***********************************************************************
2365 * GetWindowThreadProcessId (USER32.@)
2367 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2369 WND *ptr;
2370 DWORD tid = 0;
2372 if (!(ptr = WIN_GetPtr( hwnd )))
2374 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2375 return 0;
2378 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2380 /* got a valid window */
2381 tid = ptr->tid;
2382 if (process) *process = GetCurrentProcessId();
2383 WIN_ReleasePtr( ptr );
2384 return tid;
2387 /* check other processes */
2388 SERVER_START_REQ( get_window_info )
2390 req->handle = hwnd;
2391 if (!wine_server_call_err( req ))
2393 tid = (DWORD)reply->tid;
2394 if (process) *process = (DWORD)reply->pid;
2397 SERVER_END_REQ;
2398 return tid;
2402 /*****************************************************************
2403 * GetParent (USER32.@)
2405 HWND WINAPI GetParent( HWND hwnd )
2407 WND *wndPtr;
2408 HWND retvalue = 0;
2410 if (!(wndPtr = WIN_GetPtr( hwnd )))
2412 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2413 return 0;
2415 if (wndPtr == WND_DESKTOP) return 0;
2416 if (wndPtr == WND_OTHER_PROCESS)
2418 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2419 if (style & (WS_POPUP | WS_CHILD))
2421 SERVER_START_REQ( get_window_tree )
2423 req->handle = hwnd;
2424 if (!wine_server_call_err( req ))
2426 if (style & WS_POPUP) retvalue = reply->owner;
2427 else if (style & WS_CHILD) retvalue = reply->parent;
2430 SERVER_END_REQ;
2433 else
2435 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2436 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2437 WIN_ReleasePtr( wndPtr );
2439 return retvalue;
2443 /*****************************************************************
2444 * GetAncestor (USER32.@)
2446 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2448 WND *win;
2449 HWND *list, ret = 0;
2451 switch(type)
2453 case GA_PARENT:
2454 if (!(win = WIN_GetPtr( hwnd )))
2456 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2457 return 0;
2459 if (win == WND_DESKTOP) return 0;
2460 if (win != WND_OTHER_PROCESS)
2462 ret = win->parent;
2463 WIN_ReleasePtr( win );
2465 else /* need to query the server */
2467 SERVER_START_REQ( get_window_tree )
2469 req->handle = hwnd;
2470 if (!wine_server_call_err( req )) ret = reply->parent;
2472 SERVER_END_REQ;
2474 break;
2476 case GA_ROOT:
2477 if (!(list = list_window_parents( hwnd ))) return 0;
2479 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2480 else
2482 int count = 2;
2483 while (list[count]) count++;
2484 ret = list[count - 2]; /* get the one before the desktop */
2486 HeapFree( GetProcessHeap(), 0, list );
2487 break;
2489 case GA_ROOTOWNER:
2490 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2491 for (;;)
2493 HWND parent = GetParent( ret );
2494 if (!parent) break;
2495 ret = parent;
2497 break;
2499 return ret;
2503 /*****************************************************************
2504 * SetParent (USER32.@)
2506 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2508 HWND full_handle;
2510 if (is_broadcast(hwnd) || is_broadcast(parent))
2512 SetLastError(ERROR_INVALID_PARAMETER);
2513 return 0;
2516 if (!parent) parent = GetDesktopWindow();
2517 else parent = WIN_GetFullHandle( parent );
2519 if (!IsWindow( parent ))
2521 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2522 return 0;
2525 /* Some applications try to set a child as a parent */
2526 if (IsChild(hwnd, parent))
2528 SetLastError( ERROR_INVALID_PARAMETER );
2529 return 0;
2532 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2533 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2535 return USER_Driver->pSetParent( full_handle, parent );
2539 /*******************************************************************
2540 * IsChild (USER32.@)
2542 BOOL WINAPI IsChild( HWND parent, HWND child )
2544 HWND *list = list_window_parents( child );
2545 int i;
2546 BOOL ret;
2548 if (!list) return FALSE;
2549 parent = WIN_GetFullHandle( parent );
2550 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2551 ret = (list[i] != 0);
2552 HeapFree( GetProcessHeap(), 0, list );
2553 return ret;
2557 /***********************************************************************
2558 * IsWindowVisible (USER32.@)
2560 BOOL WINAPI IsWindowVisible( HWND hwnd )
2562 HWND *list;
2563 BOOL retval;
2564 int i;
2566 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2567 if (!(list = list_window_parents( hwnd ))) return TRUE;
2568 for (i = 0; list[i]; i++)
2569 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2570 retval = !list[i];
2571 HeapFree( GetProcessHeap(), 0, list );
2572 return retval;
2576 /***********************************************************************
2577 * WIN_IsWindowDrawable
2579 * hwnd is drawable when it is visible, all parents are not
2580 * minimized, and it is itself not minimized unless we are
2581 * trying to draw its default class icon.
2583 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2585 HWND *list;
2586 BOOL retval;
2587 int i;
2588 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2590 if (!(style & WS_VISIBLE)) return FALSE;
2591 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2593 if (!(list = list_window_parents( hwnd ))) return TRUE;
2594 for (i = 0; list[i]; i++)
2595 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2596 break;
2597 retval = !list[i];
2598 HeapFree( GetProcessHeap(), 0, list );
2599 return retval;
2603 /*******************************************************************
2604 * GetTopWindow (USER32.@)
2606 HWND WINAPI GetTopWindow( HWND hwnd )
2608 if (!hwnd) hwnd = GetDesktopWindow();
2609 return GetWindow( hwnd, GW_CHILD );
2613 /*******************************************************************
2614 * GetWindow (USER32.@)
2616 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2618 HWND retval = 0;
2620 if (rel == GW_OWNER) /* this one may be available locally */
2622 WND *wndPtr = WIN_GetPtr( hwnd );
2623 if (!wndPtr)
2625 SetLastError( ERROR_INVALID_HANDLE );
2626 return 0;
2628 if (wndPtr == WND_DESKTOP) return 0;
2629 if (wndPtr != WND_OTHER_PROCESS)
2631 retval = wndPtr->owner;
2632 WIN_ReleasePtr( wndPtr );
2633 return retval;
2635 /* else fall through to server call */
2638 SERVER_START_REQ( get_window_tree )
2640 req->handle = hwnd;
2641 if (!wine_server_call_err( req ))
2643 switch(rel)
2645 case GW_HWNDFIRST:
2646 retval = reply->first_sibling;
2647 break;
2648 case GW_HWNDLAST:
2649 retval = reply->last_sibling;
2650 break;
2651 case GW_HWNDNEXT:
2652 retval = reply->next_sibling;
2653 break;
2654 case GW_HWNDPREV:
2655 retval = reply->prev_sibling;
2656 break;
2657 case GW_OWNER:
2658 retval = reply->owner;
2659 break;
2660 case GW_CHILD:
2661 retval = reply->first_child;
2662 break;
2666 SERVER_END_REQ;
2667 return retval;
2671 /*******************************************************************
2672 * ShowOwnedPopups (USER32.@)
2674 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2676 int count = 0;
2677 WND *pWnd;
2678 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2680 if (!win_array) return TRUE;
2682 while (win_array[count]) count++;
2683 while (--count >= 0)
2685 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2686 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2687 if (pWnd == WND_OTHER_PROCESS) continue;
2688 if (fShow)
2690 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2692 WIN_ReleasePtr( pWnd );
2693 /* In Windows, ShowOwnedPopups(TRUE) generates
2694 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2695 * regardless of the state of the owner
2697 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2698 continue;
2701 else
2703 if (pWnd->dwStyle & WS_VISIBLE)
2705 WIN_ReleasePtr( pWnd );
2706 /* In Windows, ShowOwnedPopups(FALSE) generates
2707 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2708 * regardless of the state of the owner
2710 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2711 continue;
2714 WIN_ReleasePtr( pWnd );
2716 HeapFree( GetProcessHeap(), 0, win_array );
2717 return TRUE;
2721 /*******************************************************************
2722 * GetLastActivePopup (USER32.@)
2724 HWND WINAPI GetLastActivePopup( HWND hwnd )
2726 HWND retval = hwnd;
2728 SERVER_START_REQ( get_window_info )
2730 req->handle = hwnd;
2731 if (!wine_server_call_err( req )) retval = reply->last_active;
2733 SERVER_END_REQ;
2734 return retval;
2738 /*******************************************************************
2739 * WIN_ListChildren
2741 * Build an array of the children of a given window. The array must be
2742 * freed with HeapFree. Returns NULL when no windows are found.
2744 HWND *WIN_ListChildren( HWND hwnd )
2746 return list_window_children( hwnd, 0, 0 );
2750 /*******************************************************************
2751 * EnumWindows (USER32.@)
2753 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2755 HWND *list;
2756 BOOL ret = TRUE;
2757 int i;
2759 USER_CheckNotLock();
2761 /* We have to build a list of all windows first, to avoid */
2762 /* unpleasant side-effects, for instance if the callback */
2763 /* function changes the Z-order of the windows. */
2765 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2767 /* Now call the callback function for every window */
2769 for (i = 0; list[i]; i++)
2771 /* Make sure that the window still exists */
2772 if (!IsWindow( list[i] )) continue;
2773 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2775 HeapFree( GetProcessHeap(), 0, list );
2776 return ret;
2780 /**********************************************************************
2781 * EnumThreadWindows (USER32.@)
2783 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2785 HWND *list;
2786 int i;
2788 USER_CheckNotLock();
2790 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2792 /* Now call the callback function for every window */
2794 for (i = 0; list[i]; i++)
2795 if (!func( list[i], lParam )) break;
2796 HeapFree( GetProcessHeap(), 0, list );
2797 return TRUE;
2801 /**********************************************************************
2802 * WIN_EnumChildWindows
2804 * Helper function for EnumChildWindows().
2806 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2808 HWND *childList;
2809 BOOL ret = FALSE;
2811 for ( ; *list; list++)
2813 /* Make sure that the window still exists */
2814 if (!IsWindow( *list )) continue;
2815 /* Build children list first */
2816 childList = WIN_ListChildren( *list );
2818 ret = func( *list, lParam );
2820 if (childList)
2822 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2823 HeapFree( GetProcessHeap(), 0, childList );
2825 if (!ret) return FALSE;
2827 return TRUE;
2831 /**********************************************************************
2832 * EnumChildWindows (USER32.@)
2834 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2836 HWND *list;
2837 BOOL ret;
2839 USER_CheckNotLock();
2841 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2842 ret = WIN_EnumChildWindows( list, func, lParam );
2843 HeapFree( GetProcessHeap(), 0, list );
2844 return ret;
2848 /*******************************************************************
2849 * AnyPopup (USER.52)
2851 BOOL16 WINAPI AnyPopup16(void)
2853 return AnyPopup();
2857 /*******************************************************************
2858 * AnyPopup (USER32.@)
2860 BOOL WINAPI AnyPopup(void)
2862 int i;
2863 BOOL retvalue;
2864 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2866 if (!list) return FALSE;
2867 for (i = 0; list[i]; i++)
2869 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2871 retvalue = (list[i] != 0);
2872 HeapFree( GetProcessHeap(), 0, list );
2873 return retvalue;
2877 /*******************************************************************
2878 * FlashWindow (USER32.@)
2880 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2882 WND *wndPtr;
2884 TRACE("%p\n", hWnd);
2886 if (IsIconic( hWnd ))
2888 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2890 wndPtr = WIN_GetPtr(hWnd);
2891 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2892 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2894 wndPtr->flags |= WIN_NCACTIVATED;
2896 else
2898 wndPtr->flags &= ~WIN_NCACTIVATED;
2900 WIN_ReleasePtr( wndPtr );
2901 return TRUE;
2903 else
2905 WPARAM wparam;
2907 wndPtr = WIN_GetPtr(hWnd);
2908 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2909 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2911 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2912 else wparam = (hWnd == GetForegroundWindow());
2914 WIN_ReleasePtr( wndPtr );
2915 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2916 return wparam;
2920 /*******************************************************************
2921 * FlashWindowEx (USER32.@)
2923 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
2925 FIXME("%p\n", pfwi);
2926 return TRUE;
2929 /*******************************************************************
2930 * GetWindowContextHelpId (USER32.@)
2932 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2934 DWORD retval;
2935 WND *wnd = WIN_GetPtr( hwnd );
2936 if (!wnd || wnd == WND_DESKTOP) return 0;
2937 if (wnd == WND_OTHER_PROCESS)
2939 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2940 return 0;
2942 retval = wnd->helpContext;
2943 WIN_ReleasePtr( wnd );
2944 return retval;
2948 /*******************************************************************
2949 * SetWindowContextHelpId (USER32.@)
2951 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2953 WND *wnd = WIN_GetPtr( hwnd );
2954 if (!wnd || wnd == WND_DESKTOP) return FALSE;
2955 if (wnd == WND_OTHER_PROCESS)
2957 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2958 return 0;
2960 wnd->helpContext = id;
2961 WIN_ReleasePtr( wnd );
2962 return TRUE;
2966 /*******************************************************************
2967 * DragDetect (USER32.@)
2969 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
2971 MSG msg;
2972 RECT rect;
2973 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
2974 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
2976 rect.left = pt.x - wDragWidth;
2977 rect.right = pt.x + wDragWidth;
2979 rect.top = pt.y - wDragHeight;
2980 rect.bottom = pt.y + wDragHeight;
2982 SetCapture(hWnd);
2984 while(1)
2986 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
2988 if( msg.message == WM_LBUTTONUP )
2990 ReleaseCapture();
2991 return 0;
2993 if( msg.message == WM_MOUSEMOVE )
2995 POINT tmp;
2996 tmp.x = LOWORD(msg.lParam);
2997 tmp.y = HIWORD(msg.lParam);
2998 if( !PtInRect( &rect, tmp ))
3000 ReleaseCapture();
3001 return 1;
3005 WaitMessage();
3007 return 0;
3010 /******************************************************************************
3011 * GetWindowModuleFileNameA (USER32.@)
3013 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3015 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3016 hwnd, lpszFileName, cchFileNameMax);
3017 return 0;
3020 /******************************************************************************
3021 * GetWindowModuleFileNameW (USER32.@)
3023 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3025 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3026 hwnd, lpszFileName, cchFileNameMax);
3027 return 0;
3030 /******************************************************************************
3031 * GetWindowInfo (USER32.@)
3033 * Note: tests show that Windows doesn't check cbSize of the structure.
3035 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3037 if (!pwi) return FALSE;
3038 if (!IsWindow(hwnd)) return FALSE;
3040 GetWindowRect(hwnd, &pwi->rcWindow);
3041 GetClientRect(hwnd, &pwi->rcClient);
3042 /* translate to screen coordinates */
3043 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3045 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3046 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3047 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3049 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3050 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3052 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3053 pwi->wCreatorVersion = 0x0400;
3055 return TRUE;
3058 /******************************************************************************
3059 * SwitchDesktop (USER32.@)
3061 * NOTES: Sets the current input or interactive desktop.
3063 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3065 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3066 return TRUE;
3069 /*****************************************************************************
3070 * SetLayeredWindowAttributes (USER32.@)
3072 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3073 BYTE bAlpha, DWORD dwFlags )
3075 FIXME("(%p,0x%.8lx,%d,%ld): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3076 return TRUE;
3079 /*****************************************************************************
3080 * UpdateLayeredWindow (USER32.@)
3082 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3083 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3084 DWORD dwFlags)
3086 FIXME("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%ld): stub!\n",
3087 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3088 return 0;