Delay creation of the internal pos atom until needed.
[wine/testsucceed.git] / dlls / user / win.c
blobfb0b8660d923572f32ee88dda92ee10b23f406b4
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);
43 WINE_DECLARE_DEBUG_CHANNEL(msg);
45 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
46 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
48 /**********************************************************************/
50 /* Desktop window */
51 static HWND hwndDesktop;
53 static WORD wDragWidth = 4;
54 static WORD wDragHeight= 3;
56 static void *user_handles[NB_USER_HANDLES];
58 /***********************************************************************
59 * create_window_handle
61 * Create a window handle with the server.
63 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom,
64 HINSTANCE instance, WINDOWPROCTYPE type )
66 WORD index;
67 WND *win;
68 struct tagCLASS *class = NULL;
69 user_handle_t handle = 0;
70 int extra_bytes = 0;
72 /* if 16-bit instance, map to module handle */
73 if (instance && !HIWORD(instance))
74 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
76 SERVER_START_REQ( create_window )
78 req->parent = parent;
79 req->owner = owner;
80 req->atom = atom;
81 req->instance = instance;
82 if (!wine_server_call_err( req ))
84 handle = reply->handle;
85 extra_bytes = reply->extra;
86 class = reply->class_ptr;
89 SERVER_END_REQ;
91 if (!handle)
93 WARN( "error %ld creating window\n", GetLastError() );
94 return NULL;
97 if (!(win = HeapAlloc( GetProcessHeap(), 0, sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
99 SERVER_START_REQ( destroy_window )
101 req->handle = handle;
102 wine_server_call( req );
104 SERVER_END_REQ;
105 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
106 return NULL;
109 USER_Lock();
111 index = USER_HANDLE_TO_INDEX(handle);
112 assert( index < NB_USER_HANDLES );
113 user_handles[index] = win;
114 win->hwndSelf = handle;
115 win->dwMagic = WND_MAGIC;
116 win->cbWndExtra = extra_bytes;
117 memset( win->wExtra, 0, extra_bytes );
118 CLASS_AddWindow( class, win, type );
119 return win;
123 /***********************************************************************
124 * free_window_handle
126 * Free a window handle.
128 static WND *free_window_handle( HWND hwnd )
130 WND *ptr;
131 WORD index = USER_HANDLE_TO_INDEX(hwnd);
133 if (index >= NB_USER_HANDLES) return NULL;
134 USER_Lock();
135 if ((ptr = user_handles[index]))
137 SERVER_START_REQ( destroy_window )
139 req->handle = hwnd;
140 if (!wine_server_call_err( req ))
142 user_handles[index] = NULL;
143 ptr->dwMagic = 0;
145 else
146 ptr = NULL;
148 SERVER_END_REQ;
150 USER_Unlock();
151 HeapFree( GetProcessHeap(), 0, ptr );
152 return ptr;
156 /*******************************************************************
157 * list_window_children
159 * Build an array of the children of a given window. The array must be
160 * freed with HeapFree. Returns NULL when no windows are found.
162 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
164 HWND *list;
165 int size = 32;
167 for (;;)
169 int count = 0;
171 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
173 SERVER_START_REQ( get_window_children )
175 req->parent = hwnd;
176 req->atom = atom;
177 req->tid = tid;
178 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
179 if (!wine_server_call( req )) count = reply->count;
181 SERVER_END_REQ;
182 if (count && count < size)
184 list[count] = 0;
185 return list;
187 HeapFree( GetProcessHeap(), 0, list );
188 if (!count) break;
189 size = count + 1; /* restart with a large enough buffer */
191 return NULL;
195 /*******************************************************************
196 * list_window_parents
198 * Build an array of all parents of a given window, starting with
199 * the immediate parent. The array must be freed with HeapFree.
200 * Returns NULL if window is a top-level window.
202 static HWND *list_window_parents( HWND hwnd )
204 WND *win;
205 HWND current, *list;
206 int pos = 0, size = 16, count = 0;
208 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
210 current = hwnd;
211 for (;;)
213 if (!(win = WIN_GetPtr( current ))) goto empty;
214 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
215 if (win == WND_DESKTOP)
217 if (!pos) goto empty;
218 list[pos] = 0;
219 return list;
221 list[pos] = current = win->parent;
222 WIN_ReleasePtr( win );
223 if (++pos == size - 1)
225 /* need to grow the list */
226 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
227 if (!new_list) goto empty;
228 list = new_list;
229 size += 16;
233 /* at least one parent belongs to another process, have to query the server */
235 for (;;)
237 count = 0;
238 SERVER_START_REQ( get_window_parents )
240 req->handle = hwnd;
241 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
242 if (!wine_server_call( req )) count = reply->count;
244 SERVER_END_REQ;
245 if (!count) goto empty;
246 if (size > count)
248 list[count] = 0;
249 return list;
251 HeapFree( GetProcessHeap(), 0, list );
252 size = count + 1;
253 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
256 empty:
257 HeapFree( GetProcessHeap(), 0, list );
258 return NULL;
262 /*******************************************************************
263 * send_parent_notify
265 static void send_parent_notify( HWND hwnd, UINT msg )
267 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
268 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
269 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
270 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
274 /*******************************************************************
275 * get_server_window_text
277 * Retrieve the window text from the server.
279 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
281 size_t len = 0;
283 SERVER_START_REQ( get_window_text )
285 req->handle = hwnd;
286 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
287 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
289 SERVER_END_REQ;
290 text[len / sizeof(WCHAR)] = 0;
294 /***********************************************************************
295 * WIN_GetPtr
297 * Return a pointer to the WND structure if local to the process,
298 * or WND_OTHER_PROCESS if handle may be valid in other process.
299 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
301 WND *WIN_GetPtr( HWND hwnd )
303 WND * ptr;
304 WORD index = USER_HANDLE_TO_INDEX(hwnd);
306 if (index >= NB_USER_HANDLES) return NULL;
308 USER_Lock();
309 if ((ptr = user_handles[index]))
311 if (ptr->dwMagic == WND_MAGIC &&
312 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
313 return ptr;
314 ptr = NULL;
316 else if (index == USER_HANDLE_TO_INDEX(hwndDesktop))
318 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
319 else ptr = NULL;
321 else ptr = WND_OTHER_PROCESS;
322 USER_Unlock();
323 return ptr;
327 /***********************************************************************
328 * WIN_IsCurrentProcess
330 * Check whether a given window belongs to the current process (and return the full handle).
332 HWND WIN_IsCurrentProcess( HWND hwnd )
334 WND *ptr;
335 HWND ret;
337 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
338 ret = ptr->hwndSelf;
339 WIN_ReleasePtr( ptr );
340 return ret;
344 /***********************************************************************
345 * WIN_IsCurrentThread
347 * Check whether a given window belongs to the current thread (and return the full handle).
349 HWND WIN_IsCurrentThread( HWND hwnd )
351 WND *ptr;
352 HWND ret = 0;
354 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
355 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
356 WIN_ReleasePtr( ptr );
357 return ret;
361 /***********************************************************************
362 * WIN_Handle32
364 * Convert a 16-bit window handle to a full 32-bit handle.
366 HWND WIN_Handle32( HWND16 hwnd16 )
368 WND *ptr;
369 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
371 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
372 /* do sign extension for -2 and -3 */
373 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
375 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
377 if (ptr == WND_DESKTOP) return GetDesktopWindow();
379 if (ptr != WND_OTHER_PROCESS)
381 hwnd = ptr->hwndSelf;
382 WIN_ReleasePtr( ptr );
384 else /* may belong to another process */
386 SERVER_START_REQ( get_window_info )
388 req->handle = hwnd;
389 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
391 SERVER_END_REQ;
393 return hwnd;
397 /***********************************************************************
398 * WIN_SetOwner
400 * Change the owner of a window.
402 HWND WIN_SetOwner( HWND hwnd, HWND owner )
404 WND *win = WIN_GetPtr( hwnd );
405 HWND ret = 0;
407 if (!win || win == WND_DESKTOP) return 0;
408 if (win == WND_OTHER_PROCESS)
410 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
411 return 0;
413 SERVER_START_REQ( set_window_owner )
415 req->handle = hwnd;
416 req->owner = owner;
417 if (!wine_server_call( req ))
419 win->owner = reply->full_owner;
420 ret = reply->prev_owner;
423 SERVER_END_REQ;
424 WIN_ReleasePtr( win );
425 return ret;
429 /***********************************************************************
430 * WIN_SetStyle
432 * Change the style of a window.
434 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
436 BOOL ok;
437 ULONG new_style, old_style = 0;
438 WND *win = WIN_GetPtr( hwnd );
440 if (!win || win == WND_DESKTOP) return 0;
441 if (win == WND_OTHER_PROCESS)
443 if (IsWindow(hwnd))
444 ERR( "cannot set style %lx/%lx on other process window %p\n",
445 set_bits, clear_bits, hwnd );
446 return 0;
448 new_style = (win->dwStyle | set_bits) & ~clear_bits;
449 if (new_style == win->dwStyle)
451 WIN_ReleasePtr( win );
452 return new_style;
454 SERVER_START_REQ( set_window_info )
456 req->handle = hwnd;
457 req->flags = SET_WIN_STYLE;
458 req->style = new_style;
459 req->extra_offset = -1;
460 if ((ok = !wine_server_call( req )))
462 old_style = reply->old_style;
463 win->dwStyle = new_style;
466 SERVER_END_REQ;
467 WIN_ReleasePtr( win );
468 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, old_style );
469 return old_style;
473 /***********************************************************************
474 * WIN_GetRectangles
476 * Get the window and client rectangles.
478 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
480 WND *win = WIN_GetPtr( hwnd );
481 BOOL ret = TRUE;
483 if (!win) return FALSE;
484 if (win == WND_DESKTOP)
486 RECT rect;
487 rect.left = rect.top = 0;
488 rect.right = GetSystemMetrics(SM_CXSCREEN);
489 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
490 if (rectWindow) *rectWindow = rect;
491 if (rectClient) *rectClient = rect;
493 else if (win == WND_OTHER_PROCESS)
495 SERVER_START_REQ( get_window_rectangles )
497 req->handle = hwnd;
498 if ((ret = !wine_server_call( req )))
500 if (rectWindow)
502 rectWindow->left = reply->window.left;
503 rectWindow->top = reply->window.top;
504 rectWindow->right = reply->window.right;
505 rectWindow->bottom = reply->window.bottom;
507 if (rectClient)
509 rectClient->left = reply->client.left;
510 rectClient->top = reply->client.top;
511 rectClient->right = reply->client.right;
512 rectClient->bottom = reply->client.bottom;
516 SERVER_END_REQ;
518 else
520 if (rectWindow) *rectWindow = win->rectWindow;
521 if (rectClient) *rectClient = win->rectClient;
522 WIN_ReleasePtr( win );
524 return ret;
528 /***********************************************************************
529 * WIN_DestroyWindow
531 * Destroy storage associated to a window. "Internals" p.358
533 LRESULT WIN_DestroyWindow( HWND hwnd )
535 WND *wndPtr;
536 HWND *list;
537 HMENU menu = 0, sys_menu;
539 TRACE("%p\n", hwnd );
541 /* free child windows */
542 if ((list = WIN_ListChildren( hwnd )))
544 int i;
545 for (i = 0; list[i]; i++)
547 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
548 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
550 HeapFree( GetProcessHeap(), 0, list );
553 /* Unlink now so we won't bother with the children later on */
554 SERVER_START_REQ( set_parent )
556 req->handle = hwnd;
557 req->parent = 0;
558 wine_server_call( req );
560 SERVER_END_REQ;
563 * Send the WM_NCDESTROY to the window being destroyed.
565 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
567 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
569 WINPOS_CheckInternalPos( hwnd );
571 /* free resources associated with the window */
573 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
574 if (!(wndPtr->dwStyle & WS_CHILD)) menu = (HMENU)wndPtr->wIDmenu;
575 sys_menu = wndPtr->hSysMenu;
576 WIN_ReleasePtr( wndPtr );
578 if (menu) DestroyMenu( menu );
579 if (sys_menu) DestroyMenu( sys_menu );
581 if (USER_Driver.pDestroyWindow) USER_Driver.pDestroyWindow( hwnd );
583 free_window_handle( hwnd );
584 return 0;
587 /***********************************************************************
588 * WIN_DestroyThreadWindows
590 * Destroy all children of 'wnd' owned by the current thread.
591 * Return TRUE if something was done.
593 void WIN_DestroyThreadWindows( HWND hwnd )
595 HWND *list;
596 int i;
598 if (!(list = WIN_ListChildren( hwnd ))) return;
599 for (i = 0; list[i]; i++)
601 if (WIN_IsCurrentThread( list[i] ))
602 DestroyWindow( list[i] );
603 else
604 WIN_DestroyThreadWindows( list[i] );
606 HeapFree( GetProcessHeap(), 0, list );
609 /***********************************************************************
610 * WIN_CreateDesktopWindow
612 * Create the desktop window.
614 BOOL WIN_CreateDesktopWindow(void)
616 CREATESTRUCTA cs;
618 TRACE("Creating desktop window\n");
620 SERVER_START_REQ( create_window )
622 req->parent = 0;
623 req->owner = 0;
624 req->atom = LOWORD(DESKTOP_CLASS_ATOM);
625 req->instance = 0;
626 if (!wine_server_call_err( req )) hwndDesktop = reply->handle;
628 SERVER_END_REQ;
630 if (!hwndDesktop)
632 ERR( "error %ld creating desktop window\n", GetLastError() );
633 return FALSE;
636 cs.lpCreateParams = NULL;
637 cs.hInstance = 0;
638 cs.hMenu = 0;
639 cs.hwndParent = 0;
640 cs.x = 0;
641 cs.y = 0;
642 cs.cx = GetSystemMetrics( SM_CXSCREEN );
643 cs.cy = GetSystemMetrics( SM_CYSCREEN );
644 cs.style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
645 cs.dwExStyle = 0;
646 cs.lpszName = NULL;
647 cs.lpszClass = DESKTOP_CLASS_ATOM;
649 return USER_Driver.pCreateWindow( hwndDesktop, &cs, TRUE );
653 /***********************************************************************
654 * WIN_FixCoordinates
656 * Fix the coordinates - Helper for WIN_CreateWindowEx.
657 * returns default show mode in sw.
658 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
660 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
662 POINT pos[2];
664 if (cs->dwExStyle & WS_EX_MDICHILD)
666 UINT id = 0;
668 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
669 if (!(cs->style & WS_POPUP)) cs->hMenu = (HMENU)id;
671 TRACE("MDI child id %04x\n", id);
674 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
675 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
677 if (cs->style & (WS_CHILD | WS_POPUP))
679 if (cs->dwExStyle & WS_EX_MDICHILD)
681 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
683 cs->x = pos[0].x;
684 cs->y = pos[0].y;
686 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx)
687 cs->cx = pos[1].x;
688 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy)
689 cs->cy = pos[1].y;
691 else
693 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
694 cs->x = cs->y = 0;
695 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
696 cs->cx = cs->cy = 0;
699 else /* overlapped window */
701 STARTUPINFOW info;
703 GetStartupInfoW( &info );
705 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
707 /* Never believe Microsoft's documentation... CreateWindowEx doc says
708 * that if an overlapped window is created with WS_VISIBLE style bit
709 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
710 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
711 * reveals that
713 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
714 * 2) it does not ignore the y parameter as the docs claim; instead, it
715 * uses it as second parameter to ShowWindow() unless y is either
716 * CW_USEDEFAULT or CW_USEDEFAULT16.
718 * The fact that we didn't do 2) caused bogus windows pop up when wine
719 * was running apps that were using this obscure feature. Example -
720 * calc.exe that comes with Win98 (only Win98, it's different from
721 * the one that comes with Win95 and NT)
723 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
724 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
725 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
728 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
730 if (info.dwFlags & STARTF_USESIZE)
732 cs->cx = info.dwXSize;
733 cs->cy = info.dwYSize;
735 else /* if no other hint from the app, pick 3/4 of the screen real estate */
737 RECT r;
738 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
739 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
740 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
743 /* Handle case where only the cy values is set to default */
744 else if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16)
746 RECT r;
747 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
748 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
752 else
754 /* neither x nor cx are default. Check the y values .
755 * In the trace we see Outlook and Outlook Express using
756 * cy set to CW_USEDEFAULT when opening the address book.
758 if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16) {
759 RECT r;
760 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
761 SystemParametersInfoW( SPI_GETWORKAREA, 0, &r, 0);
762 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
767 /***********************************************************************
768 * dump_window_styles
770 static void dump_window_styles( DWORD style, DWORD exstyle )
772 TRACE( "style:" );
773 if(style & WS_POPUP) TRACE(" WS_POPUP");
774 if(style & WS_CHILD) TRACE(" WS_CHILD");
775 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
776 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
777 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
778 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
779 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
780 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
781 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
782 else
784 if(style & WS_BORDER) TRACE(" WS_BORDER");
785 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
787 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
788 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
789 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
790 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
791 if(style & WS_GROUP) TRACE(" WS_GROUP");
792 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
793 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
794 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
796 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
797 #define DUMPED_STYLES \
798 (WS_POPUP | \
799 WS_CHILD | \
800 WS_MINIMIZE | \
801 WS_VISIBLE | \
802 WS_DISABLED | \
803 WS_CLIPSIBLINGS | \
804 WS_CLIPCHILDREN | \
805 WS_MAXIMIZE | \
806 WS_BORDER | \
807 WS_DLGFRAME | \
808 WS_VSCROLL | \
809 WS_HSCROLL | \
810 WS_SYSMENU | \
811 WS_THICKFRAME | \
812 WS_GROUP | \
813 WS_TABSTOP | \
814 WS_MINIMIZEBOX | \
815 WS_MAXIMIZEBOX)
817 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
818 TRACE("\n");
819 #undef DUMPED_STYLES
821 TRACE( "exstyle:" );
822 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
823 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
824 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
825 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
826 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
827 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
828 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
829 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
830 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
831 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
832 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
833 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
834 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
835 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
836 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
837 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
838 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
839 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
841 #define DUMPED_EX_STYLES \
842 (WS_EX_DLGMODALFRAME | \
843 WS_EX_DRAGDETECT | \
844 WS_EX_NOPARENTNOTIFY | \
845 WS_EX_TOPMOST | \
846 WS_EX_ACCEPTFILES | \
847 WS_EX_TRANSPARENT | \
848 WS_EX_MDICHILD | \
849 WS_EX_TOOLWINDOW | \
850 WS_EX_WINDOWEDGE | \
851 WS_EX_CLIENTEDGE | \
852 WS_EX_CONTEXTHELP | \
853 WS_EX_RIGHT | \
854 WS_EX_RTLREADING | \
855 WS_EX_LEFTSCROLLBAR | \
856 WS_EX_CONTROLPARENT | \
857 WS_EX_STATICEDGE | \
858 WS_EX_APPWINDOW | \
859 WS_EX_LAYERED)
861 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
862 TRACE("\n");
863 #undef DUMPED_EX_STYLES
867 /***********************************************************************
868 * WIN_CreateWindowEx
870 * Implementation of CreateWindowEx().
872 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
873 WINDOWPROCTYPE type )
875 INT sw = SW_SHOW;
876 WND *wndPtr;
877 HWND hwnd, parent, owner, top_child = 0;
878 BOOL unicode = (type == WIN_PROC_32W);
880 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
881 (type == WIN_PROC_32W) ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
882 (type == WIN_PROC_32W) ? debugstr_w((LPCWSTR)cs->lpszClass) : debugstr_a(cs->lpszClass),
883 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
884 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
886 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
888 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
889 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
891 /* Fix the styles for MDI children */
892 if (cs->dwExStyle & WS_EX_MDICHILD)
894 MDICREATESTRUCTA mdi_cs;
895 UINT flags = 0;
897 wndPtr = WIN_GetPtr(cs->hwndParent);
898 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
900 flags = wndPtr->flags;
901 WIN_ReleasePtr(wndPtr);
904 if (!(flags & WIN_ISMDICLIENT))
906 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
907 return 0;
910 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
911 * MDICREATESTRUCT members have the originally passed values.
913 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
914 * have the same layout.
916 mdi_cs.szClass = cs->lpszClass;
917 mdi_cs.szTitle = cs->lpszName;
918 mdi_cs.hOwner = cs->hInstance;
919 mdi_cs.x = cs->x;
920 mdi_cs.y = cs->y;
921 mdi_cs.cx = cs->cx;
922 mdi_cs.cy = cs->cy;
923 mdi_cs.style = cs->style;
924 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
926 cs->lpCreateParams = (LPVOID)&mdi_cs;
928 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
930 if (cs->style & WS_POPUP)
932 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
933 return 0;
935 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
937 else
939 cs->style &= ~WS_POPUP;
940 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
941 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
944 top_child = GetWindow(cs->hwndParent, GW_CHILD);
946 if (top_child)
948 /* Restore current maximized child */
949 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
951 TRACE("Restoring current maximized child %p\n", top_child);
952 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
953 ShowWindow(top_child, SW_RESTORE);
954 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
959 /* Find the parent window */
961 parent = GetDesktopWindow();
962 owner = 0;
964 if (cs->hwndParent == HWND_MESSAGE)
966 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
967 * message window (style: WS_POPUP|WS_DISABLED)
969 FIXME("Parent is HWND_MESSAGE\n");
971 else if (cs->hwndParent)
973 /* Make sure parent is valid */
974 if (!IsWindow( cs->hwndParent ))
976 WARN("Bad parent %p\n", cs->hwndParent );
977 return 0;
979 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
980 parent = WIN_GetFullHandle(cs->hwndParent);
981 else
982 owner = GetAncestor( cs->hwndParent, GA_ROOT );
984 else if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
986 WARN("No parent for child window\n" );
987 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
990 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
992 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
993 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
994 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
995 cs->dwExStyle |= WS_EX_WINDOWEDGE;
996 else
997 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
999 /* Create the window structure */
1001 if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type )))
1003 TRACE("out of memory\n" );
1004 return 0;
1006 hwnd = wndPtr->hwndSelf;
1008 /* Fill the window structure */
1010 wndPtr->tid = GetCurrentThreadId();
1011 wndPtr->owner = owner;
1012 wndPtr->parent = parent;
1013 wndPtr->hInstance = cs->hInstance;
1014 wndPtr->text = NULL;
1015 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1016 wndPtr->dwExStyle = cs->dwExStyle;
1017 wndPtr->wIDmenu = 0;
1018 wndPtr->helpContext = 0;
1019 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1020 wndPtr->pVScroll = NULL;
1021 wndPtr->pHScroll = NULL;
1022 wndPtr->userdata = 0;
1023 wndPtr->hIcon = 0;
1024 wndPtr->hIconSmall = 0;
1025 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, (HMENU)-1 ) : 0;
1028 * Correct the window styles.
1030 * It affects only the style loaded into the WIN structure.
1033 if (!(wndPtr->dwStyle & WS_CHILD))
1035 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1036 if (!(wndPtr->dwStyle & WS_POPUP))
1037 wndPtr->dwStyle |= WS_CAPTION;
1041 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1042 * why does the user get to set it?
1045 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1046 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1047 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1048 else
1049 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1051 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1052 wndPtr->flags |= WIN_NEED_SIZE;
1054 SERVER_START_REQ( set_window_info )
1056 req->handle = hwnd;
1057 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1058 req->style = wndPtr->dwStyle;
1059 req->ex_style = wndPtr->dwExStyle;
1060 req->instance = (void *)wndPtr->hInstance;
1061 req->is_unicode = (type == WIN_PROC_32W);
1062 req->extra_offset = -1;
1063 wine_server_call( req );
1065 SERVER_END_REQ;
1067 /* Set the window menu */
1069 if (((wndPtr->dwStyle & (WS_CAPTION|WS_CHILD)) == WS_CAPTION) ||
1070 (wndPtr->dwExStyle & WS_EX_APPWINDOW))
1072 if (cs->hMenu) MENU_SetMenu(hwnd, cs->hMenu);
1073 else
1075 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1076 if (menuName)
1078 if (HIWORD(cs->hInstance))
1079 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1080 else
1081 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1083 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1087 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1088 WIN_ReleasePtr( wndPtr );
1090 if (!USER_Driver.pCreateWindow || !USER_Driver.pCreateWindow( hwnd, cs, unicode))
1092 WIN_DestroyWindow( hwnd );
1093 return 0;
1096 /* Notify the parent window only */
1098 send_parent_notify( hwnd, WM_CREATE );
1099 if (!IsWindow( hwnd )) return 0;
1101 if (cs->style & WS_VISIBLE)
1103 if (cs->style & WS_MAXIMIZE)
1104 sw = SW_SHOWMAXIMIZED;
1105 else if (cs->style & WS_MINIMIZE)
1106 sw = SW_SHOWMINIMIZED;
1108 ShowWindow( hwnd, sw );
1109 if (cs->dwExStyle & WS_EX_MDICHILD)
1111 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1112 /* ShowWindow won't activate child windows */
1113 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1117 /* Call WH_SHELL hook */
1119 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1120 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1122 TRACE("created window %p\n", hwnd);
1123 return hwnd;
1127 /***********************************************************************
1128 * CreateWindow (USER.41)
1130 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1131 DWORD style, INT16 x, INT16 y, INT16 width,
1132 INT16 height, HWND16 parent, HMENU16 menu,
1133 HINSTANCE16 instance, LPVOID data )
1135 return CreateWindowEx16( 0, className, windowName, style,
1136 x, y, width, height, parent, menu, instance, data );
1140 /***********************************************************************
1141 * CreateWindowEx (USER.452)
1143 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1144 LPCSTR windowName, DWORD style, INT16 x,
1145 INT16 y, INT16 width, INT16 height,
1146 HWND16 parent, HMENU16 menu,
1147 HINSTANCE16 instance, LPVOID data )
1149 ATOM classAtom;
1150 CREATESTRUCTA cs;
1151 char buffer[256];
1153 /* Find the class atom */
1155 if (HIWORD(className))
1157 if (!(classAtom = GlobalFindAtomA( className )))
1159 ERR( "bad class name %s\n", debugstr_a(className) );
1160 return 0;
1163 else
1165 classAtom = LOWORD(className);
1166 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1168 ERR( "bad atom %x\n", classAtom);
1169 return 0;
1171 className = buffer;
1174 /* Fix the coordinates */
1176 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1177 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1178 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1179 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1181 /* Create the window */
1183 cs.lpCreateParams = data;
1184 cs.hInstance = HINSTANCE_32(instance);
1185 cs.hMenu = HMENU_32(menu);
1186 cs.hwndParent = WIN_Handle32( parent );
1187 cs.style = style;
1188 cs.lpszName = windowName;
1189 cs.lpszClass = className;
1190 cs.dwExStyle = exStyle;
1192 return HWND_16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1196 /***********************************************************************
1197 * CreateWindowExA (USER32.@)
1199 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1200 LPCSTR windowName, DWORD style, INT x,
1201 INT y, INT width, INT height,
1202 HWND parent, HMENU menu,
1203 HINSTANCE instance, LPVOID data )
1205 ATOM classAtom;
1206 CREATESTRUCTA cs;
1207 char buffer[256];
1209 /* Find the class atom */
1211 if (HIWORD(className))
1213 if (!(classAtom = GlobalFindAtomA( className )))
1215 ERR( "bad class name %s\n", debugstr_a(className) );
1216 return 0;
1219 else
1221 classAtom = LOWORD(className);
1222 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1224 ERR( "bad atom %x\n", classAtom);
1225 return 0;
1227 className = buffer;
1230 /* Create the window */
1232 cs.lpCreateParams = data;
1233 cs.hInstance = instance;
1234 cs.hMenu = menu;
1235 cs.hwndParent = parent;
1236 cs.x = x;
1237 cs.y = y;
1238 cs.cx = width;
1239 cs.cy = height;
1240 cs.style = style;
1241 cs.lpszName = windowName;
1242 cs.lpszClass = className;
1243 cs.dwExStyle = exStyle;
1245 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1249 /***********************************************************************
1250 * CreateWindowExW (USER32.@)
1252 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1253 LPCWSTR windowName, DWORD style, INT x,
1254 INT y, INT width, INT height,
1255 HWND parent, HMENU menu,
1256 HINSTANCE instance, LPVOID data )
1258 ATOM classAtom;
1259 CREATESTRUCTW cs;
1260 WCHAR buffer[256];
1262 /* Find the class atom */
1264 if (HIWORD(className))
1266 if (!(classAtom = GlobalFindAtomW( className )))
1268 ERR( "bad class name %s\n", debugstr_w(className) );
1269 return 0;
1272 else
1274 classAtom = LOWORD(className);
1275 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1277 ERR( "bad atom %x\n", classAtom);
1278 return 0;
1280 className = buffer;
1283 /* Create the window */
1285 cs.lpCreateParams = data;
1286 cs.hInstance = instance;
1287 cs.hMenu = menu;
1288 cs.hwndParent = parent;
1289 cs.x = x;
1290 cs.y = y;
1291 cs.cx = width;
1292 cs.cy = height;
1293 cs.style = style;
1294 cs.lpszName = windowName;
1295 cs.lpszClass = className;
1296 cs.dwExStyle = exStyle;
1298 /* Note: we rely on the fact that CREATESTRUCTA and */
1299 /* CREATESTRUCTW have the same layout. */
1300 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1304 /***********************************************************************
1305 * WIN_SendDestroyMsg
1307 static void WIN_SendDestroyMsg( HWND hwnd )
1309 GUITHREADINFO info;
1311 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1313 if (hwnd == info.hwndCaret) DestroyCaret();
1314 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1316 if (USER_Driver.pResetSelectionOwner)
1317 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1320 * Send the WM_DESTROY to the window.
1322 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1325 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1326 * make sure that the window still exists when we come back.
1328 if (IsWindow(hwnd))
1330 HWND* pWndArray;
1331 int i;
1333 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1335 for (i = 0; pWndArray[i]; i++)
1337 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1339 HeapFree( GetProcessHeap(), 0, pWndArray );
1341 else
1342 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1346 /***********************************************************************
1347 * DestroyWindow (USER32.@)
1349 BOOL WINAPI DestroyWindow( HWND hwnd )
1351 BOOL is_child;
1353 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1355 SetLastError( ERROR_ACCESS_DENIED );
1356 return FALSE;
1359 TRACE("(%p)\n", hwnd);
1361 /* Call hooks */
1363 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1365 if (MENU_IsMenuActive() == hwnd)
1366 EndMenu();
1368 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1370 if (is_child)
1372 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1373 send_parent_notify( hwnd, WM_DESTROY );
1375 else if (!GetWindow( hwnd, GW_OWNER ))
1377 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1378 /* FIXME: clean up palette - see "Internals" p.352 */
1381 if (!IsWindow(hwnd)) return TRUE;
1383 if (USER_Driver.pResetSelectionOwner)
1384 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1386 /* Hide the window */
1387 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1389 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1390 if (is_child)
1391 ShowWindow( hwnd, SW_HIDE );
1392 else
1393 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1394 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1397 if (!IsWindow(hwnd)) return TRUE;
1399 /* Recursively destroy owned windows */
1401 if (!is_child)
1403 for (;;)
1405 int i, got_one = 0;
1406 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1407 if (list)
1409 for (i = 0; list[i]; i++)
1411 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1412 if (WIN_IsCurrentThread( list[i] ))
1414 DestroyWindow( list[i] );
1415 got_one = 1;
1416 continue;
1418 WIN_SetOwner( list[i], 0 );
1420 HeapFree( GetProcessHeap(), 0, list );
1422 if (!got_one) break;
1426 /* Send destroy messages */
1428 WIN_SendDestroyMsg( hwnd );
1429 if (!IsWindow( hwnd )) return TRUE;
1431 if (GetClipboardOwner() == hwnd)
1432 CLIPBOARD_ReleaseOwner();
1434 /* Destroy the window storage */
1436 WIN_DestroyWindow( hwnd );
1437 return TRUE;
1441 /***********************************************************************
1442 * CloseWindow (USER32.@)
1444 BOOL WINAPI CloseWindow( HWND hwnd )
1446 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1447 ShowWindow( hwnd, SW_MINIMIZE );
1448 return TRUE;
1452 /***********************************************************************
1453 * OpenIcon (USER32.@)
1455 BOOL WINAPI OpenIcon( HWND hwnd )
1457 if (!IsIconic( hwnd )) return FALSE;
1458 ShowWindow( hwnd, SW_SHOWNORMAL );
1459 return TRUE;
1463 /***********************************************************************
1464 * WIN_FindWindow
1466 * Implementation of FindWindow() and FindWindowEx().
1468 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1470 HWND *list = NULL;
1471 HWND retvalue = 0;
1472 int i = 0, len = 0;
1473 WCHAR *buffer = NULL;
1475 if (!parent) parent = GetDesktopWindow();
1476 if (title)
1478 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1479 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1482 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1484 if (child)
1486 child = WIN_GetFullHandle( child );
1487 while (list[i] && list[i] != child) i++;
1488 if (!list[i]) goto done;
1489 i++; /* start from next window */
1492 if (title)
1494 while (list[i])
1496 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1497 i++;
1500 retvalue = list[i];
1502 done:
1503 HeapFree( GetProcessHeap(), 0, list );
1504 HeapFree( GetProcessHeap(), 0, buffer );
1505 return retvalue;
1510 /***********************************************************************
1511 * FindWindowA (USER32.@)
1513 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1515 HWND ret = FindWindowExA( 0, 0, className, title );
1516 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1517 return ret;
1521 /***********************************************************************
1522 * FindWindowExA (USER32.@)
1524 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1525 LPCSTR className, LPCSTR title )
1527 ATOM atom = 0;
1528 LPWSTR buffer;
1529 HWND hwnd;
1530 INT len;
1532 if (className)
1534 /* If the atom doesn't exist, then no class */
1535 /* with this name exists either. */
1536 if (!(atom = GlobalFindAtomA( className )))
1538 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1539 return 0;
1542 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1544 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1545 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1546 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1547 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1548 HeapFree( GetProcessHeap(), 0, buffer );
1549 return hwnd;
1553 /***********************************************************************
1554 * FindWindowExW (USER32.@)
1556 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1557 LPCWSTR className, LPCWSTR title )
1559 ATOM atom = 0;
1561 if (className)
1563 /* If the atom doesn't exist, then no class */
1564 /* with this name exists either. */
1565 if (!(atom = GlobalFindAtomW( className )))
1567 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1568 return 0;
1571 return WIN_FindWindow( parent, child, atom, title );
1575 /***********************************************************************
1576 * FindWindowW (USER32.@)
1578 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1580 return FindWindowExW( 0, 0, className, title );
1584 /**********************************************************************
1585 * GetDesktopWindow (USER32.@)
1587 HWND WINAPI GetDesktopWindow(void)
1589 if (hwndDesktop) return hwndDesktop;
1590 ERR( "Wine init error: either you're trying to use an invalid native USER.EXE config, or some graphics/GUI libraries or DLLs didn't initialize properly. Aborting.\n" );
1591 ExitProcess(1);
1592 return 0;
1596 /*******************************************************************
1597 * EnableWindow (USER32.@)
1599 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1601 BOOL retvalue;
1602 HWND full_handle;
1604 if (is_broadcast(hwnd))
1606 SetLastError( ERROR_INVALID_PARAMETER );
1607 return FALSE;
1610 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1611 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1613 hwnd = full_handle;
1615 TRACE("( %p, %d )\n", hwnd, enable);
1617 retvalue = !IsWindowEnabled( hwnd );
1619 if (enable && retvalue)
1621 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1622 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1624 else if (!enable && !retvalue)
1626 HWND capture_wnd;
1628 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1630 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1632 if (hwnd == GetFocus())
1633 SetFocus( 0 ); /* A disabled window can't have the focus */
1635 capture_wnd = GetCapture();
1636 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1637 ReleaseCapture(); /* A disabled window can't capture the mouse */
1639 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1641 return retvalue;
1645 /***********************************************************************
1646 * IsWindowEnabled (USER32.@)
1648 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1650 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1654 /***********************************************************************
1655 * IsWindowUnicode (USER32.@)
1657 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1659 WND * wndPtr;
1660 BOOL retvalue = FALSE;
1662 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1664 if (wndPtr == WND_DESKTOP) return TRUE;
1666 if (wndPtr != WND_OTHER_PROCESS)
1668 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1669 WIN_ReleasePtr( wndPtr );
1671 else
1673 SERVER_START_REQ( get_window_info )
1675 req->handle = hwnd;
1676 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1678 SERVER_END_REQ;
1680 return retvalue;
1684 /**********************************************************************
1685 * GetWindowWord (USER32.@)
1687 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1689 if (offset >= 0)
1691 WORD retvalue = 0;
1692 WND *wndPtr = WIN_GetPtr( hwnd );
1693 if (!wndPtr)
1695 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1696 return 0;
1698 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1700 SERVER_START_REQ( set_window_info )
1702 req->handle = hwnd;
1703 req->flags = 0; /* don't set anything, just retrieve */
1704 req->extra_offset = offset;
1705 req->extra_size = sizeof(retvalue);
1706 if (!wine_server_call_err( req ))
1707 memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
1709 SERVER_END_REQ;
1710 return retvalue;
1712 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1714 WARN("Invalid offset %d\n", offset );
1715 SetLastError( ERROR_INVALID_INDEX );
1717 else memcpy( &retvalue, (char *)wndPtr->wExtra + offset, sizeof(retvalue) );
1718 WIN_ReleasePtr( wndPtr );
1719 return retvalue;
1722 switch(offset)
1724 case GWLP_HWNDPARENT:
1725 return GetWindowLongPtrW( hwnd, offset );
1726 case GWLP_ID:
1727 case GWLP_HINSTANCE:
1729 LONG_PTR ret = GetWindowLongPtrW( hwnd, offset );
1730 if (HIWORD(ret))
1731 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1732 return LOWORD(ret);
1734 default:
1735 WARN("Invalid offset %d\n", offset );
1736 return 0;
1741 /**********************************************************************
1742 * SetWindowWord (USER32.@)
1744 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1746 WORD retval = 0;
1747 WND * wndPtr;
1749 switch(offset)
1751 case GWLP_ID:
1752 case GWLP_HINSTANCE:
1753 case GWLP_HWNDPARENT:
1754 return SetWindowLongPtrW( hwnd, offset, (ULONG_PTR)newval );
1755 default:
1756 if (offset < 0)
1758 WARN("Invalid offset %d\n", offset );
1759 SetLastError( ERROR_INVALID_INDEX );
1760 return 0;
1764 wndPtr = WIN_GetPtr( hwnd );
1765 if (wndPtr == WND_DESKTOP)
1767 SetLastError( ERROR_ACCESS_DENIED );
1768 return 0;
1770 if (wndPtr == WND_OTHER_PROCESS)
1772 if (IsWindow(hwnd))
1773 FIXME( "set %d <- %x not supported yet on other process window %p\n",
1774 offset, newval, hwnd );
1775 wndPtr = NULL;
1777 if (!wndPtr)
1779 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1780 return 0;
1783 if (offset > (int)(wndPtr->cbWndExtra - sizeof(WORD)))
1785 WARN("Invalid offset %d\n", offset );
1786 WIN_ReleasePtr(wndPtr);
1787 SetLastError( ERROR_INVALID_INDEX );
1788 return 0;
1791 SERVER_START_REQ( set_window_info )
1793 req->handle = hwnd;
1794 req->flags = SET_WIN_EXTRA;
1795 req->extra_offset = offset;
1796 req->extra_size = sizeof(newval);
1797 memcpy( &req->extra_value, &newval, sizeof(newval) );
1798 if (!wine_server_call_err( req ))
1800 void *ptr = (char *)wndPtr->wExtra + offset;
1801 memcpy( &retval, ptr, sizeof(retval) );
1802 memcpy( ptr, &newval, sizeof(newval) );
1805 SERVER_END_REQ;
1806 WIN_ReleasePtr( wndPtr );
1807 return retval;
1811 /**********************************************************************
1812 * WIN_GetWindowLong
1814 * Helper function for GetWindowLong().
1816 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1818 LONG_PTR retvalue = 0;
1819 WND *wndPtr;
1821 if (offset == GWLP_HWNDPARENT)
1823 HWND parent = GetAncestor( hwnd, GA_PARENT );
1824 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1825 return (ULONG_PTR)parent;
1828 if (!(wndPtr = WIN_GetPtr( hwnd )))
1830 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1831 return 0;
1834 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1836 if (offset == GWLP_WNDPROC)
1838 SetLastError( ERROR_ACCESS_DENIED );
1839 return 0;
1841 SERVER_START_REQ( set_window_info )
1843 req->handle = hwnd;
1844 req->flags = 0; /* don't set anything, just retrieve */
1845 req->extra_offset = (offset >= 0) ? offset : -1;
1846 req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
1847 if (!wine_server_call_err( req ))
1849 switch(offset)
1851 case GWL_STYLE: retvalue = reply->old_style; break;
1852 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1853 case GWLP_ID: retvalue = reply->old_id; break;
1854 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1855 case GWLP_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1856 default:
1857 if (offset >= 0) retvalue = reply->old_extra_value;
1858 else SetLastError( ERROR_INVALID_INDEX );
1859 break;
1863 SERVER_END_REQ;
1864 return retvalue;
1867 /* now we have a valid wndPtr */
1869 if (offset >= 0)
1871 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
1874 * Some programs try to access last element from 16 bit
1875 * code using illegal offset value. Hopefully this is
1876 * what those programs really expect.
1878 if (type == WIN_PROC_16 &&
1879 wndPtr->cbWndExtra >= 4 &&
1880 offset == wndPtr->cbWndExtra - sizeof(WORD))
1882 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
1884 ERR( "- replaced invalid offset %d with %d\n",
1885 offset, offset2 );
1887 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset2);
1888 WIN_ReleasePtr( wndPtr );
1889 return retvalue;
1891 WARN("Invalid offset %d\n", offset );
1892 WIN_ReleasePtr( wndPtr );
1893 SetLastError( ERROR_INVALID_INDEX );
1894 return 0;
1896 retvalue = *(LONG_PTR *)(((char *)wndPtr->wExtra) + offset);
1897 /* Special case for dialog window procedure */
1898 if ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1899 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, type );
1900 WIN_ReleasePtr( wndPtr );
1901 return retvalue;
1904 switch(offset)
1906 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1907 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1908 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1909 case GWLP_ID: retvalue = (ULONG_PTR)wndPtr->wIDmenu; break;
1910 case GWLP_WNDPROC: retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type ); break;
1911 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1912 default:
1913 WARN("Unknown offset %d\n", offset );
1914 SetLastError( ERROR_INVALID_INDEX );
1915 break;
1917 WIN_ReleasePtr(wndPtr);
1918 return retvalue;
1922 /**********************************************************************
1923 * WIN_SetWindowLong
1925 * Helper function for SetWindowLong().
1927 * 0 is the failure code. However, in the case of failure SetLastError
1928 * must be set to distinguish between a 0 return value and a failure.
1930 static LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, LONG_PTR newval,
1931 WINDOWPROCTYPE type )
1933 STYLESTRUCT style;
1934 BOOL ok;
1935 LONG_PTR retval = 0;
1936 WND *wndPtr;
1938 TRACE( "%p %d %lx %x\n", hwnd, offset, newval, type );
1940 if (is_broadcast(hwnd))
1942 SetLastError( ERROR_INVALID_PARAMETER );
1943 return FALSE;
1946 if (!(wndPtr = WIN_GetPtr( hwnd )))
1948 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1949 return 0;
1951 if (wndPtr == WND_DESKTOP)
1953 /* can't change anything on the desktop window */
1954 SetLastError( ERROR_ACCESS_DENIED );
1955 return 0;
1957 if (wndPtr == WND_OTHER_PROCESS)
1959 if (offset == GWLP_WNDPROC)
1961 SetLastError( ERROR_ACCESS_DENIED );
1962 return 0;
1964 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1967 /* first some special cases */
1968 switch( offset )
1970 case GWL_STYLE:
1971 case GWL_EXSTYLE:
1972 style.styleOld =
1973 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1974 style.styleNew = newval;
1975 WIN_ReleasePtr( wndPtr );
1976 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1977 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1978 newval = style.styleNew;
1979 break;
1980 case GWLP_HWNDPARENT:
1981 if (wndPtr->parent == GetDesktopWindow())
1983 WIN_ReleasePtr( wndPtr );
1984 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1986 else
1988 WIN_ReleasePtr( wndPtr );
1989 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1991 case GWLP_WNDPROC:
1993 WINDOWPROCTYPE old_type = WINPROC_GetProcType( wndPtr->winproc );
1994 retval = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, type );
1995 wndPtr->winproc = WINPROC_AllocProc( (WNDPROC)newval, type );
1996 if (old_type == type)
1998 WIN_ReleasePtr( wndPtr );
1999 return retval;
2001 /* update is_unicode flag on the server side */
2002 break;
2004 case GWLP_ID:
2005 case GWLP_HINSTANCE:
2006 case GWLP_USERDATA:
2007 break;
2008 case DWLP_DLGPROC:
2009 if ((wndPtr->cbWndExtra + sizeof(LONG_PTR) >= DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
2011 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
2012 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, type );
2013 *ptr = WINPROC_AllocProc( (WNDPROC)newval, type );
2014 WIN_ReleasePtr( wndPtr );
2015 return retval;
2017 /* fall through */
2018 default:
2019 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - sizeof(LONG_PTR)))
2021 WARN("Invalid offset %d\n", offset );
2022 WIN_ReleasePtr( wndPtr );
2023 SetLastError( ERROR_INVALID_INDEX );
2024 return 0;
2026 else
2028 LONG_PTR *ptr = (LONG_PTR *)((char *)wndPtr->wExtra + offset);
2029 if (*ptr == newval) /* already set to the same value */
2031 WIN_ReleasePtr( wndPtr );
2032 return newval;
2035 break;
2038 SERVER_START_REQ( set_window_info )
2040 req->handle = hwnd;
2041 req->extra_offset = -1;
2042 switch(offset)
2044 case GWL_STYLE:
2045 req->flags = SET_WIN_STYLE;
2046 req->style = newval;
2047 break;
2048 case GWL_EXSTYLE:
2049 req->flags = SET_WIN_EXSTYLE;
2050 req->ex_style = newval;
2051 break;
2052 case GWLP_ID:
2053 req->flags = SET_WIN_ID;
2054 req->id = newval;
2055 break;
2056 case GWLP_HINSTANCE:
2057 req->flags = SET_WIN_INSTANCE;
2058 req->instance = (void *)newval;
2059 break;
2060 case GWLP_WNDPROC:
2061 req->flags = SET_WIN_UNICODE;
2062 req->is_unicode = (type == WIN_PROC_32W);
2063 break;
2064 case GWLP_USERDATA:
2065 req->flags = SET_WIN_USERDATA;
2066 req->user_data = (void *)newval;
2067 break;
2068 default:
2069 req->flags = SET_WIN_EXTRA;
2070 req->extra_offset = offset;
2071 req->extra_size = sizeof(newval);
2072 memcpy( &req->extra_value, &newval, sizeof(newval) );
2074 if ((ok = !wine_server_call_err( req )))
2076 switch(offset)
2078 case GWL_STYLE:
2079 wndPtr->dwStyle = newval;
2080 retval = reply->old_style;
2081 break;
2082 case GWL_EXSTYLE:
2083 wndPtr->dwExStyle = newval;
2084 retval = reply->old_ex_style;
2085 break;
2086 case GWLP_ID:
2087 wndPtr->wIDmenu = newval;
2088 retval = reply->old_id;
2089 break;
2090 case GWLP_HINSTANCE:
2091 wndPtr->hInstance = (HINSTANCE)newval;
2092 retval = (ULONG_PTR)reply->old_instance;
2093 break;
2094 case GWLP_WNDPROC:
2095 break;
2096 case GWLP_USERDATA:
2097 wndPtr->userdata = newval;
2098 retval = (ULONG_PTR)reply->old_user_data;
2099 break;
2100 default:
2102 void *ptr = (char *)wndPtr->wExtra + offset;
2103 memcpy( &retval, ptr, sizeof(retval) );
2104 memcpy( ptr, &newval, sizeof(newval) );
2106 break;
2110 SERVER_END_REQ;
2111 WIN_ReleasePtr( wndPtr );
2113 if (!ok) return 0;
2115 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2116 USER_Driver.pSetWindowStyle( hwnd, retval );
2118 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2119 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2121 return retval;
2125 /**********************************************************************
2126 * GetWindowLong (USER.135)
2128 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2130 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2134 /**********************************************************************
2135 * GetWindowLongA (USER32.@)
2137 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2139 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2143 /**********************************************************************
2144 * GetWindowLongW (USER32.@)
2146 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2148 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2152 /**********************************************************************
2153 * SetWindowLong (USER.136)
2155 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2157 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2161 /**********************************************************************
2162 * SetWindowLongA (USER32.@)
2164 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2166 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2170 /**********************************************************************
2171 * SetWindowLongW (USER32.@) Set window attribute
2173 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2174 * value in a window's extra memory.
2176 * The _hwnd_ parameter specifies the window. is the handle to a
2177 * window that has extra memory. The _newval_ parameter contains the
2178 * new attribute or extra memory value. If positive, the _offset_
2179 * parameter is the byte-addressed location in the window's extra
2180 * memory to set. If negative, _offset_ specifies the window
2181 * attribute to set, and should be one of the following values:
2183 * GWL_EXSTYLE The window's extended window style
2185 * GWL_STYLE The window's window style.
2187 * GWLP_WNDPROC Pointer to the window's window procedure.
2189 * GWLP_HINSTANCE The window's pplication instance handle.
2191 * GWLP_ID The window's identifier.
2193 * GWLP_USERDATA The window's user-specified data.
2195 * If the window is a dialog box, the _offset_ parameter can be one of
2196 * the following values:
2198 * DWLP_DLGPROC The address of the window's dialog box procedure.
2200 * DWLP_MSGRESULT The return value of a message
2201 * that the dialog box procedure processed.
2203 * DWLP_USER Application specific information.
2205 * RETURNS
2207 * If successful, returns the previous value located at _offset_. Otherwise,
2208 * returns 0.
2210 * NOTES
2212 * Extra memory for a window class is specified by a nonzero cbWndExtra
2213 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2214 * time of class creation.
2216 * Using GWL_WNDPROC to set a new window procedure effectively creates
2217 * a window subclass. Use CallWindowProc() in the new windows procedure
2218 * to pass messages to the superclass's window procedure.
2220 * The user data is reserved for use by the application which created
2221 * the window.
2223 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2224 * instead, call the EnableWindow() function to change the window's
2225 * disabled state.
2227 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2228 * SetParent() instead.
2230 * Win95:
2231 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2232 * it sends WM_STYLECHANGING before changing the settings
2233 * and WM_STYLECHANGED afterwards.
2234 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2236 LONG WINAPI SetWindowLongW(
2237 HWND hwnd, /* [in] window to alter */
2238 INT offset, /* [in] offset, in bytes, of location to alter */
2239 LONG newval /* [in] new value of location */
2241 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2245 /*******************************************************************
2246 * GetWindowTextA (USER32.@)
2248 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2250 WCHAR *buffer;
2252 if (!lpString) return 0;
2254 if (WIN_IsCurrentProcess( hwnd ))
2255 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2257 /* when window belongs to other process, don't send a message */
2258 if (nMaxCount <= 0) return 0;
2259 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2260 get_server_window_text( hwnd, buffer, nMaxCount );
2261 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2262 lpString[nMaxCount-1] = 0;
2263 HeapFree( GetProcessHeap(), 0, buffer );
2264 return strlen(lpString);
2268 /*******************************************************************
2269 * InternalGetWindowText (USER32.@)
2271 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2273 WND *win;
2275 if (nMaxCount <= 0) return 0;
2276 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2277 if (win == WND_DESKTOP) lpString[0] = 0;
2278 else if (win != WND_OTHER_PROCESS)
2280 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2281 else lpString[0] = 0;
2282 WIN_ReleasePtr( win );
2284 else
2286 get_server_window_text( hwnd, lpString, nMaxCount );
2288 return strlenW(lpString);
2292 /*******************************************************************
2293 * GetWindowTextW (USER32.@)
2295 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2297 if (!lpString) return 0;
2299 if (WIN_IsCurrentProcess( hwnd ))
2300 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2302 /* when window belongs to other process, don't send a message */
2303 if (nMaxCount <= 0) return 0;
2304 get_server_window_text( hwnd, lpString, nMaxCount );
2305 return strlenW(lpString);
2309 /*******************************************************************
2310 * SetWindowText (USER32.@)
2311 * SetWindowTextA (USER32.@)
2313 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2315 if (is_broadcast(hwnd))
2317 SetLastError( ERROR_INVALID_PARAMETER );
2318 return FALSE;
2320 if (!WIN_IsCurrentProcess( hwnd ))
2321 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2322 debugstr_a(lpString), hwnd );
2323 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2327 /*******************************************************************
2328 * SetWindowTextW (USER32.@)
2330 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2332 if (is_broadcast(hwnd))
2334 SetLastError( ERROR_INVALID_PARAMETER );
2335 return FALSE;
2337 if (!WIN_IsCurrentProcess( hwnd ))
2338 FIXME( "setting text %s of other process window %p should not use SendMessage\n",
2339 debugstr_w(lpString), hwnd );
2340 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2344 /*******************************************************************
2345 * GetWindowTextLengthA (USER32.@)
2347 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2349 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2352 /*******************************************************************
2353 * GetWindowTextLengthW (USER32.@)
2355 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2357 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2361 /*******************************************************************
2362 * IsWindow (USER32.@)
2364 BOOL WINAPI IsWindow( HWND hwnd )
2366 WND *ptr;
2367 BOOL ret;
2369 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2370 if (ptr == WND_DESKTOP) return TRUE;
2372 if (ptr != WND_OTHER_PROCESS)
2374 WIN_ReleasePtr( ptr );
2375 return TRUE;
2378 /* check other processes */
2379 SERVER_START_REQ( get_window_info )
2381 req->handle = hwnd;
2382 ret = !wine_server_call_err( req );
2384 SERVER_END_REQ;
2385 return ret;
2389 /***********************************************************************
2390 * GetWindowThreadProcessId (USER32.@)
2392 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2394 WND *ptr;
2395 DWORD tid = 0;
2397 if (!(ptr = WIN_GetPtr( hwnd )))
2399 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2400 return 0;
2403 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2405 /* got a valid window */
2406 tid = ptr->tid;
2407 if (process) *process = GetCurrentProcessId();
2408 WIN_ReleasePtr( ptr );
2409 return tid;
2412 /* check other processes */
2413 SERVER_START_REQ( get_window_info )
2415 req->handle = hwnd;
2416 if (!wine_server_call_err( req ))
2418 tid = (DWORD)reply->tid;
2419 if (process) *process = (DWORD)reply->pid;
2422 SERVER_END_REQ;
2423 return tid;
2427 /*****************************************************************
2428 * GetParent (USER32.@)
2430 HWND WINAPI GetParent( HWND hwnd )
2432 WND *wndPtr;
2433 HWND retvalue = 0;
2435 if (!(wndPtr = WIN_GetPtr( hwnd )))
2437 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2438 return 0;
2440 if (wndPtr == WND_DESKTOP) return 0;
2441 if (wndPtr == WND_OTHER_PROCESS)
2443 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2444 if (style & (WS_POPUP | WS_CHILD))
2446 SERVER_START_REQ( get_window_tree )
2448 req->handle = hwnd;
2449 if (!wine_server_call_err( req ))
2451 if (style & WS_POPUP) retvalue = reply->owner;
2452 else if (style & WS_CHILD) retvalue = reply->parent;
2455 SERVER_END_REQ;
2458 else
2460 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2461 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2462 WIN_ReleasePtr( wndPtr );
2464 return retvalue;
2468 /*****************************************************************
2469 * GetAncestor (USER32.@)
2471 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2473 WND *win;
2474 HWND *list, ret = 0;
2476 switch(type)
2478 case GA_PARENT:
2479 if (!(win = WIN_GetPtr( hwnd )))
2481 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2482 return 0;
2484 if (win == WND_DESKTOP) return 0;
2485 if (win != WND_OTHER_PROCESS)
2487 ret = win->parent;
2488 WIN_ReleasePtr( win );
2490 else /* need to query the server */
2492 SERVER_START_REQ( get_window_tree )
2494 req->handle = hwnd;
2495 if (!wine_server_call_err( req )) ret = reply->parent;
2497 SERVER_END_REQ;
2499 break;
2501 case GA_ROOT:
2502 if (!(list = list_window_parents( hwnd ))) return 0;
2504 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2505 else
2507 int count = 2;
2508 while (list[count]) count++;
2509 ret = list[count - 2]; /* get the one before the desktop */
2511 HeapFree( GetProcessHeap(), 0, list );
2512 break;
2514 case GA_ROOTOWNER:
2515 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2516 for (;;)
2518 HWND parent = GetParent( ret );
2519 if (!parent) break;
2520 ret = parent;
2522 break;
2524 return ret;
2528 /*****************************************************************
2529 * SetParent (USER32.@)
2531 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2533 HWND full_handle;
2535 if (is_broadcast(hwnd) || is_broadcast(parent))
2537 SetLastError(ERROR_INVALID_PARAMETER);
2538 return 0;
2541 if (!parent) parent = GetDesktopWindow();
2542 else parent = WIN_GetFullHandle( parent );
2544 if (!IsWindow( parent ))
2546 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2547 return 0;
2550 /* Some applications try to set a child as a parent */
2551 if (IsChild(hwnd, parent))
2553 SetLastError( ERROR_INVALID_PARAMETER );
2554 return 0;
2557 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2558 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2560 if (USER_Driver.pSetParent)
2561 return USER_Driver.pSetParent( full_handle, parent );
2563 return 0;
2567 /*******************************************************************
2568 * IsChild (USER32.@)
2570 BOOL WINAPI IsChild( HWND parent, HWND child )
2572 HWND *list = list_window_parents( child );
2573 int i;
2574 BOOL ret;
2576 if (!list) return FALSE;
2577 parent = WIN_GetFullHandle( parent );
2578 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2579 ret = (list[i] != 0);
2580 HeapFree( GetProcessHeap(), 0, list );
2581 return ret;
2585 /***********************************************************************
2586 * IsWindowVisible (USER32.@)
2588 BOOL WINAPI IsWindowVisible( HWND hwnd )
2590 HWND *list;
2591 BOOL retval;
2592 int i;
2594 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2595 if (!(list = list_window_parents( hwnd ))) return TRUE;
2596 for (i = 0; list[i]; i++)
2597 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2598 retval = !list[i];
2599 HeapFree( GetProcessHeap(), 0, list );
2600 return retval;
2604 /***********************************************************************
2605 * WIN_IsWindowDrawable
2607 * hwnd is drawable when it is visible, all parents are not
2608 * minimized, and it is itself not minimized unless we are
2609 * trying to draw its default class icon.
2611 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2613 HWND *list;
2614 BOOL retval;
2615 int i;
2616 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2618 if (!(style & WS_VISIBLE)) return FALSE;
2619 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2621 if (!(list = list_window_parents( hwnd ))) return TRUE;
2622 for (i = 0; list[i]; i++)
2623 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2624 break;
2625 retval = !list[i];
2626 HeapFree( GetProcessHeap(), 0, list );
2627 return retval;
2631 /*******************************************************************
2632 * GetTopWindow (USER32.@)
2634 HWND WINAPI GetTopWindow( HWND hwnd )
2636 if (!hwnd) hwnd = GetDesktopWindow();
2637 return GetWindow( hwnd, GW_CHILD );
2641 /*******************************************************************
2642 * GetWindow (USER32.@)
2644 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2646 HWND retval = 0;
2648 if (rel == GW_OWNER) /* this one may be available locally */
2650 WND *wndPtr = WIN_GetPtr( hwnd );
2651 if (!wndPtr)
2653 SetLastError( ERROR_INVALID_HANDLE );
2654 return 0;
2656 if (wndPtr == WND_DESKTOP) return 0;
2657 if (wndPtr != WND_OTHER_PROCESS)
2659 retval = wndPtr->owner;
2660 WIN_ReleasePtr( wndPtr );
2661 return retval;
2663 /* else fall through to server call */
2666 SERVER_START_REQ( get_window_tree )
2668 req->handle = hwnd;
2669 if (!wine_server_call_err( req ))
2671 switch(rel)
2673 case GW_HWNDFIRST:
2674 retval = reply->first_sibling;
2675 break;
2676 case GW_HWNDLAST:
2677 retval = reply->last_sibling;
2678 break;
2679 case GW_HWNDNEXT:
2680 retval = reply->next_sibling;
2681 break;
2682 case GW_HWNDPREV:
2683 retval = reply->prev_sibling;
2684 break;
2685 case GW_OWNER:
2686 retval = reply->owner;
2687 break;
2688 case GW_CHILD:
2689 retval = reply->first_child;
2690 break;
2694 SERVER_END_REQ;
2695 return retval;
2699 /*******************************************************************
2700 * ShowOwnedPopups (USER32.@)
2702 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2704 int count = 0;
2705 WND *pWnd;
2706 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2708 if (!win_array) return TRUE;
2710 while (win_array[count]) count++;
2711 while (--count >= 0)
2713 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2714 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2715 if (pWnd == WND_OTHER_PROCESS) continue;
2716 if (fShow)
2718 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2720 WIN_ReleasePtr( pWnd );
2721 /* In Windows, ShowOwnedPopups(TRUE) generates
2722 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2723 * regardless of the state of the owner
2725 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2726 continue;
2729 else
2731 if (pWnd->dwStyle & WS_VISIBLE)
2733 WIN_ReleasePtr( pWnd );
2734 /* In Windows, ShowOwnedPopups(FALSE) generates
2735 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2736 * regardless of the state of the owner
2738 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2739 continue;
2742 WIN_ReleasePtr( pWnd );
2744 HeapFree( GetProcessHeap(), 0, win_array );
2745 return TRUE;
2749 /*******************************************************************
2750 * GetLastActivePopup (USER32.@)
2752 HWND WINAPI GetLastActivePopup( HWND hwnd )
2754 HWND retval = hwnd;
2756 SERVER_START_REQ( get_window_info )
2758 req->handle = hwnd;
2759 if (!wine_server_call_err( req )) retval = reply->last_active;
2761 SERVER_END_REQ;
2762 return retval;
2766 /*******************************************************************
2767 * WIN_ListChildren
2769 * Build an array of the children of a given window. The array must be
2770 * freed with HeapFree. Returns NULL when no windows are found.
2772 HWND *WIN_ListChildren( HWND hwnd )
2774 return list_window_children( hwnd, 0, 0 );
2778 /*******************************************************************
2779 * EnumWindows (USER32.@)
2781 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2783 HWND *list;
2784 BOOL ret = TRUE;
2785 int i;
2787 USER_CheckNotLock();
2789 /* We have to build a list of all windows first, to avoid */
2790 /* unpleasant side-effects, for instance if the callback */
2791 /* function changes the Z-order of the windows. */
2793 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2795 /* Now call the callback function for every window */
2797 for (i = 0; list[i]; i++)
2799 /* Make sure that the window still exists */
2800 if (!IsWindow( list[i] )) continue;
2801 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2803 HeapFree( GetProcessHeap(), 0, list );
2804 return ret;
2808 /**********************************************************************
2809 * EnumThreadWindows (USER32.@)
2811 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2813 HWND *list;
2814 int i;
2816 USER_CheckNotLock();
2818 if (!(list = list_window_children( GetDesktopWindow(), 0, id ))) return TRUE;
2820 /* Now call the callback function for every window */
2822 for (i = 0; list[i]; i++)
2823 if (!func( list[i], lParam )) break;
2824 HeapFree( GetProcessHeap(), 0, list );
2825 return TRUE;
2829 /**********************************************************************
2830 * WIN_EnumChildWindows
2832 * Helper function for EnumChildWindows().
2834 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2836 HWND *childList;
2837 BOOL ret = FALSE;
2839 for ( ; *list; list++)
2841 /* Make sure that the window still exists */
2842 if (!IsWindow( *list )) continue;
2843 /* skip owned windows */
2844 if (GetWindow( *list, GW_OWNER )) continue;
2845 /* Build children list first */
2846 childList = WIN_ListChildren( *list );
2848 ret = func( *list, lParam );
2850 if (childList)
2852 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2853 HeapFree( GetProcessHeap(), 0, childList );
2855 if (!ret) return FALSE;
2857 return TRUE;
2861 /**********************************************************************
2862 * EnumChildWindows (USER32.@)
2864 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2866 HWND *list;
2868 USER_CheckNotLock();
2870 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2871 WIN_EnumChildWindows( list, func, lParam );
2872 HeapFree( GetProcessHeap(), 0, list );
2873 return TRUE;
2877 /*******************************************************************
2878 * AnyPopup (USER.52)
2880 BOOL16 WINAPI AnyPopup16(void)
2882 return AnyPopup();
2886 /*******************************************************************
2887 * AnyPopup (USER32.@)
2889 BOOL WINAPI AnyPopup(void)
2891 int i;
2892 BOOL retvalue;
2893 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2895 if (!list) return FALSE;
2896 for (i = 0; list[i]; i++)
2898 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2900 retvalue = (list[i] != 0);
2901 HeapFree( GetProcessHeap(), 0, list );
2902 return retvalue;
2906 /*******************************************************************
2907 * FlashWindow (USER32.@)
2909 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2911 WND *wndPtr;
2913 TRACE("%p\n", hWnd);
2915 if (IsIconic( hWnd ))
2917 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2919 wndPtr = WIN_GetPtr(hWnd);
2920 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2921 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2923 wndPtr->flags |= WIN_NCACTIVATED;
2925 else
2927 wndPtr->flags &= ~WIN_NCACTIVATED;
2929 WIN_ReleasePtr( wndPtr );
2930 return TRUE;
2932 else
2934 WPARAM wparam;
2936 wndPtr = WIN_GetPtr(hWnd);
2937 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
2938 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2940 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2941 else wparam = (hWnd == GetForegroundWindow());
2943 WIN_ReleasePtr( wndPtr );
2944 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2945 return wparam;
2949 /*******************************************************************
2950 * FlashWindowEx (USER32.@)
2952 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
2954 FIXME("%p\n", pfwi);
2955 return TRUE;
2958 /*******************************************************************
2959 * GetWindowContextHelpId (USER32.@)
2961 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2963 DWORD retval;
2964 WND *wnd = WIN_GetPtr( hwnd );
2965 if (!wnd || wnd == WND_DESKTOP) return 0;
2966 if (wnd == WND_OTHER_PROCESS)
2968 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2969 return 0;
2971 retval = wnd->helpContext;
2972 WIN_ReleasePtr( wnd );
2973 return retval;
2977 /*******************************************************************
2978 * SetWindowContextHelpId (USER32.@)
2980 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2982 WND *wnd = WIN_GetPtr( hwnd );
2983 if (!wnd || wnd == WND_DESKTOP) return FALSE;
2984 if (wnd == WND_OTHER_PROCESS)
2986 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
2987 return 0;
2989 wnd->helpContext = id;
2990 WIN_ReleasePtr( wnd );
2991 return TRUE;
2995 /*******************************************************************
2996 * DragDetect (USER32.@)
2998 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3000 MSG msg;
3001 RECT rect;
3003 rect.left = pt.x - wDragWidth;
3004 rect.right = pt.x + wDragWidth;
3006 rect.top = pt.y - wDragHeight;
3007 rect.bottom = pt.y + wDragHeight;
3009 SetCapture(hWnd);
3011 while(1)
3013 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3015 if( msg.message == WM_LBUTTONUP )
3017 ReleaseCapture();
3018 return 0;
3020 if( msg.message == WM_MOUSEMOVE )
3022 POINT tmp;
3023 tmp.x = LOWORD(msg.lParam);
3024 tmp.y = HIWORD(msg.lParam);
3025 if( !PtInRect( &rect, tmp ))
3027 ReleaseCapture();
3028 return 1;
3032 WaitMessage();
3034 return 0;
3037 /******************************************************************************
3038 * GetWindowModuleFileNameA (USER32.@)
3040 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3042 FIXME("GetWindowModuleFileNameA(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3043 hwnd, lpszFileName, cchFileNameMax);
3044 return 0;
3047 /******************************************************************************
3048 * GetWindowModuleFileNameW (USER32.@)
3050 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR lpszFileName, UINT cchFileNameMax)
3052 FIXME("GetWindowModuleFileNameW(hwnd %p, lpszFileName %p, cchFileNameMax %u) stub!\n",
3053 hwnd, lpszFileName, cchFileNameMax);
3054 return 0;
3057 /******************************************************************************
3058 * GetWindowInfo (USER32.@)
3060 * Note: tests show that Windows doesn't check cbSize of the structure.
3062 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3064 if (!pwi) return FALSE;
3065 if (!IsWindow(hwnd)) return FALSE;
3067 GetWindowRect(hwnd, &pwi->rcWindow);
3068 GetClientRect(hwnd, &pwi->rcClient);
3069 /* translate to screen coordinates */
3070 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3072 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3073 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3074 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3076 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3077 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3079 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3080 pwi->wCreatorVersion = 0x0400;
3082 return TRUE;
3085 /******************************************************************************
3086 * SwitchDesktop (USER32.@)
3088 * NOTES: Sets the current input or interactive desktop.
3090 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3092 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3093 return TRUE;