gdi: Write out glyph count correctly in GetCharacterPlacementA.
[wine/multimedia.git] / dlls / user / win.c
blob10a1a4fec2bc3bee2599f123f6b463064c472e0e
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 HWND full_parent = 0, full_owner = 0;
63 struct tagCLASS *class = NULL;
64 user_handle_t handle = 0;
65 int extra_bytes = 0;
67 /* if 16-bit instance, map to module handle */
68 if (instance && !HIWORD(instance))
69 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
71 SERVER_START_REQ( create_window )
73 req->parent = parent;
74 req->owner = owner;
75 req->atom = atom;
76 req->instance = instance;
77 if (!wine_server_call_err( req ))
79 handle = reply->handle;
80 full_parent = reply->parent;
81 full_owner = reply->owner;
82 extra_bytes = reply->extra;
83 class = reply->class_ptr;
86 SERVER_END_REQ;
88 if (!handle)
90 WARN( "error %ld creating window\n", GetLastError() );
91 return NULL;
94 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
96 SERVER_START_REQ( destroy_window )
98 req->handle = handle;
99 wine_server_call( req );
101 SERVER_END_REQ;
102 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
103 return NULL;
106 if (!parent) /* if parent is 0 we don't have a desktop window yet */
108 struct user_thread_info *thread_info = get_user_thread_info();
110 assert( !thread_info->desktop );
111 thread_info->desktop = full_parent ? full_parent : handle;
112 if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
113 ERR( "failed to create desktop window\n" );
116 USER_Lock();
118 index = USER_HANDLE_TO_INDEX(handle);
119 assert( index < NB_USER_HANDLES );
120 user_handles[index] = win;
121 win->hwndSelf = handle;
122 win->parent = full_parent;
123 win->owner = full_owner;
124 win->dwMagic = WND_MAGIC;
125 win->cbWndExtra = extra_bytes;
126 memset( win->wExtra, 0, extra_bytes );
127 CLASS_AddWindow( class, win, type );
128 return win;
132 /***********************************************************************
133 * free_window_handle
135 * Free a window handle.
137 static WND *free_window_handle( HWND hwnd )
139 WND *ptr;
140 WORD index = USER_HANDLE_TO_INDEX(hwnd);
142 if (index >= NB_USER_HANDLES) return NULL;
143 USER_Lock();
144 if ((ptr = user_handles[index]))
146 SERVER_START_REQ( destroy_window )
148 req->handle = hwnd;
149 if (!wine_server_call_err( req ))
151 user_handles[index] = NULL;
152 ptr->dwMagic = 0;
154 else
155 ptr = NULL;
157 SERVER_END_REQ;
159 USER_Unlock();
160 HeapFree( GetProcessHeap(), 0, ptr );
161 return ptr;
165 /*******************************************************************
166 * list_window_children
168 * Build an array of the children of a given window. The array must be
169 * freed with HeapFree. Returns NULL when no windows are found.
171 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
173 HWND *list;
174 int size = 32;
176 for (;;)
178 int count = 0;
180 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
182 SERVER_START_REQ( get_window_children )
184 req->parent = hwnd;
185 req->atom = atom;
186 req->tid = tid;
187 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
188 if (!wine_server_call( req )) count = reply->count;
190 SERVER_END_REQ;
191 if (count && count < size)
193 list[count] = 0;
194 return list;
196 HeapFree( GetProcessHeap(), 0, list );
197 if (!count) break;
198 size = count + 1; /* restart with a large enough buffer */
200 return NULL;
204 /*******************************************************************
205 * list_window_parents
207 * Build an array of all parents of a given window, starting with
208 * the immediate parent. The array must be freed with HeapFree.
209 * Returns NULL if window is a top-level window.
211 static HWND *list_window_parents( HWND hwnd )
213 WND *win;
214 HWND current, *list;
215 int pos = 0, size = 16, count = 0;
217 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
219 current = hwnd;
220 for (;;)
222 if (!(win = WIN_GetPtr( current ))) goto empty;
223 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
224 if (win == WND_DESKTOP)
226 if (!pos) goto empty;
227 list[pos] = 0;
228 return list;
230 list[pos] = current = win->parent;
231 WIN_ReleasePtr( win );
232 if (++pos == size - 1)
234 /* need to grow the list */
235 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
236 if (!new_list) goto empty;
237 list = new_list;
238 size += 16;
242 /* at least one parent belongs to another process, have to query the server */
244 for (;;)
246 count = 0;
247 SERVER_START_REQ( get_window_parents )
249 req->handle = hwnd;
250 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
251 if (!wine_server_call( req )) count = reply->count;
253 SERVER_END_REQ;
254 if (!count) goto empty;
255 if (size > count)
257 list[count] = 0;
258 return list;
260 HeapFree( GetProcessHeap(), 0, list );
261 size = count + 1;
262 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
265 empty:
266 HeapFree( GetProcessHeap(), 0, list );
267 return NULL;
271 /*******************************************************************
272 * send_parent_notify
274 static void send_parent_notify( HWND hwnd, UINT msg )
276 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
277 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
279 HWND parent = GetParent(hwnd);
280 if (parent && parent != GetDesktopWindow())
281 SendMessageW( parent, WM_PARENTNOTIFY,
282 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
287 /*******************************************************************
288 * get_server_window_text
290 * Retrieve the window text from the server.
292 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
294 size_t len = 0;
296 SERVER_START_REQ( get_window_text )
298 req->handle = hwnd;
299 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
300 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
302 SERVER_END_REQ;
303 text[len / sizeof(WCHAR)] = 0;
307 /***********************************************************************
308 * WIN_GetPtr
310 * Return a pointer to the WND structure if local to the process,
311 * or WND_OTHER_PROCESS if handle may be valid in other process.
312 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
314 WND *WIN_GetPtr( HWND hwnd )
316 WND * ptr;
317 WORD index = USER_HANDLE_TO_INDEX(hwnd);
319 if (index >= NB_USER_HANDLES) return NULL;
321 USER_Lock();
322 if ((ptr = user_handles[index]))
324 if (ptr->dwMagic == WND_MAGIC &&
325 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
326 return ptr;
327 ptr = NULL;
329 else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
331 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
332 else ptr = NULL;
334 else ptr = WND_OTHER_PROCESS;
335 USER_Unlock();
336 return ptr;
340 /***********************************************************************
341 * WIN_IsCurrentProcess
343 * Check whether a given window belongs to the current process (and return the full handle).
345 HWND WIN_IsCurrentProcess( HWND hwnd )
347 WND *ptr;
348 HWND ret;
350 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
351 ret = ptr->hwndSelf;
352 WIN_ReleasePtr( ptr );
353 return ret;
357 /***********************************************************************
358 * WIN_IsCurrentThread
360 * Check whether a given window belongs to the current thread (and return the full handle).
362 HWND WIN_IsCurrentThread( HWND hwnd )
364 WND *ptr;
365 HWND ret = 0;
367 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
368 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
369 WIN_ReleasePtr( ptr );
370 return ret;
374 /***********************************************************************
375 * WIN_Handle32
377 * Convert a 16-bit window handle to a full 32-bit handle.
379 HWND WIN_Handle32( HWND16 hwnd16 )
381 WND *ptr;
382 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
384 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
385 /* do sign extension for -2 and -3 */
386 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
388 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
390 if (ptr == WND_DESKTOP) return GetDesktopWindow();
392 if (ptr != WND_OTHER_PROCESS)
394 hwnd = ptr->hwndSelf;
395 WIN_ReleasePtr( ptr );
397 else /* may belong to another process */
399 SERVER_START_REQ( get_window_info )
401 req->handle = hwnd;
402 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
404 SERVER_END_REQ;
406 return hwnd;
410 /***********************************************************************
411 * WIN_SetOwner
413 * Change the owner of a window.
415 HWND WIN_SetOwner( HWND hwnd, HWND owner )
417 WND *win = WIN_GetPtr( hwnd );
418 HWND ret = 0;
420 if (!win || win == WND_DESKTOP) return 0;
421 if (win == WND_OTHER_PROCESS)
423 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
424 return 0;
426 SERVER_START_REQ( set_window_owner )
428 req->handle = hwnd;
429 req->owner = owner;
430 if (!wine_server_call( req ))
432 win->owner = reply->full_owner;
433 ret = reply->prev_owner;
436 SERVER_END_REQ;
437 WIN_ReleasePtr( win );
438 return ret;
442 /***********************************************************************
443 * WIN_SetStyle
445 * Change the style of a window.
447 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
449 BOOL ok;
450 ULONG new_style, old_style = 0;
451 WND *win = WIN_GetPtr( hwnd );
453 if (!win || win == WND_DESKTOP) return 0;
454 if (win == WND_OTHER_PROCESS)
456 if (IsWindow(hwnd))
457 ERR( "cannot set style %lx/%lx on other process window %p\n",
458 set_bits, clear_bits, hwnd );
459 return 0;
461 new_style = (win->dwStyle | set_bits) & ~clear_bits;
462 if (new_style == win->dwStyle)
464 WIN_ReleasePtr( win );
465 return new_style;
467 SERVER_START_REQ( set_window_info )
469 req->handle = hwnd;
470 req->flags = SET_WIN_STYLE;
471 req->style = new_style;
472 req->extra_offset = -1;
473 if ((ok = !wine_server_call( req )))
475 old_style = reply->old_style;
476 win->dwStyle = new_style;
479 SERVER_END_REQ;
480 WIN_ReleasePtr( win );
481 if (ok) USER_Driver->pSetWindowStyle( hwnd, old_style );
482 return old_style;
486 /***********************************************************************
487 * WIN_GetRectangles
489 * Get the window and client rectangles.
491 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
493 WND *win = WIN_GetPtr( hwnd );
494 BOOL ret = TRUE;
496 if (!win) return FALSE;
497 if (win == WND_DESKTOP)
499 RECT rect;
500 rect.left = rect.top = 0;
501 rect.right = GetSystemMetrics(SM_CXSCREEN);
502 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
503 if (rectWindow) *rectWindow = rect;
504 if (rectClient) *rectClient = rect;
506 else if (win == WND_OTHER_PROCESS)
508 SERVER_START_REQ( get_window_rectangles )
510 req->handle = hwnd;
511 if ((ret = !wine_server_call( req )))
513 if (rectWindow)
515 rectWindow->left = reply->window.left;
516 rectWindow->top = reply->window.top;
517 rectWindow->right = reply->window.right;
518 rectWindow->bottom = reply->window.bottom;
520 if (rectClient)
522 rectClient->left = reply->client.left;
523 rectClient->top = reply->client.top;
524 rectClient->right = reply->client.right;
525 rectClient->bottom = reply->client.bottom;
529 SERVER_END_REQ;
531 else
533 if (rectWindow) *rectWindow = win->rectWindow;
534 if (rectClient) *rectClient = win->rectClient;
535 WIN_ReleasePtr( win );
537 return ret;
541 /***********************************************************************
542 * WIN_DestroyWindow
544 * Destroy storage associated to a window. "Internals" p.358
546 LRESULT WIN_DestroyWindow( HWND hwnd )
548 WND *wndPtr;
549 HWND *list;
550 HMENU menu = 0, sys_menu;
552 TRACE("%p\n", hwnd );
554 /* free child windows */
555 if ((list = WIN_ListChildren( hwnd )))
557 int i;
558 for (i = 0; list[i]; i++)
560 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
561 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
563 HeapFree( GetProcessHeap(), 0, list );
566 /* Unlink now so we won't bother with the children later on */
567 SERVER_START_REQ( set_parent )
569 req->handle = hwnd;
570 req->parent = 0;
571 wine_server_call( req );
573 SERVER_END_REQ;
576 * Send the WM_NCDESTROY to the window being destroyed.
578 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
580 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
582 WINPOS_CheckInternalPos( hwnd );
584 /* free resources associated with the window */
586 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
587 if (!(wndPtr->dwStyle & WS_CHILD)) menu = (HMENU)wndPtr->wIDmenu;
588 sys_menu = wndPtr->hSysMenu;
589 WIN_ReleasePtr( wndPtr );
591 if (menu) DestroyMenu( menu );
592 if (sys_menu) DestroyMenu( sys_menu );
594 USER_Driver->pDestroyWindow( hwnd );
596 free_window_handle( hwnd );
597 return 0;
600 /***********************************************************************
601 * WIN_DestroyThreadWindows
603 * Destroy all children of 'wnd' owned by the current thread.
604 * Return TRUE if something was done.
606 void WIN_DestroyThreadWindows( HWND hwnd )
608 HWND *list;
609 int i;
611 if (!(list = WIN_ListChildren( hwnd ))) return;
612 for (i = 0; list[i]; i++)
614 if (WIN_IsCurrentThread( list[i] ))
615 DestroyWindow( list[i] );
616 else
617 WIN_DestroyThreadWindows( list[i] );
619 HeapFree( GetProcessHeap(), 0, list );
623 /***********************************************************************
624 * WIN_FixCoordinates
626 * Fix the coordinates - Helper for WIN_CreateWindowEx.
627 * returns default show mode in sw.
628 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
630 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
632 POINT pos[2];
634 if (cs->dwExStyle & WS_EX_MDICHILD)
636 UINT id = 0;
638 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
639 if (!(cs->style & WS_POPUP)) cs->hMenu = (HMENU)id;
641 TRACE("MDI child id %04x\n", id);
644 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
645 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
647 if (cs->style & (WS_CHILD | WS_POPUP))
649 if (cs->dwExStyle & WS_EX_MDICHILD)
651 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
653 cs->x = pos[0].x;
654 cs->y = pos[0].y;
656 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
657 cs->cx = pos[1].x;
658 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
659 cs->cy = pos[1].y;
661 else
663 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
664 cs->x = cs->y = 0;
665 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
666 cs->cx = cs->cy = 0;
669 else /* overlapped window */
671 STARTUPINFOW info;
673 GetStartupInfoW( &info );
675 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
677 /* Never believe Microsoft's documentation... CreateWindowEx doc says
678 * that if an overlapped window is created with WS_VISIBLE style bit
679 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
680 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
681 * reveals that
683 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
684 * 2) it does not ignore the y parameter as the docs claim; instead, it
685 * uses it as second parameter to ShowWindow() unless y is either
686 * CW_USEDEFAULT or CW_USEDEFAULT16.
688 * The fact that we didn't do 2) caused bogus windows pop up when wine
689 * was running apps that were using this obscure feature. Example -
690 * calc.exe that comes with Win98 (only Win98, it's different from
691 * the one that comes with Win95 and NT)
693 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
694 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
695 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
698 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
700 if (info.dwFlags & STARTF_USESIZE)
702 cs->cx = info.dwXSize;
703 cs->cy = info.dwYSize;
705 else /* if no other hint from the app, pick 3/4 of the screen real estate */
707 RECT r;
708 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
709 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
710 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
713 /* Handle case where only the cy values is set to default */
714 else if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16)
716 RECT r;
717 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
718 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
722 else
724 /* neither x nor cx are default. Check the y values .
725 * In the trace we see Outlook and Outlook Express using
726 * cy set to CW_USEDEFAULT when opening the address book.
728 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
729 RECT r;
730 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
731 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
732 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
737 /***********************************************************************
738 * dump_window_styles
740 static void dump_window_styles( DWORD style, DWORD exstyle )
742 TRACE( "style:" );
743 if(style & WS_POPUP) TRACE(" WS_POPUP");
744 if(style & WS_CHILD) TRACE(" WS_CHILD");
745 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
746 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
747 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
748 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
749 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
750 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
751 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
752 else
754 if(style & WS_BORDER) TRACE(" WS_BORDER");
755 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
757 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
758 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
759 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
760 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
761 if (style & WS_CHILD)
763 if(style & WS_GROUP) TRACE(" WS_GROUP");
764 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
766 else
768 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
769 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
772 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
773 #define DUMPED_STYLES \
774 (WS_POPUP | \
775 WS_CHILD | \
776 WS_MINIMIZE | \
777 WS_VISIBLE | \
778 WS_DISABLED | \
779 WS_CLIPSIBLINGS | \
780 WS_CLIPCHILDREN | \
781 WS_MAXIMIZE | \
782 WS_BORDER | \
783 WS_DLGFRAME | \
784 WS_VSCROLL | \
785 WS_HSCROLL | \
786 WS_SYSMENU | \
787 WS_THICKFRAME | \
788 WS_GROUP | \
789 WS_TABSTOP | \
790 WS_MINIMIZEBOX | \
791 WS_MAXIMIZEBOX)
793 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
794 TRACE("\n");
795 #undef DUMPED_STYLES
797 TRACE( "exstyle:" );
798 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
799 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
800 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
801 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
802 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
803 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
804 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
805 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
806 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
807 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
808 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
809 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
810 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
811 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
812 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
813 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
814 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
815 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
817 #define DUMPED_EX_STYLES \
818 (WS_EX_DLGMODALFRAME | \
819 WS_EX_DRAGDETECT | \
820 WS_EX_NOPARENTNOTIFY | \
821 WS_EX_TOPMOST | \
822 WS_EX_ACCEPTFILES | \
823 WS_EX_TRANSPARENT | \
824 WS_EX_MDICHILD | \
825 WS_EX_TOOLWINDOW | \
826 WS_EX_WINDOWEDGE | \
827 WS_EX_CLIENTEDGE | \
828 WS_EX_CONTEXTHELP | \
829 WS_EX_RIGHT | \
830 WS_EX_RTLREADING | \
831 WS_EX_LEFTSCROLLBAR | \
832 WS_EX_CONTROLPARENT | \
833 WS_EX_STATICEDGE | \
834 WS_EX_APPWINDOW | \
835 WS_EX_LAYERED)
837 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
838 TRACE("\n");
839 #undef DUMPED_EX_STYLES
843 /***********************************************************************
844 * WIN_CreateWindowEx
846 * Implementation of CreateWindowEx().
848 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
849 WINDOWPROCTYPE type )
851 INT sw = SW_SHOW;
852 WND *wndPtr;
853 HWND hwnd, parent, owner, top_child = 0;
854 BOOL unicode = (type == WIN_PROC_32W);
855 MDICREATESTRUCTA mdi_cs;
857 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
858 (type == WIN_PROC_32W) ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
859 (type == WIN_PROC_32W) ? debugstr_w((LPCWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
860 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
861 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
863 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
865 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
866 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
868 /* Fix the styles for MDI children */
869 if (cs->dwExStyle & WS_EX_MDICHILD)
871 UINT flags = 0;
873 wndPtr = WIN_GetPtr(cs->hwndParent);
874 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
876 flags = wndPtr->flags;
877 WIN_ReleasePtr(wndPtr);
880 if (!(flags & WIN_ISMDICLIENT))
882 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
883 return 0;
886 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
887 * MDICREATESTRUCT members have the originally passed values.
889 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
890 * have the same layout.
892 mdi_cs.szClass = cs->lpszClass;
893 mdi_cs.szTitle = cs->lpszName;
894 mdi_cs.hOwner = cs->hInstance;
895 mdi_cs.x = cs->x;
896 mdi_cs.y = cs->y;
897 mdi_cs.cx = cs->cx;
898 mdi_cs.cy = cs->cy;
899 mdi_cs.style = cs->style;
900 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
902 cs->lpCreateParams = (LPVOID)&mdi_cs;
904 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
906 if (cs->style & WS_POPUP)
908 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
909 return 0;
911 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
913 else
915 cs->style &= ~WS_POPUP;
916 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
917 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
920 top_child = GetWindow(cs->hwndParent, GW_CHILD);
922 if (top_child)
924 /* Restore current maximized child */
925 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
927 TRACE("Restoring current maximized child %p\n", top_child);
928 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
929 ShowWindow(top_child, SW_RESTORE);
930 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
935 /* Find the parent window */
937 parent = cs->hwndParent;
938 owner = 0;
940 if (cs->hwndParent == HWND_MESSAGE)
942 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
943 * message window (style: WS_POPUP|WS_DISABLED)
945 FIXME("Parent is HWND_MESSAGE\n");
946 parent = GetDesktopWindow();
948 else if (cs->hwndParent)
950 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
952 parent = GetDesktopWindow();
953 owner = cs->hwndParent;
956 else
958 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
960 WARN("No parent for child window\n" );
961 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
963 if (classAtom != LOWORD(DESKTOP_CLASS_ATOM)) /* are we creating the desktop itself? */
964 parent = GetDesktopWindow();
967 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
969 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
970 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
971 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
972 cs->dwExStyle |= WS_EX_WINDOWEDGE;
973 else
974 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
976 /* Create the window structure */
978 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
979 return 0;
980 hwnd = wndPtr->hwndSelf;
982 /* Fill the window structure */
984 wndPtr->tid = GetCurrentThreadId();
985 wndPtr->hInstance = cs->hInstance;
986 wndPtr->text = NULL;
987 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
988 wndPtr->dwExStyle = cs->dwExStyle;
989 wndPtr->wIDmenu = 0;
990 wndPtr->helpContext = 0;
991 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
992 wndPtr->pVScroll = NULL;
993 wndPtr->pHScroll = NULL;
994 wndPtr->userdata = 0;
995 wndPtr->hIcon = 0;
996 wndPtr->hIconSmall = 0;
997 wndPtr->hSysMenu = 0;
999 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1002 * Correct the window styles.
1004 * It affects only the style loaded into the WIN structure.
1007 if (!(wndPtr->dwStyle & WS_CHILD))
1009 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1010 if (!(wndPtr->dwStyle & WS_POPUP))
1011 wndPtr->dwStyle |= WS_CAPTION;
1015 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1016 * why does the user get to set it?
1019 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1020 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1021 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1022 else
1023 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1025 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1026 wndPtr->flags |= WIN_NEED_SIZE;
1028 SERVER_START_REQ( set_window_info )
1030 req->handle = hwnd;
1031 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1032 req->style = wndPtr->dwStyle;
1033 req->ex_style = wndPtr->dwExStyle;
1034 req->instance = (void *)wndPtr->hInstance;
1035 req->is_unicode = (type == WIN_PROC_32W);
1036 req->extra_offset = -1;
1037 wine_server_call( req );
1039 SERVER_END_REQ;
1041 /* Set the window menu */
1043 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1044 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1046 if (cs->hMenu)
1048 if (!MENU_SetMenu(hwnd, cs->hMenu))
1050 WIN_ReleasePtr( wndPtr );
1051 free_window_handle( hwnd );
1052 return 0;
1055 else
1057 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1058 if (menuName)
1060 if (!cs->hInstance || HIWORD(cs->hInstance))
1061 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1062 else
1063 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1065 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1069 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1070 WIN_ReleasePtr( wndPtr );
1072 if (!USER_Driver->pCreateWindow( hwnd, cs, unicode))
1074 WIN_DestroyWindow( hwnd );
1075 return 0;
1078 /* Notify the parent window only */
1080 send_parent_notify( hwnd, WM_CREATE );
1081 if (!IsWindow( hwnd )) return 0;
1083 if (cs->style & WS_VISIBLE)
1085 if (cs->style & WS_MAXIMIZE)
1086 sw = SW_SHOW;
1087 else if (cs->style & WS_MINIMIZE)
1088 sw = SW_SHOWMINIMIZED;
1090 ShowWindow( hwnd, sw );
1091 if (cs->dwExStyle & WS_EX_MDICHILD)
1093 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1094 /* ShowWindow won't activate child windows */
1095 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1099 /* Call WH_SHELL hook */
1101 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1102 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1104 TRACE("created window %p\n", hwnd);
1105 return hwnd;
1109 /***********************************************************************
1110 * CreateWindow (USER.41)
1112 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1113 DWORD style, INT16 x, INT16 y, INT16 width,
1114 INT16 height, HWND16 parent, HMENU16 menu,
1115 HINSTANCE16 instance, LPVOID data )
1117 return CreateWindowEx16( 0, className, windowName, style,
1118 x, y, width, height, parent, menu, instance, data );
1122 /***********************************************************************
1123 * CreateWindowEx (USER.452)
1125 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1126 LPCSTR windowName, DWORD style, INT16 x,
1127 INT16 y, INT16 width, INT16 height,
1128 HWND16 parent, HMENU16 menu,
1129 HINSTANCE16 instance, LPVOID data )
1131 ATOM classAtom;
1132 CREATESTRUCTA cs;
1133 char buffer[256];
1135 /* Find the class atom */
1137 if (HIWORD(className))
1139 if (!(classAtom = GlobalFindAtomA( className )))
1141 ERR( "bad class name %s\n", debugstr_a(className) );
1142 return 0;
1145 else
1147 classAtom = LOWORD(className);
1148 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1150 ERR( "bad atom %x\n", classAtom);
1151 return 0;
1153 className = buffer;
1156 /* Fix the coordinates */
1158 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1159 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1160 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1161 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1163 /* Create the window */
1165 cs.lpCreateParams = data;
1166 cs.hInstance = HINSTANCE_32(instance);
1167 cs.hMenu = HMENU_32(menu);
1168 cs.hwndParent = WIN_Handle32( parent );
1169 cs.style = style;
1170 cs.lpszName = windowName;
1171 cs.lpszClass = className;
1172 cs.dwExStyle = exStyle;
1174 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1178 /***********************************************************************
1179 * CreateWindowExA (USER32.@)
1181 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1182 LPCSTR windowName, DWORD style, INT x,
1183 INT y, INT width, INT height,
1184 HWND parent, HMENU menu,
1185 HINSTANCE instance, LPVOID data )
1187 ATOM classAtom;
1188 CREATESTRUCTA cs;
1189 char buffer[256];
1191 /* Find the class atom */
1193 if (HIWORD(className))
1195 if (!(classAtom = GlobalFindAtomA( className )))
1197 ERR( "bad class name %s\n", debugstr_a(className) );
1198 return 0;
1201 else
1203 classAtom = LOWORD(className);
1204 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1206 ERR( "bad atom %x\n", classAtom);
1207 return 0;
1209 className = buffer;
1212 /* Create the window */
1214 cs.lpCreateParams = data;
1215 cs.hInstance = instance;
1216 cs.hMenu = menu;
1217 cs.hwndParent = parent;
1218 cs.x = x;
1219 cs.y = y;
1220 cs.cx = width;
1221 cs.cy = height;
1222 cs.style = style;
1223 cs.lpszName = windowName;
1224 cs.lpszClass = className;
1225 cs.dwExStyle = exStyle;
1227 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1231 /***********************************************************************
1232 * CreateWindowExW (USER32.@)
1234 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1235 LPCWSTR windowName, DWORD style, INT x,
1236 INT y, INT width, INT height,
1237 HWND parent, HMENU menu,
1238 HINSTANCE instance, LPVOID data )
1240 ATOM classAtom;
1241 CREATESTRUCTW cs;
1242 WCHAR buffer[256];
1244 /* Find the class atom */
1246 if (HIWORD(className))
1248 if (!(classAtom = GlobalFindAtomW( className )))
1250 ERR( "bad class name %s\n", debugstr_w(className) );
1251 return 0;
1254 else
1256 classAtom = LOWORD(className);
1257 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1259 ERR( "bad atom %x\n", classAtom);
1260 return 0;
1262 className = buffer;
1265 /* Create the window */
1267 cs.lpCreateParams = data;
1268 cs.hInstance = instance;
1269 cs.hMenu = menu;
1270 cs.hwndParent = parent;
1271 cs.x = x;
1272 cs.y = y;
1273 cs.cx = width;
1274 cs.cy = height;
1275 cs.style = style;
1276 cs.lpszName = windowName;
1277 cs.lpszClass = className;
1278 cs.dwExStyle = exStyle;
1280 /* Note: we rely on the fact that CREATESTRUCTA and */
1281 /* CREATESTRUCTW have the same layout. */
1282 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1286 /***********************************************************************
1287 * WIN_SendDestroyMsg
1289 static void WIN_SendDestroyMsg( HWND hwnd )
1291 GUITHREADINFO info;
1293 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1295 if (hwnd == info.hwndCaret) DestroyCaret();
1296 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1298 USER_Driver->pResetSelectionOwner( hwnd, TRUE );
1301 * Send the WM_DESTROY to the window.
1303 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1306 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1307 * make sure that the window still exists when we come back.
1309 if (IsWindow(hwnd))
1311 HWND* pWndArray;
1312 int i;
1314 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1316 for (i = 0; pWndArray[i]; i++)
1318 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1320 HeapFree( GetProcessHeap(), 0, pWndArray );
1322 else
1323 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1327 /***********************************************************************
1328 * DestroyWindow (USER32.@)
1330 BOOL WINAPI DestroyWindow( HWND hwnd )
1332 BOOL is_child;
1334 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1336 SetLastError( ERROR_ACCESS_DENIED );
1337 return FALSE;
1340 TRACE("(%p)\n", hwnd);
1342 /* Call hooks */
1344 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1346 if (MENU_IsMenuActive() == hwnd)
1347 EndMenu();
1349 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1351 if (is_child)
1353 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1354 send_parent_notify( hwnd, WM_DESTROY );
1356 else if (!GetWindow( hwnd, GW_OWNER ))
1358 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1359 /* FIXME: clean up palette - see "Internals" p.352 */
1362 if (!IsWindow(hwnd)) return TRUE;
1364 USER_Driver->pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1366 /* Hide the window */
1367 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1369 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1370 if (is_child)
1371 ShowWindow( hwnd, SW_HIDE );
1372 else
1373 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1374 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1377 if (!IsWindow(hwnd)) return TRUE;
1379 /* Recursively destroy owned windows */
1381 if (!is_child)
1383 for (;;)
1385 int i, got_one = 0;
1386 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1387 if (list)
1389 for (i = 0; list[i]; i++)
1391 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1392 if (WIN_IsCurrentThread( list[i] ))
1394 DestroyWindow( list[i] );
1395 got_one = 1;
1396 continue;
1398 WIN_SetOwner( list[i], 0 );
1400 HeapFree( GetProcessHeap(), 0, list );
1402 if (!got_one) break;
1406 /* Send destroy messages */
1408 WIN_SendDestroyMsg( hwnd );
1409 if (!IsWindow( hwnd )) return TRUE;
1411 if (GetClipboardOwner() == hwnd)
1412 CLIPBOARD_ReleaseOwner();
1414 /* Destroy the window storage */
1416 WIN_DestroyWindow( hwnd );
1417 return TRUE;
1421 /***********************************************************************
1422 * CloseWindow (USER32.@)
1424 BOOL WINAPI CloseWindow( HWND hwnd )
1426 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1427 ShowWindow( hwnd, SW_MINIMIZE );
1428 return TRUE;
1432 /***********************************************************************
1433 * OpenIcon (USER32.@)
1435 BOOL WINAPI OpenIcon( HWND hwnd )
1437 if (!IsIconic( hwnd )) return FALSE;
1438 ShowWindow( hwnd, SW_SHOWNORMAL );
1439 return TRUE;
1443 /***********************************************************************
1444 * WIN_FindWindow
1446 * Implementation of FindWindow() and FindWindowEx().
1448 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1450 HWND *list = NULL;
1451 HWND retvalue = 0;
1452 int i = 0, len = 0;
1453 WCHAR *buffer = NULL;
1455 if (!parent) parent = GetDesktopWindow();
1456 if (title)
1458 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1459 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1462 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1464 if (child)
1466 child = WIN_GetFullHandle( child );
1467 while (list[i] && list[i] != child) i++;
1468 if (!list[i]) goto done;
1469 i++; /* start from next window */
1472 if (title)
1474 while (list[i])
1476 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1477 i++;
1480 retvalue = list[i];
1482 done:
1483 HeapFree( GetProcessHeap(), 0, list );
1484 HeapFree( GetProcessHeap(), 0, buffer );
1485 return retvalue;
1490 /***********************************************************************
1491 * FindWindowA (USER32.@)
1493 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1495 HWND ret = FindWindowExA( 0, 0, className, title );
1496 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1497 return ret;
1501 /***********************************************************************
1502 * FindWindowExA (USER32.@)
1504 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1505 LPCSTR className, LPCSTR title )
1507 ATOM atom = 0;
1508 LPWSTR buffer;
1509 HWND hwnd;
1510 INT len;
1512 if (className)
1514 /* If the atom doesn't exist, then no class */
1515 /* with this name exists either. */
1516 if (!(atom = GlobalFindAtomA( className )))
1518 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1519 return 0;
1522 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1524 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1525 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1526 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1527 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1528 HeapFree( GetProcessHeap(), 0, buffer );
1529 return hwnd;
1533 /***********************************************************************
1534 * FindWindowExW (USER32.@)
1536 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1537 LPCWSTR className, LPCWSTR title )
1539 ATOM atom = 0;
1541 if (className)
1543 /* If the atom doesn't exist, then no class */
1544 /* with this name exists either. */
1545 if (!(atom = GlobalFindAtomW( className )))
1547 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1548 return 0;
1551 return WIN_FindWindow( parent, child, atom, title );
1555 /***********************************************************************
1556 * FindWindowW (USER32.@)
1558 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1560 return FindWindowExW( 0, 0, className, title );
1564 /**********************************************************************
1565 * GetDesktopWindow (USER32.@)
1567 HWND WINAPI GetDesktopWindow(void)
1569 struct user_thread_info *thread_info = get_user_thread_info();
1571 if (thread_info->desktop) return thread_info->desktop;
1573 SERVER_START_REQ( get_desktop_window )
1575 req->force = 0;
1576 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1578 SERVER_END_REQ;
1580 if (!thread_info->desktop)
1582 STARTUPINFOW si;
1583 PROCESS_INFORMATION pi;
1584 WCHAR command_line[] = {'e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1586 memset( &si, 0, sizeof(si) );
1587 si.cb = sizeof(si);
1588 if (CreateProcessW( NULL, command_line, NULL, NULL, FALSE, DETACHED_PROCESS,
1589 NULL, NULL, &si, &pi ))
1591 TRACE( "started explorer pid %04lx tid %04lx\n", pi.dwProcessId, pi.dwThreadId );
1592 WaitForInputIdle( pi.hProcess, 10000 );
1593 CloseHandle( pi.hThread );
1594 CloseHandle( pi.hProcess );
1597 else WARN( "failed to start explorer, err %ld\n", GetLastError() );
1599 SERVER_START_REQ( get_desktop_window )
1601 req->force = 1;
1602 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1604 SERVER_END_REQ;
1607 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1608 ERR( "failed to create desktop window\n" );
1610 return thread_info->desktop;
1614 /*******************************************************************
1615 * EnableWindow (USER32.@)
1617 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1619 BOOL retvalue;
1620 HWND full_handle;
1622 if (is_broadcast(hwnd))
1624 SetLastError( ERROR_INVALID_PARAMETER );
1625 return FALSE;
1628 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1629 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1631 hwnd = full_handle;
1633 TRACE("( %p, %d )\n", hwnd, enable);
1635 retvalue = !IsWindowEnabled( hwnd );
1637 if (enable && retvalue)
1639 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1640 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1642 else if (!enable && !retvalue)
1644 HWND capture_wnd;
1646 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1648 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1650 if (hwnd == GetFocus())
1651 SetFocus( 0 ); /* A disabled window can't have the focus */
1653 capture_wnd = GetCapture();
1654 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1655 ReleaseCapture(); /* A disabled window can't capture the mouse */
1657 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1659 return retvalue;
1663 /***********************************************************************
1664 * IsWindowEnabled (USER32.@)
1666 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1668 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1672 /***********************************************************************
1673 * IsWindowUnicode (USER32.@)
1675 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1677 WND * wndPtr;
1678 BOOL retvalue = FALSE;
1680 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1682 if (wndPtr == WND_DESKTOP) return TRUE;
1684 if (wndPtr != WND_OTHER_PROCESS)
1686 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1687 WIN_ReleasePtr( wndPtr );
1689 else
1691 SERVER_START_REQ( get_window_info )
1693 req->handle = hwnd;
1694 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1696 SERVER_END_REQ;
1698 return retvalue;
1702 /**********************************************************************
1703 * GetWindowWord (USER32.@)
1705 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1707 if (offset >= 0)
1709 WORD retvalue = 0;
1710 WND *wndPtr = WIN_GetPtr( hwnd );
1711 if (!wndPtr)
1713 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1714 return 0;
1716 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1718 SERVER_START_REQ( set_window_info )
1720 req->handle = hwnd;
1721 req->flags = 0; /* don't set anything, just retrieve */
1722 req->extra_offset = offset;
1723 req->extra_size = sizeof(retvalue);
1724 if (!wine_server_call_err( req ))
1725 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1727 SERVER_END_REQ;
1728 return retvalue;
1730 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1732 WARN("Invalid offset %d\n", offset );
1733 SetLastError( ERROR_INVALID_INDEX );
1735 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1736 WIN_ReleasePtr( wndPtr );
1737 return retvalue;
1740 switch(offset)
1742 case GWLP_HWNDPARENT:
1743 return GetWindowLongPtrW( hwnd, offset );
1744 case GWLP_ID:
1745 case GWLP_HINSTANCE:
1747 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1748 if (HIWORD(ret))
1749 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1750 return LOWORD(ret);
1752 default:
1753 WARN("Invalid offset %d\n", offset );
1754 return 0;
1759 /**********************************************************************
1760 * SetWindowWord (USER32.@)
1762 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1764 WORD retval = 0;
1765 WND * wndPtr;
1767 switch(offset)
1769 case GWLP_ID:
1770 case GWLP_HINSTANCE:
1771 case GWLP_HWNDPARENT:
1772 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1773 default:
1774 if (offset < 0)
1776 WARN("Invalid offset %d\n", offset );
1777 SetLastError( ERROR_INVALID_INDEX );
1778 return 0;
1782 wndPtr = WIN_GetPtr( hwnd );
1783 if (wndPtr == WND_DESKTOP)
1785 SetLastError( ERROR_ACCESS_DENIED );
1786 return 0;
1788 if (wndPtr == WND_OTHER_PROCESS)
1790 if (IsWindow(hwnd))
1791 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1792 offset, newval, hwnd );
1793 wndPtr = NULL;
1795 if (!wndPtr)
1797 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1798 return 0;
1801 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1803 WARN("Invalid offset %d\n", offset );
1804 WIN_ReleasePtr(wndPtr);
1805 SetLastError( ERROR_INVALID_INDEX );
1806 return 0;
1809 SERVER_START_REQ( set_window_info )
1811 req->handle = hwnd;
1812 req->flags = SET_WIN_EXTRA;
1813 req->extra_offset = offset;
1814 req->extra_size = sizeof(newval);
1815 memcpy( &req->extra_value, &newval, sizeof(newval) );
1816 if (!wine_server_call_err( req ))
1818 void *ptr = (char *)wndPtr->wExtra + offset;
1819 memcpy( &retval, ptr, sizeof(retval) );
1820 memcpy( ptr, &newval, sizeof(newval) );
1823 SERVER_END_REQ;
1824 WIN_ReleasePtr( wndPtr );
1825 return retval;
1829 /**********************************************************************
1830 * WIN_GetWindowLong
1832 * Helper function for GetWindowLong().
1834 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1836 LONG_PTR retvalue = 0;
1837 WND *wndPtr;
1839 if (offset == GWLP_HWNDPARENT)
1841 HWND parent = GetAncestor( hwnd, GA_PARENT );
1842 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1843 return (ULONG_PTR)parent;
1846 if (!(wndPtr = WIN_GetPtr( hwnd )))
1848 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1849 return 0;
1852 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1854 if (offset == GWLP_WNDPROC)
1856 SetLastError( ERROR_ACCESS_DENIED );
1857 return 0;
1859 SERVER_START_REQ( set_window_info )
1861 req->handle = hwnd;
1862 req->flags = 0; /* don't set anything, just retrieve */
1863 req->extra_offset = (offset >= 0) ? offset : -1;
1864 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1865 if (!wine_server_call_err( req ))
1867 switch(offset)
1869 case GWL_STYLE: retvalue = reply->old_style; break;
1870 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1871 case GWLP_ID: retvalue = reply->old_id; break;
1872 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1873 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1874 default:
1875 if (offset >= 0) retvalue = reply->old_extra_value;
1876 else SetLastError( ERROR_INVALID_INDEX );
1877 break;
1881 SERVER_END_REQ;
1882 return retvalue;
1885 /* now we have a valid wndPtr */
1887 if (offset >= 0)
1889 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1892 * Some programs try to access last element from 16 bit
1893 * code using illegal offset value. Hopefully this is
1894 * what those programs really expect.
1896 if (type == WIN_PROC_16 &&
1897 wndPtr->cbWndExtra >= 4 &&
1898 offset == wndPtr->cbWndExtra - sizeof(WORD))
1900 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1902 ERR( "- replaced invalid offset %d with %d\n",
1903 offset, offset2 );
1905 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset2);
1906 WIN_ReleasePtr( wndPtr );
1907 return retvalue;
1909 WARN("Invalid offset %d\n", offset );
1910 WIN_ReleasePtr( wndPtr );
1911 SetLastError( ERROR_INVALID_INDEX );
1912 return 0;
1914 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset);
1915 /* Special case for dialog window procedure */
1916 if ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1917 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, type );
1918 WIN_ReleasePtr( wndPtr );
1919 return retvalue;
1922 switch(offset)
1924 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1925 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1926 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1927 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1928 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type ); break;
1929 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1930 default:
1931 WARN("Unknown offset %d\n", offset );
1932 SetLastError( ERROR_INVALID_INDEX );
1933 break;
1935 WIN_ReleasePtr(wndPtr);
1936 return retvalue;
1940 /**********************************************************************
1941 * WIN_SetWindowLong
1943 * Helper function for SetWindowLong().
1945 * 0 is the failure code. However, in the case of failure SetLastError
1946 * must be set to distinguish between a 0 return value and a failure.
1948 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval,
1949 WINDOWPROCTYPE type )
1951 STYLESTRUCT style;
1952 BOOL ok;
1953 LONG_PTR retval = 0;
1954 WND *wndPtr;
1956 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1958 if (is_broadcast(hwnd))
1960 SetLastError( ERROR_INVALID_PARAMETER );
1961 return FALSE;
1964 if (!(wndPtr = WIN_GetPtr( hwnd )))
1966 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1967 return 0;
1969 if (wndPtr == WND_DESKTOP)
1971 /* can't change anything on the desktop window */
1972 SetLastError( ERROR_ACCESS_DENIED );
1973 return 0;
1975 if (wndPtr == WND_OTHER_PROCESS)
1977 if (offset == GWLP_WNDPROC)
1979 SetLastError( ERROR_ACCESS_DENIED );
1980 return 0;
1982 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1985 /* first some special cases */
1986 switch( offset )
1988 case GWL_STYLE:
1989 case GWL_EXSTYLE:
1990 style.styleOld =
1991 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1992 style.styleNew = newval;
1993 WIN_ReleasePtr( wndPtr );
1994 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1995 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1996 newval = style.styleNew;
1997 break;
1998 case GWLP_HWNDPARENT:
1999 if (wndPtr->parent == GetDesktopWindow())
2001 WIN_ReleasePtr( wndPtr );
2002 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
2004 else
2006 WIN_ReleasePtr( wndPtr );
2007 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
2009 case GWLP_WNDPROC:
2011 WINDOWPROCTYPE old_type = WINPROC_GetProcType( wndPtr->winproc );
2012 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type );
2013 wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, type );
2014 if (old_type == type)
2016 WIN_ReleasePtr( wndPtr );
2017 return retval;
2019 /* update is_unicode flag on the server side */
2020 break;
2022 case GWLP_ID:
2023 case GWLP_HINSTANCE:
2024 case GWLP_USERDATA:
2025 break;
2026 case DWLP_DLGPROC:
2027 if ((wndPtr->cbWndExtra + sizeof(LONG_PTR) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2029 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2030 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, type );
2031 *ptr = WINPROC_AllocProc( (WNDPROC)newval, type );
2032 WIN_ReleasePtr( wndPtr );
2033 return retval;
2035 /* fall through */
2036 default:
2037 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG_PTR)))
2039 WARN("Invalid offset %d\n", offset );
2040 WIN_ReleasePtr( wndPtr );
2041 SetLastError( ERROR_INVALID_INDEX );
2042 return 0;
2044 else
2046 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
2047 if (*ptr == newval) /* already set to the same value */
2049 WIN_ReleasePtr( wndPtr );
2050 return newval;
2053 break;
2056 SERVER_START_REQ( set_window_info )
2058 req->handle = hwnd;
2059 req->extra_offset = -1;
2060 switch(offset)
2062 case GWL_STYLE:
2063 req->flags = SET_WIN_STYLE;
2064 req->style = newval;
2065 break;
2066 case GWL_EXSTYLE:
2067 req->flags = SET_WIN_EXSTYLE;
2068 req->ex_style = newval;
2069 break;
2070 case GWLP_ID:
2071 req->flags = SET_WIN_ID;
2072 req->id = newval;
2073 break;
2074 case GWLP_HINSTANCE:
2075 req->flags = SET_WIN_INSTANCE;
2076 req->instance = (void *)newval;
2077 break;
2078 case GWLP_WNDPROC:
2079 req->flags = SET_WIN_UNICODE;
2080 req->is_unicode = (type == WIN_PROC_32W);
2081 break;
2082 case GWLP_USERDATA:
2083 req->flags = SET_WIN_USERDATA;
2084 req->user_data = (void *)newval;
2085 break;
2086 default:
2087 req->flags = SET_WIN_EXTRA;
2088 req->extra_offset = offset;
2089 req->extra_size = sizeof(newval);
2090 memcpy( &req->extra_value, &newval, sizeof(newval) );
2092 if ((ok = !wine_server_call_err( req )))
2094 switch(offset)
2096 case GWL_STYLE:
2097 wndPtr->dwStyle = newval;
2098 retval = reply->old_style;
2099 break;
2100 case GWL_EXSTYLE:
2101 wndPtr->dwExStyle = newval;
2102 retval = reply->old_ex_style;
2103 break;
2104 case GWLP_ID:
2105 wndPtr->wIDmenu = newval;
2106 retval = reply->old_id;
2107 break;
2108 case GWLP_HINSTANCE:
2109 wndPtr->hInstance = (HINSTANCE)newval;
2110 retval = (ULONG_PTR)reply->old_instance;
2111 break;
2112 case GWLP_WNDPROC:
2113 break;
2114 case GWLP_USERDATA:
2115 wndPtr->userdata = newval;
2116 retval = (ULONG_PTR)reply->old_user_data;
2117 break;
2118 default:
2120 void *ptr = (char *)wndPtr->wExtra + offset;
2121 memcpy( &retval, ptr, sizeof(retval) );
2122 memcpy( ptr, &newval, sizeof(newval) );
2124 break;
2128 SERVER_END_REQ;
2129 WIN_ReleasePtr( wndPtr );
2131 if (!ok) return 0;
2133 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2135 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2136 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2138 return retval;
2142 /**********************************************************************
2143 * GetWindowLong (USER.135)
2145 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2147 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2151 /**********************************************************************
2152 * GetWindowLongA (USER32.@)
2154 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2156 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2160 /**********************************************************************
2161 * GetWindowLongW (USER32.@)
2163 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2165 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2169 /**********************************************************************
2170 * SetWindowLong (USER.136)
2172 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2174 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2178 /**********************************************************************
2179 * SetWindowLongA (USER32.@)
2181 * See SetWindowLongW.
2183 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2185 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2189 /**********************************************************************
2190 * SetWindowLongW (USER32.@) Set window attribute
2192 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2193 * value in a window's extra memory.
2195 * The _hwnd_ parameter specifies the window. is the handle to a
2196 * window that has extra memory. The _newval_ parameter contains the
2197 * new attribute or extra memory value. If positive, the _offset_
2198 * parameter is the byte-addressed location in the window's extra
2199 * memory to set. If negative, _offset_ specifies the window
2200 * attribute to set, and should be one of the following values:
2202 * GWL_EXSTYLE The window's extended window style
2204 * GWL_STYLE The window's window style.
2206 * GWLP_WNDPROC Pointer to the window's window procedure.
2208 * GWLP_HINSTANCE The window's pplication instance handle.
2210 * GWLP_ID The window's identifier.
2212 * GWLP_USERDATA The window's user-specified data.
2214 * If the window is a dialog box, the _offset_ parameter can be one of
2215 * the following values:
2217 * DWLP_DLGPROC The address of the window's dialog box procedure.
2219 * DWLP_MSGRESULT The return value of a message
2220 * that the dialog box procedure processed.
2222 * DWLP_USER Application specific information.
2224 * RETURNS
2226 * If successful, returns the previous value located at _offset_. Otherwise,
2227 * returns 0.
2229 * NOTES
2231 * Extra memory for a window class is specified by a nonzero cbWndExtra
2232 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2233 * time of class creation.
2235 * Using GWL_WNDPROC to set a new window procedure effectively creates
2236 * a window subclass. Use CallWindowProc() in the new windows procedure
2237 * to pass messages to the superclass's window procedure.
2239 * The user data is reserved for use by the application which created
2240 * the window.
2242 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2243 * instead, call the EnableWindow() function to change the window's
2244 * disabled state.
2246 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2247 * SetParent() instead.
2249 * Win95:
2250 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2251 * it sends WM_STYLECHANGING before changing the settings
2252 * and WM_STYLECHANGED afterwards.
2253 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2255 LONG WINAPI SetWindowLongW(
2256 HWND hwnd, /* [in] window to alter */
2257 INT offset, /* [in] offset, in bytes, of location to alter */
2258 LONG newval /* [in] new value of location */
2260 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2264 /*******************************************************************
2265 * GetWindowTextA (USER32.@)
2267 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2269 WCHAR *buffer;
2271 if (!lpString) return 0;
2273 if (WIN_IsCurrentProcess( hwnd ))
2274 return (INT)SendMessageA( 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 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2279 get_server_window_text( hwnd, buffer, nMaxCount );
2280 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2281 lpString[nMaxCount-1] = 0;
2282 HeapFree( GetProcessHeap(), 0, buffer );
2283 return strlen(lpString);
2287 /*******************************************************************
2288 * InternalGetWindowText (USER32.@)
2290 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2292 WND *win;
2294 if (nMaxCount <= 0) return 0;
2295 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2296 if (win == WND_DESKTOP) lpString[0] = 0;
2297 else if (win != WND_OTHER_PROCESS)
2299 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2300 else lpString[0] = 0;
2301 WIN_ReleasePtr( win );
2303 else
2305 get_server_window_text( hwnd, lpString, nMaxCount );
2307 return strlenW(lpString);
2311 /*******************************************************************
2312 * GetWindowTextW (USER32.@)
2314 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2316 if (!lpString) return 0;
2318 if (WIN_IsCurrentProcess( hwnd ))
2319 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2321 /* when window belongs to other process, don't send a message */
2322 if (nMaxCount <= 0) return 0;
2323 get_server_window_text( hwnd, lpString, nMaxCount );
2324 return strlenW(lpString);
2328 /*******************************************************************
2329 * SetWindowTextA (USER32.@)
2330 * SetWindowText (USER32.@)
2332 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2334 if (is_broadcast(hwnd))
2336 SetLastError( ERROR_INVALID_PARAMETER );
2337 return FALSE;
2339 if (!WIN_IsCurrentProcess( hwnd ))
2340 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2341 debugstr_a(lpString), hwnd );
2342 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2346 /*******************************************************************
2347 * SetWindowTextW (USER32.@)
2349 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2351 if (is_broadcast(hwnd))
2353 SetLastError( ERROR_INVALID_PARAMETER );
2354 return FALSE;
2356 if (!WIN_IsCurrentProcess( hwnd ))
2357 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2358 debugstr_w(lpString), hwnd );
2359 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2363 /*******************************************************************
2364 * GetWindowTextLengthA (USER32.@)
2366 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2368 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2371 /*******************************************************************
2372 * GetWindowTextLengthW (USER32.@)
2374 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2376 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2380 /*******************************************************************
2381 * IsWindow (USER32.@)
2383 BOOL WINAPI IsWindow( HWND hwnd )
2385 WND *ptr;
2386 BOOL ret;
2388 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2389 if (ptr == WND_DESKTOP) return TRUE;
2391 if (ptr != WND_OTHER_PROCESS)
2393 WIN_ReleasePtr( ptr );
2394 return TRUE;
2397 /* check other processes */
2398 SERVER_START_REQ( get_window_info )
2400 req->handle = hwnd;
2401 ret = !wine_server_call_err( req );
2403 SERVER_END_REQ;
2404 return ret;
2408 /***********************************************************************
2409 * GetWindowThreadProcessId (USER32.@)
2411 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2413 WND *ptr;
2414 DWORD tid = 0;
2416 if (!(ptr = WIN_GetPtr( hwnd )))
2418 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2419 return 0;
2422 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2424 /* got a valid window */
2425 tid = ptr->tid;
2426 if (process) *process = GetCurrentProcessId();
2427 WIN_ReleasePtr( ptr );
2428 return tid;
2431 /* check other processes */
2432 SERVER_START_REQ( get_window_info )
2434 req->handle = hwnd;
2435 if (!wine_server_call_err( req ))
2437 tid = (DWORD)reply->tid;
2438 if (process) *process = (DWORD)reply->pid;
2441 SERVER_END_REQ;
2442 return tid;
2446 /*****************************************************************
2447 * GetParent (USER32.@)
2449 HWND WINAPI GetParent( HWND hwnd )
2451 WND *wndPtr;
2452 HWND retvalue = 0;
2454 if (!(wndPtr = WIN_GetPtr( hwnd )))
2456 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2457 return 0;
2459 if (wndPtr == WND_DESKTOP) return 0;
2460 if (wndPtr == WND_OTHER_PROCESS)
2462 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2463 if (style & (WS_POPUP | WS_CHILD))
2465 SERVER_START_REQ( get_window_tree )
2467 req->handle = hwnd;
2468 if (!wine_server_call_err( req ))
2470 if (style & WS_POPUP) retvalue = reply->owner;
2471 else if (style & WS_CHILD) retvalue = reply->parent;
2474 SERVER_END_REQ;
2477 else
2479 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2480 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2481 WIN_ReleasePtr( wndPtr );
2483 return retvalue;
2487 /*****************************************************************
2488 * GetAncestor (USER32.@)
2490 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2492 WND *win;
2493 HWND *list, ret = 0;
2495 switch(type)
2497 case GA_PARENT:
2498 if (!(win = WIN_GetPtr( hwnd )))
2500 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2501 return 0;
2503 if (win == WND_DESKTOP) return 0;
2504 if (win != WND_OTHER_PROCESS)
2506 ret = win->parent;
2507 WIN_ReleasePtr( win );
2509 else /* need to query the server */
2511 SERVER_START_REQ( get_window_tree )
2513 req->handle = hwnd;
2514 if (!wine_server_call_err( req )) ret = reply->parent;
2516 SERVER_END_REQ;
2518 break;
2520 case GA_ROOT:
2521 if (!(list = list_window_parents( hwnd ))) return 0;
2523 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2524 else
2526 int count = 2;
2527 while (list[count]) count++;
2528 ret = list[count - 2]; /* get the one before the desktop */
2530 HeapFree( GetProcessHeap(), 0, list );
2531 break;
2533 case GA_ROOTOWNER:
2534 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2535 for (;;)
2537 HWND parent = GetParent( ret );
2538 if (!parent) break;
2539 ret = parent;
2541 break;
2543 return ret;
2547 /*****************************************************************
2548 * SetParent (USER32.@)
2550 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2552 HWND full_handle;
2554 if (is_broadcast(hwnd) || is_broadcast(parent))
2556 SetLastError(ERROR_INVALID_PARAMETER);
2557 return 0;
2560 if (!parent) parent = GetDesktopWindow();
2561 else parent = WIN_GetFullHandle( parent );
2563 if (!IsWindow( parent ))
2565 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2566 return 0;
2569 /* Some applications try to set a child as a parent */
2570 if (IsChild(hwnd, parent))
2572 SetLastError( ERROR_INVALID_PARAMETER );
2573 return 0;
2576 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2577 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2579 return USER_Driver->pSetParent( full_handle, parent );
2583 /*******************************************************************
2584 * IsChild (USER32.@)
2586 BOOL WINAPI IsChild( HWND parent, HWND child )
2588 HWND *list = list_window_parents( child );
2589 int i;
2590 BOOL ret;
2592 if (!list) return FALSE;
2593 parent = WIN_GetFullHandle( parent );
2594 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2595 ret = (list[i] != 0);
2596 HeapFree( GetProcessHeap(), 0, list );
2597 return ret;
2601 /***********************************************************************
2602 * IsWindowVisible (USER32.@)
2604 BOOL WINAPI IsWindowVisible( HWND hwnd )
2606 HWND *list;
2607 BOOL retval;
2608 int i;
2610 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2611 if (!(list = list_window_parents( hwnd ))) return TRUE;
2612 for (i = 0; list[i]; i++)
2613 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2614 retval = !list[i];
2615 HeapFree( GetProcessHeap(), 0, list );
2616 return retval;
2620 /***********************************************************************
2621 * WIN_IsWindowDrawable
2623 * hwnd is drawable when it is visible, all parents are not
2624 * minimized, and it is itself not minimized unless we are
2625 * trying to draw its default class icon.
2627 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2629 HWND *list;
2630 BOOL retval;
2631 int i;
2632 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2634 if (!(style & WS_VISIBLE)) return FALSE;
2635 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2637 if (!(list = list_window_parents( hwnd ))) return TRUE;
2638 for (i = 0; list[i]; i++)
2639 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2640 break;
2641 retval = !list[i];
2642 HeapFree( GetProcessHeap(), 0, list );
2643 return retval;
2647 /*******************************************************************
2648 * GetTopWindow (USER32.@)
2650 HWND WINAPI GetTopWindow( HWND hwnd )
2652 if (!hwnd) hwnd = GetDesktopWindow();
2653 return GetWindow( hwnd, GW_CHILD );
2657 /*******************************************************************
2658 * GetWindow (USER32.@)
2660 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2662 HWND retval = 0;
2664 if (rel == GW_OWNER) /* this one may be available locally */
2666 WND *wndPtr = WIN_GetPtr( hwnd );
2667 if (!wndPtr)
2669 SetLastError( ERROR_INVALID_HANDLE );
2670 return 0;
2672 if (wndPtr == WND_DESKTOP) return 0;
2673 if (wndPtr != WND_OTHER_PROCESS)
2675 retval = wndPtr->owner;
2676 WIN_ReleasePtr( wndPtr );
2677 return retval;
2679 /* else fall through to server call */
2682 SERVER_START_REQ( get_window_tree )
2684 req->handle = hwnd;
2685 if (!wine_server_call_err( req ))
2687 switch(rel)
2689 case GW_HWNDFIRST:
2690 retval = reply->first_sibling;
2691 break;
2692 case GW_HWNDLAST:
2693 retval = reply->last_sibling;
2694 break;
2695 case GW_HWNDNEXT:
2696 retval = reply->next_sibling;
2697 break;
2698 case GW_HWNDPREV:
2699 retval = reply->prev_sibling;
2700 break;
2701 case GW_OWNER:
2702 retval = reply->owner;
2703 break;
2704 case GW_CHILD:
2705 retval = reply->first_child;
2706 break;
2710 SERVER_END_REQ;
2711 return retval;
2715 /*******************************************************************
2716 * ShowOwnedPopups (USER32.@)
2718 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2720 int count = 0;
2721 WND *pWnd;
2722 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2724 if (!win_array) return TRUE;
2726 while (win_array[count]) count++;
2727 while (--count >= 0)
2729 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2730 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2731 if (pWnd == WND_OTHER_PROCESS) continue;
2732 if (fShow)
2734 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2736 WIN_ReleasePtr( pWnd );
2737 /* In Windows, ShowOwnedPopups(TRUE) generates
2738 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2739 * regardless of the state of the owner
2741 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2742 continue;
2745 else
2747 if (pWnd->dwStyle & WS_VISIBLE)
2749 WIN_ReleasePtr( pWnd );
2750 /* In Windows, ShowOwnedPopups(FALSE) generates
2751 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2752 * regardless of the state of the owner
2754 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2755 continue;
2758 WIN_ReleasePtr( pWnd );
2760 HeapFree( GetProcessHeap(), 0, win_array );
2761 return TRUE;
2765 /*******************************************************************
2766 * GetLastActivePopup (USER32.@)
2768 HWND WINAPI GetLastActivePopup( HWND hwnd )
2770 HWND retval = hwnd;
2772 SERVER_START_REQ( get_window_info )
2774 req->handle = hwnd;
2775 if (!wine_server_call_err( req )) retval = reply->last_active;
2777 SERVER_END_REQ;
2778 return retval;
2782 /*******************************************************************
2783 * WIN_ListChildren
2785 * Build an array of the children of a given window. The array must be
2786 * freed with HeapFree. Returns NULL when no windows are found.
2788 HWND *WIN_ListChildren( HWND hwnd )
2790 return list_window_children( hwnd, 0, 0 );
2794 /*******************************************************************
2795 * EnumWindows (USER32.@)
2797 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2799 HWND *list;
2800 BOOL ret = TRUE;
2801 int i;
2803 USER_CheckNotLock();
2805 /* We have to build a list of all windows first, to avoid */
2806 /* unpleasant side-effects, for instance if the callback */
2807 /* function changes the Z-order of the windows. */
2809 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2811 /* Now call the callback function for every window */
2813 for (i = 0; list[i]; i++)
2815 /* Make sure that the window still exists */
2816 if (!IsWindow( list[i] )) continue;
2817 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2819 HeapFree( GetProcessHeap(), 0, list );
2820 return ret;
2824 /**********************************************************************
2825 * EnumThreadWindows (USER32.@)
2827 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2829 HWND *list;
2830 int i;
2832 USER_CheckNotLock();
2834 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2836 /* Now call the callback function for every window */
2838 for (i = 0; list[i]; i++)
2839 if (!func( list[i], lParam )) break;
2840 HeapFree( GetProcessHeap(), 0, list );
2841 return TRUE;
2845 /**********************************************************************
2846 * WIN_EnumChildWindows
2848 * Helper function for EnumChildWindows().
2850 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2852 HWND *childList;
2853 BOOL ret = FALSE;
2855 for ( ; *list; list++)
2857 /* Make sure that the window still exists */
2858 if (!IsWindow( *list )) continue;
2859 /* Build children list first */
2860 childList = WIN_ListChildren( *list );
2862 ret = func( *list, lParam );
2864 if (childList)
2866 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2867 HeapFree( GetProcessHeap(), 0, childList );
2869 if (!ret) return FALSE;
2871 return TRUE;
2875 /**********************************************************************
2876 * EnumChildWindows (USER32.@)
2878 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2880 HWND *list;
2881 BOOL ret;
2883 USER_CheckNotLock();
2885 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2886 ret = WIN_EnumChildWindows( list, func, lParam );
2887 HeapFree( GetProcessHeap(), 0, list );
2888 return ret;
2892 /*******************************************************************
2893 * AnyPopup (USER.52)
2895 BOOL16 WINAPI AnyPopup16(void)
2897 return AnyPopup();
2901 /*******************************************************************
2902 * AnyPopup (USER32.@)
2904 BOOL WINAPI AnyPopup(void)
2906 int i;
2907 BOOL retvalue;
2908 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2910 if (!list) return FALSE;
2911 for (i = 0; list[i]; i++)
2913 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2915 retvalue = (list[i] != 0);
2916 HeapFree( GetProcessHeap(), 0, list );
2917 return retvalue;
2921 /*******************************************************************
2922 * FlashWindow (USER32.@)
2924 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2926 WND *wndPtr;
2928 TRACE("%p\n", hWnd);
2930 if (IsIconic( hWnd ))
2932 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2934 wndPtr = WIN_GetPtr(hWnd);
2935 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2936 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2938 wndPtr->flags |= WIN_NCACTIVATED;
2940 else
2942 wndPtr->flags &= ~WIN_NCACTIVATED;
2944 WIN_ReleasePtr( wndPtr );
2945 return TRUE;
2947 else
2949 WPARAM wparam;
2951 wndPtr = WIN_GetPtr(hWnd);
2952 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2953 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2955 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2956 else wparam = (hWnd == GetForegroundWindow());
2958 WIN_ReleasePtr( wndPtr );
2959 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2960 return wparam;
2964 /*******************************************************************
2965 * FlashWindowEx (USER32.@)
2967 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
2969 FIXME("%p\n", pfwi);
2970 return TRUE;
2973 /*******************************************************************
2974 * GetWindowContextHelpId (USER32.@)
2976 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2978 DWORD retval;
2979 WND *wnd = WIN_GetPtr( hwnd );
2980 if (!wnd || wnd == WND_DESKTOP) return 0;
2981 if (wnd == WND_OTHER_PROCESS)
2983 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2984 return 0;
2986 retval = wnd->helpContext;
2987 WIN_ReleasePtr( wnd );
2988 return retval;
2992 /*******************************************************************
2993 * SetWindowContextHelpId (USER32.@)
2995 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2997 WND *wnd = WIN_GetPtr( hwnd );
2998 if (!wnd || wnd == WND_DESKTOP) return FALSE;
2999 if (wnd == WND_OTHER_PROCESS)
3001 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3002 return 0;
3004 wnd->helpContext = id;
3005 WIN_ReleasePtr( wnd );
3006 return TRUE;
3010 /*******************************************************************
3011 * DragDetect (USER32.@)
3013 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3015 MSG msg;
3016 RECT rect;
3017 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3018 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3020 rect.left = pt.x - wDragWidth;
3021 rect.right = pt.x + wDragWidth;
3023 rect.top = pt.y - wDragHeight;
3024 rect.bottom = pt.y + wDragHeight;
3026 SetCapture(hWnd);
3028 while(1)
3030 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3032 if( msg.message == WM_LBUTTONUP )
3034 ReleaseCapture();
3035 return 0;
3037 if( msg.message == WM_MOUSEMOVE )
3039 POINT tmp;
3040 tmp.x = LOWORD(msg.lParam);
3041 tmp.y = HIWORD(msg.lParam);
3042 if( !PtInRect( &rect, tmp ))
3044 ReleaseCapture();
3045 return 1;
3049 WaitMessage();
3051 return 0;
3054 /******************************************************************************
3055 * GetWindowModuleFileNameA (USER32.@)
3057 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3059 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3060 hwnd, lpszFileName, cchFileNameMax);
3061 return 0;
3064 /******************************************************************************
3065 * GetWindowModuleFileNameW (USER32.@)
3067 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3069 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3070 hwnd, lpszFileName, cchFileNameMax);
3071 return 0;
3074 /******************************************************************************
3075 * GetWindowInfo (USER32.@)
3077 * Note: tests show that Windows doesn't check cbSize of the structure.
3079 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3081 if (!pwi) return FALSE;
3082 if (!IsWindow(hwnd)) return FALSE;
3084 GetWindowRect(hwnd, &pwi->rcWindow);
3085 GetClientRect(hwnd, &pwi->rcClient);
3086 /* translate to screen coordinates */
3087 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3089 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3090 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3091 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3093 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3094 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3096 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3097 pwi->wCreatorVersion = 0x0400;
3099 return TRUE;
3102 /******************************************************************************
3103 * SwitchDesktop (USER32.@)
3105 * NOTES: Sets the current input or interactive desktop.
3107 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3109 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3110 return TRUE;
3113 /*****************************************************************************
3114 * SetLayeredWindowAttributes (USER32.@)
3116 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3117 BYTE bAlpha, DWORD dwFlags )
3119 FIXME("(%p,0x%.8lx,%d,%ld): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3120 return TRUE;
3123 /*****************************************************************************
3124 * UpdateLayeredWindow (USER32.@)
3126 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3127 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3128 DWORD dwFlags)
3130 FIXME("(%p,%p,%p,%p,%p,%p,0x%08lx,%p,%ld): stub!\n",
3131 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3132 return 0;