Correct optlen when WS_setsockopt is called with SO_LINGER.
[wine/dcerpc.git] / windows / win.c
bloba1d3135d9c70612d7ede6a7788192e14a67ecf98
1 /*
2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include <assert.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include "windef.h"
11 #include "wine/winbase16.h"
12 #include "wine/winuser16.h"
13 #include "wine/server.h"
14 #include "wine/unicode.h"
15 #include "win.h"
16 #include "user.h"
17 #include "dce.h"
18 #include "controls.h"
19 #include "cursoricon.h"
20 #include "hook.h"
21 #include "message.h"
22 #include "queue.h"
23 #include "task.h"
24 #include "winpos.h"
25 #include "winerror.h"
26 #include "stackframe.h"
27 #include "debugtools.h"
29 DEFAULT_DEBUG_CHANNEL(win);
30 DECLARE_DEBUG_CHANNEL(msg);
32 #define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
34 /**********************************************************************/
36 /* Desktop window */
37 static WND *pWndDesktop = NULL;
39 static WORD wDragWidth = 4;
40 static WORD wDragHeight= 3;
42 static void *user_handles[NB_USER_HANDLES];
44 /* thread safeness */
45 extern SYSLEVEL USER_SysLevel; /* FIXME */
47 /***********************************************************************
48 * WIN_SuspendWndsLock
50 * Suspend the lock on WND structures.
51 * Returns the number of locks suspended
53 int WIN_SuspendWndsLock( void )
55 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
56 int count = isuspendedLocks;
58 while ( count-- > 0 )
59 _LeaveSysLevel( &USER_SysLevel );
61 return isuspendedLocks;
64 /***********************************************************************
65 * WIN_RestoreWndsLock
67 * Restore the suspended locks on WND structures
69 void WIN_RestoreWndsLock( int ipreviousLocks )
71 while ( ipreviousLocks-- > 0 )
72 _EnterSysLevel( &USER_SysLevel );
75 /***********************************************************************
76 * create_window_handle
78 * Create a window handle with the server.
80 static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
82 BOOL res;
83 user_handle_t handle = 0;
84 WORD index;
85 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
87 if (!win) return NULL;
89 USER_Lock();
91 SERVER_START_REQ( create_window )
93 req->parent = parent;
94 req->owner = owner;
95 req->atom = atom;
96 if ((res = !wine_server_call_err( req ))) handle = reply->handle;
98 SERVER_END_REQ;
100 if (!res)
102 USER_Unlock();
103 HeapFree( GetProcessHeap(), 0, win );
104 return NULL;
106 index = LOWORD(handle) - FIRST_USER_HANDLE;
107 assert( index < NB_USER_HANDLES );
108 user_handles[index] = win;
109 win->hwndSelf = handle;
110 win->dwMagic = WND_MAGIC;
111 win->irefCount = 1;
112 return win;
116 /***********************************************************************
117 * free_window_handle
119 * Free a window handle.
121 static WND *free_window_handle( HWND hwnd )
123 WND *ptr;
124 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
126 if (index >= NB_USER_HANDLES) return NULL;
127 USER_Lock();
128 if ((ptr = user_handles[index]))
130 SERVER_START_REQ( destroy_window )
132 req->handle = hwnd;
133 if (!wine_server_call_err( req ))
134 user_handles[index] = NULL;
135 else
136 ptr = NULL;
138 SERVER_END_REQ;
140 USER_Unlock();
141 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
142 return ptr;
146 /*******************************************************************
147 * list_window_children
149 * Build an array of the children of a given window. The array must be
150 * freed with HeapFree. Returns NULL when no windows are found.
152 static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
154 HWND *list;
155 int size = 32;
157 for (;;)
159 int count = 0;
161 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
163 SERVER_START_REQ( get_window_children )
165 req->parent = hwnd;
166 req->atom = atom;
167 req->tid = (void *)tid;
168 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
169 if (!wine_server_call( req )) count = reply->count;
171 SERVER_END_REQ;
172 if (count && count < size)
174 list[count] = 0;
175 return list;
177 HeapFree( GetProcessHeap(), 0, list );
178 if (!count) break;
179 size = count + 1; /* restart with a large enough buffer */
181 return NULL;
185 /*******************************************************************
186 * send_parent_notify
188 static void send_parent_notify( HWND hwnd, UINT msg )
190 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD)) return;
191 if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY) return;
192 SendMessageW( GetParent(hwnd), WM_PARENTNOTIFY,
193 MAKEWPARAM( msg, GetWindowLongW( hwnd, GWL_ID )), (LPARAM)hwnd );
197 /*******************************************************************
198 * get_server_window_text
200 * Retrieve the window text from the server.
202 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
204 size_t len = 0;
206 SERVER_START_REQ( get_window_text )
208 req->handle = hwnd;
209 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
210 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
212 SERVER_END_REQ;
213 text[len / sizeof(WCHAR)] = 0;
217 /***********************************************************************
218 * WIN_GetPtr
220 * Return a pointer to the WND structure if local to the process,
221 * or WND_OTHER_PROCESS is handle may be valid in other process.
222 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
224 WND *WIN_GetPtr( HWND hwnd )
226 WND * ptr;
227 WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
229 if (index >= NB_USER_HANDLES) return NULL;
231 USER_Lock();
232 if ((ptr = user_handles[index]))
234 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
235 return ptr;
236 ptr = NULL;
238 else ptr = WND_OTHER_PROCESS;
239 USER_Unlock();
240 return ptr;
244 /***********************************************************************
245 * WIN_IsCurrentProcess
247 * Check whether a given window belongs to the current process (and return the full handle).
249 HWND WIN_IsCurrentProcess( HWND hwnd )
251 WND *ptr;
252 HWND ret;
254 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS) return 0;
255 ret = ptr->hwndSelf;
256 WIN_ReleasePtr( ptr );
257 return ret;
261 /***********************************************************************
262 * WIN_IsCurrentThread
264 * Check whether a given window belongs to the current thread (and return the full handle).
266 HWND WIN_IsCurrentThread( HWND hwnd )
268 WND *ptr;
269 HWND ret = 0;
271 if ((ptr = WIN_GetPtr( hwnd )) && ptr != WND_OTHER_PROCESS)
273 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
274 WIN_ReleasePtr( ptr );
276 return ret;
280 /***********************************************************************
281 * WIN_Handle32
283 * Convert a 16-bit window handle to a full 32-bit handle.
285 HWND WIN_Handle32( HWND16 hwnd16 )
287 WND *ptr;
288 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
290 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
291 /* do sign extension for -2 and -3 */
292 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
294 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
296 if (ptr != WND_OTHER_PROCESS)
298 hwnd = ptr->hwndSelf;
299 WIN_ReleasePtr( ptr );
301 else /* may belong to another process */
303 SERVER_START_REQ( get_window_info )
305 req->handle = hwnd;
306 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
308 SERVER_END_REQ;
310 return hwnd;
314 /***********************************************************************
315 * WIN_FindWndPtr
317 * Return a pointer to the WND structure corresponding to a HWND.
319 WND * WIN_FindWndPtr( HWND hwnd )
321 WND * ptr;
323 if (!hwnd) return NULL;
325 if ((ptr = WIN_GetPtr( hwnd )))
327 if (ptr != WND_OTHER_PROCESS)
329 /* increment destruction monitoring */
330 ptr->irefCount++;
331 return ptr;
333 if (IsWindow( hwnd )) /* check other processes */
335 ERR( "window %04x belongs to other process\n", hwnd );
336 /* DbgBreakPoint(); */
339 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
340 return NULL;
344 /***********************************************************************
345 * WIN_ReleaseWndPtr
347 * Release the pointer to the WND structure.
349 void WIN_ReleaseWndPtr(WND *wndPtr)
351 if(!wndPtr) return;
353 /* Decrement destruction monitoring value */
354 wndPtr->irefCount--;
355 /* Check if it's time to release the memory */
356 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
358 /* Release memory */
359 free_window_handle( wndPtr->hwndSelf );
361 else if(wndPtr->irefCount < 0)
363 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
364 ERR("forgot a Lock on %p somewhere\n",wndPtr);
366 /* unlock all WND structures for thread safeness */
367 USER_Unlock();
371 /***********************************************************************
372 * WIN_UnlinkWindow
374 * Remove a window from the siblings linked list.
376 void WIN_UnlinkWindow( HWND hwnd )
378 WIN_LinkWindow( hwnd, 0, 0 );
382 /***********************************************************************
383 * WIN_LinkWindow
385 * Insert a window into the siblings linked list.
386 * The window is inserted after the specified window, which can also
387 * be specified as HWND_TOP or HWND_BOTTOM.
388 * If parent is 0, window is unlinked from the tree.
390 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
392 WND *wndPtr = WIN_GetPtr( hwnd );
394 if (!wndPtr) return;
395 if (wndPtr == WND_OTHER_PROCESS)
397 if (IsWindow(hwnd)) ERR(" cannot link other process window %x\n", hwnd );
398 return;
401 SERVER_START_REQ( link_window )
403 req->handle = hwnd;
404 req->parent = parent;
405 req->previous = hwndInsertAfter;
406 if (!wine_server_call( req ))
408 if (reply->full_parent && reply->full_parent != wndPtr->parent)
410 wndPtr->owner = 0; /* reset owner when changing parent */
411 wndPtr->parent = reply->full_parent;
416 SERVER_END_REQ;
417 WIN_ReleasePtr( wndPtr );
421 /***********************************************************************
422 * WIN_SetOwner
424 * Change the owner of a window.
426 void WIN_SetOwner( HWND hwnd, HWND owner )
428 WND *win = WIN_GetPtr( hwnd );
430 if (!win) return;
431 if (win == WND_OTHER_PROCESS)
433 if (IsWindow(hwnd)) ERR( "cannot set owner %x on other process window %x\n", owner, hwnd );
434 return;
436 SERVER_START_REQ( set_window_owner )
438 req->handle = hwnd;
439 req->owner = owner;
440 if (!wine_server_call( req )) win->owner = reply->full_owner;
442 SERVER_END_REQ;
443 WIN_ReleasePtr( win );
447 /***********************************************************************
448 * WIN_SetStyle
450 * Change the style of a window.
452 LONG WIN_SetStyle( HWND hwnd, LONG style )
454 BOOL ok;
455 LONG ret = 0;
456 WND *win = WIN_GetPtr( hwnd );
458 if (!win) return 0;
459 if (win == WND_OTHER_PROCESS)
461 if (IsWindow(hwnd))
462 ERR( "cannot set style %lx on other process window %x\n", style, hwnd );
463 return 0;
465 if (style == win->dwStyle)
467 WIN_ReleasePtr( win );
468 return style;
470 SERVER_START_REQ( set_window_info )
472 req->handle = hwnd;
473 req->flags = SET_WIN_STYLE;
474 req->style = style;
475 if ((ok = !wine_server_call( req )))
477 ret = reply->old_style;
478 win->dwStyle = style;
481 SERVER_END_REQ;
482 WIN_ReleasePtr( win );
483 if (ok && USER_Driver.pSetWindowStyle) USER_Driver.pSetWindowStyle( hwnd, ret );
484 return ret;
488 /***********************************************************************
489 * WIN_SetExStyle
491 * Change the extended style of a window.
493 LONG WIN_SetExStyle( HWND hwnd, LONG style )
495 LONG ret = 0;
496 WND *win = WIN_GetPtr( hwnd );
498 if (!win) return 0;
499 if (win == WND_OTHER_PROCESS)
501 if (IsWindow(hwnd))
502 ERR( "cannot set exstyle %lx on other process window %x\n", style, hwnd );
503 return 0;
505 if (style == win->dwExStyle)
507 WIN_ReleasePtr( win );
508 return style;
510 SERVER_START_REQ( set_window_info )
512 req->handle = hwnd;
513 req->flags = SET_WIN_EXSTYLE;
514 req->ex_style = style;
515 if (!wine_server_call( req ))
517 ret = reply->old_ex_style;
518 win->dwExStyle = style;
521 SERVER_END_REQ;
522 WIN_ReleasePtr( win );
523 return ret;
527 /***********************************************************************
528 * WIN_SetRectangles
530 * Set the window and client rectangles.
532 void WIN_SetRectangles( HWND hwnd, const RECT *rectWindow, const RECT *rectClient )
534 WND *win = WIN_GetPtr( hwnd );
535 BOOL ret;
537 if (!win) return;
538 if (win == WND_OTHER_PROCESS)
540 if (IsWindow( hwnd )) ERR( "cannot set rectangles of other process window %x\n", hwnd );
541 return;
543 SERVER_START_REQ( set_window_rectangles )
545 req->handle = hwnd;
546 req->window.left = rectWindow->left;
547 req->window.top = rectWindow->top;
548 req->window.right = rectWindow->right;
549 req->window.bottom = rectWindow->bottom;
550 req->client.left = rectClient->left;
551 req->client.top = rectClient->top;
552 req->client.right = rectClient->right;
553 req->client.bottom = rectClient->bottom;
554 ret = !wine_server_call( req );
556 SERVER_END_REQ;
557 if (ret)
559 win->rectWindow = *rectWindow;
560 win->rectClient = *rectClient;
562 TRACE( "win %x window (%d,%d)-(%d,%d) client (%d,%d)-(%d,%d)\n", hwnd,
563 rectWindow->left, rectWindow->top, rectWindow->right, rectWindow->bottom,
564 rectClient->left, rectClient->top, rectClient->right, rectClient->bottom );
566 WIN_ReleasePtr( win );
570 /***********************************************************************
571 * WIN_GetRectangles
573 * Get the window and client rectangles.
575 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
577 WND *win = WIN_GetPtr( hwnd );
578 BOOL ret = TRUE;
580 if (!win) return FALSE;
581 if (win == WND_OTHER_PROCESS)
583 SERVER_START_REQ( get_window_rectangles )
585 req->handle = hwnd;
586 if ((ret = !wine_server_call( req )))
588 if (rectWindow)
590 rectWindow->left = reply->window.left;
591 rectWindow->top = reply->window.top;
592 rectWindow->right = reply->window.right;
593 rectWindow->bottom = reply->window.bottom;
595 if (rectClient)
597 rectClient->left = reply->client.left;
598 rectClient->top = reply->client.top;
599 rectClient->right = reply->client.right;
600 rectClient->bottom = reply->client.bottom;
604 SERVER_END_REQ;
606 else
608 if (rectWindow) *rectWindow = win->rectWindow;
609 if (rectClient) *rectClient = win->rectClient;
610 WIN_ReleasePtr( win );
612 return ret;
616 /***********************************************************************
617 * WIN_DestroyWindow
619 * Destroy storage associated to a window. "Internals" p.358
621 LRESULT WIN_DestroyWindow( HWND hwnd )
623 WND *wndPtr;
624 HWND *list;
626 TRACE("%04x\n", hwnd );
628 if (!(hwnd = WIN_IsCurrentThread( hwnd )))
630 ERR( "window doesn't belong to current thread\n" );
631 return 0;
634 /* free child windows */
635 if ((list = WIN_ListChildren( hwnd )))
637 int i;
638 for (i = 0; list[i]; i++)
640 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
641 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
643 HeapFree( GetProcessHeap(), 0, list );
647 * Clear the update region to make sure no WM_PAINT messages will be
648 * generated for this window while processing the WM_NCDESTROY.
650 RedrawWindow( hwnd, NULL, 0,
651 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
654 * Send the WM_NCDESTROY to the window being destroyed.
656 SendMessageA( hwnd, WM_NCDESTROY, 0, 0);
658 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
660 WINPOS_CheckInternalPos( hwnd );
661 if( hwnd == GetCapture()) ReleaseCapture();
663 /* free resources associated with the window */
665 TIMER_RemoveWindowTimers( hwnd );
667 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
668 wndPtr->hmemTaskQ = 0;
670 if (!(wndPtr->dwStyle & WS_CHILD))
672 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
673 if (menu) DestroyMenu( menu );
675 if (wndPtr->hSysMenu)
677 DestroyMenu( wndPtr->hSysMenu );
678 wndPtr->hSysMenu = 0;
680 USER_Driver.pDestroyWindow( hwnd );
681 DCE_FreeWindowDCE( hwnd ); /* Always do this to catch orphaned DCs */
682 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
683 CLASS_RemoveWindow( wndPtr->class );
684 wndPtr->class = NULL;
685 wndPtr->dwMagic = 0; /* Mark it as invalid */
686 WIN_ReleaseWndPtr( wndPtr );
687 return 0;
690 /***********************************************************************
691 * WIN_DestroyThreadWindows
693 * Destroy all children of 'wnd' owned by the current thread.
694 * Return TRUE if something was done.
696 void WIN_DestroyThreadWindows( HWND hwnd )
698 HWND *list;
699 int i;
701 if (!(list = WIN_ListChildren( hwnd ))) return;
702 for (i = 0; list[i]; i++)
704 if (WIN_IsCurrentThread( list[i] ))
705 DestroyWindow( list[i] );
706 else
707 WIN_DestroyThreadWindows( list[i] );
709 HeapFree( GetProcessHeap(), 0, list );
712 /***********************************************************************
713 * WIN_CreateDesktopWindow
715 * Create the desktop window.
717 BOOL WIN_CreateDesktopWindow(void)
719 struct tagCLASS *class;
720 HWND hwndDesktop;
721 INT wndExtra;
722 DWORD clsStyle;
723 WNDPROC winproc;
724 DCE *dce;
725 CREATESTRUCTA cs;
726 RECT rect;
728 TRACE("Creating desktop window\n");
730 if (!WINPOS_CreateInternalPosAtom() ||
731 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
732 &wndExtra, &winproc, &clsStyle, &dce )))
733 return FALSE;
735 pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
736 sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
737 if (!pWndDesktop) return FALSE;
738 hwndDesktop = pWndDesktop->hwndSelf;
740 pWndDesktop->tid = 0; /* nobody owns the desktop */
741 pWndDesktop->parent = 0;
742 pWndDesktop->owner = 0;
743 pWndDesktop->class = class;
744 pWndDesktop->hInstance = 0;
745 pWndDesktop->text = NULL;
746 pWndDesktop->hmemTaskQ = 0;
747 pWndDesktop->hrgnUpdate = 0;
748 pWndDesktop->hwndLastActive = hwndDesktop;
749 pWndDesktop->dwStyle = 0;
750 pWndDesktop->dwExStyle = 0;
751 pWndDesktop->clsStyle = clsStyle;
752 pWndDesktop->dce = NULL;
753 pWndDesktop->pVScroll = NULL;
754 pWndDesktop->pHScroll = NULL;
755 pWndDesktop->wIDmenu = 0;
756 pWndDesktop->helpContext = 0;
757 pWndDesktop->flags = 0;
758 pWndDesktop->hSysMenu = 0;
759 pWndDesktop->userdata = 0;
760 pWndDesktop->winproc = winproc;
761 pWndDesktop->cbWndExtra = wndExtra;
763 cs.lpCreateParams = NULL;
764 cs.hInstance = 0;
765 cs.hMenu = 0;
766 cs.hwndParent = 0;
767 cs.x = 0;
768 cs.y = 0;
769 cs.cx = GetSystemMetrics( SM_CXSCREEN );
770 cs.cy = GetSystemMetrics( SM_CYSCREEN );
771 cs.style = pWndDesktop->dwStyle;
772 cs.dwExStyle = pWndDesktop->dwExStyle;
773 cs.lpszName = NULL;
774 cs.lpszClass = DESKTOP_CLASS_ATOM;
776 SetRect( &rect, 0, 0, cs.cx, cs.cy );
777 WIN_SetRectangles( hwndDesktop, &rect, &rect );
778 WIN_SetStyle( hwndDesktop, WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS );
780 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
782 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
783 WIN_ReleaseWndPtr( pWndDesktop );
784 return TRUE;
788 /***********************************************************************
789 * WIN_FixCoordinates
791 * Fix the coordinates - Helper for WIN_CreateWindowEx.
792 * returns default show mode in sw.
793 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
795 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
797 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
798 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
800 if (cs->style & (WS_CHILD | WS_POPUP))
802 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
803 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
805 else /* overlapped window */
807 STARTUPINFOA info;
809 GetStartupInfoA( &info );
811 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
813 /* Never believe Microsoft's documentation... CreateWindowEx doc says
814 * that if an overlapped window is created with WS_VISIBLE style bit
815 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
816 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
817 * reveals that
819 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
820 * 2) it does not ignore the y parameter as the docs claim; instead, it
821 * uses it as second parameter to ShowWindow() unless y is either
822 * CW_USEDEFAULT or CW_USEDEFAULT16.
824 * The fact that we didn't do 2) caused bogus windows pop up when wine
825 * was running apps that were using this obscure feature. Example -
826 * calc.exe that comes with Win98 (only Win98, it's different from
827 * the one that comes with Win95 and NT)
829 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
830 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
831 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
834 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
836 if (info.dwFlags & STARTF_USESIZE)
838 cs->cx = info.dwXSize;
839 cs->cy = info.dwYSize;
841 else /* if no other hint from the app, pick 3/4 of the screen real estate */
843 RECT r;
844 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
845 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
846 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
853 /***********************************************************************
854 * dump_window_styles
856 static void dump_window_styles( DWORD style, DWORD exstyle )
858 TRACE( "style:" );
859 if(style & WS_POPUP) DPRINTF(" WS_POPUP");
860 if(style & WS_CHILD) DPRINTF(" WS_CHILD");
861 if(style & WS_MINIMIZE) DPRINTF(" WS_MINIMIZE");
862 if(style & WS_VISIBLE) DPRINTF(" WS_VISIBLE");
863 if(style & WS_DISABLED) DPRINTF(" WS_DISABLED");
864 if(style & WS_CLIPSIBLINGS) DPRINTF(" WS_CLIPSIBLINGS");
865 if(style & WS_CLIPCHILDREN) DPRINTF(" WS_CLIPCHILDREN");
866 if(style & WS_MAXIMIZE) DPRINTF(" WS_MAXIMIZE");
867 if((style & WS_CAPTION) == WS_CAPTION) DPRINTF(" WS_CAPTION");
868 else
870 if(style & WS_BORDER) DPRINTF(" WS_BORDER");
871 if(style & WS_DLGFRAME) DPRINTF(" WS_DLGFRAME");
873 if(style & WS_VSCROLL) DPRINTF(" WS_VSCROLL");
874 if(style & WS_HSCROLL) DPRINTF(" WS_HSCROLL");
875 if(style & WS_SYSMENU) DPRINTF(" WS_SYSMENU");
876 if(style & WS_THICKFRAME) DPRINTF(" WS_THICKFRAME");
877 if(style & WS_GROUP) DPRINTF(" WS_GROUP");
878 if(style & WS_TABSTOP) DPRINTF(" WS_TABSTOP");
879 if(style & WS_MINIMIZEBOX) DPRINTF(" WS_MINIMIZEBOX");
880 if(style & WS_MAXIMIZEBOX) DPRINTF(" WS_MAXIMIZEBOX");
882 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
883 #define DUMPED_STYLES \
884 (WS_POPUP | \
885 WS_CHILD | \
886 WS_MINIMIZE | \
887 WS_VISIBLE | \
888 WS_DISABLED | \
889 WS_CLIPSIBLINGS | \
890 WS_CLIPCHILDREN | \
891 WS_MAXIMIZE | \
892 WS_BORDER | \
893 WS_DLGFRAME | \
894 WS_VSCROLL | \
895 WS_HSCROLL | \
896 WS_SYSMENU | \
897 WS_THICKFRAME | \
898 WS_GROUP | \
899 WS_TABSTOP | \
900 WS_MINIMIZEBOX | \
901 WS_MAXIMIZEBOX)
903 if(style & ~DUMPED_STYLES) DPRINTF(" %08lx", style & ~DUMPED_STYLES);
904 DPRINTF("\n");
905 #undef DUMPED_STYLES
907 TRACE( "exstyle:" );
908 if(exstyle & WS_EX_DLGMODALFRAME) DPRINTF(" WS_EX_DLGMODALFRAME");
909 if(exstyle & WS_EX_DRAGDETECT) DPRINTF(" WS_EX_DRAGDETECT");
910 if(exstyle & WS_EX_NOPARENTNOTIFY) DPRINTF(" WS_EX_NOPARENTNOTIFY");
911 if(exstyle & WS_EX_TOPMOST) DPRINTF(" WS_EX_TOPMOST");
912 if(exstyle & WS_EX_ACCEPTFILES) DPRINTF(" WS_EX_ACCEPTFILES");
913 if(exstyle & WS_EX_TRANSPARENT) DPRINTF(" WS_EX_TRANSPARENT");
914 if(exstyle & WS_EX_MDICHILD) DPRINTF(" WS_EX_MDICHILD");
915 if(exstyle & WS_EX_TOOLWINDOW) DPRINTF(" WS_EX_TOOLWINDOW");
916 if(exstyle & WS_EX_WINDOWEDGE) DPRINTF(" WS_EX_WINDOWEDGE");
917 if(exstyle & WS_EX_CLIENTEDGE) DPRINTF(" WS_EX_CLIENTEDGE");
918 if(exstyle & WS_EX_CONTEXTHELP) DPRINTF(" WS_EX_CONTEXTHELP");
919 if(exstyle & WS_EX_RIGHT) DPRINTF(" WS_EX_RIGHT");
920 if(exstyle & WS_EX_RTLREADING) DPRINTF(" WS_EX_RTLREADING");
921 if(exstyle & WS_EX_LEFTSCROLLBAR) DPRINTF(" WS_EX_LEFTSCROLLBAR");
922 if(exstyle & WS_EX_CONTROLPARENT) DPRINTF(" WS_EX_CONTROLPARENT");
923 if(exstyle & WS_EX_STATICEDGE) DPRINTF(" WS_EX_STATICEDGE");
924 if(exstyle & WS_EX_APPWINDOW) DPRINTF(" WS_EX_APPWINDOW");
925 if(exstyle & WS_EX_LAYERED) DPRINTF(" WS_EX_LAYERED");
927 #define DUMPED_EX_STYLES \
928 (WS_EX_DLGMODALFRAME | \
929 WS_EX_DRAGDETECT | \
930 WS_EX_NOPARENTNOTIFY | \
931 WS_EX_TOPMOST | \
932 WS_EX_ACCEPTFILES | \
933 WS_EX_TRANSPARENT | \
934 WS_EX_MDICHILD | \
935 WS_EX_TOOLWINDOW | \
936 WS_EX_WINDOWEDGE | \
937 WS_EX_CLIENTEDGE | \
938 WS_EX_CONTEXTHELP | \
939 WS_EX_RIGHT | \
940 WS_EX_RTLREADING | \
941 WS_EX_LEFTSCROLLBAR | \
942 WS_EX_CONTROLPARENT | \
943 WS_EX_STATICEDGE | \
944 WS_EX_APPWINDOW | \
945 WS_EX_LAYERED)
947 if(exstyle & ~DUMPED_EX_STYLES) DPRINTF(" %08lx", exstyle & ~DUMPED_EX_STYLES);
948 DPRINTF("\n");
949 #undef DUMPED_EX_STYLES
953 /***********************************************************************
954 * WIN_CreateWindowEx
956 * Implementation of CreateWindowEx().
958 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
959 WINDOWPROCTYPE type )
961 INT sw = SW_SHOW;
962 struct tagCLASS *classPtr;
963 WND *wndPtr;
964 HWND hwnd, parent, owner;
965 INT wndExtra;
966 DWORD clsStyle;
967 WNDPROC winproc;
968 DCE *dce;
969 BOOL unicode = (type == WIN_PROC_32W);
971 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
972 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
973 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
974 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
975 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
977 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
979 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
980 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
982 /* Find the parent window */
984 parent = GetDesktopWindow();
985 owner = 0;
986 if (cs->hwndParent)
988 /* Make sure parent is valid */
989 if (!IsWindow( cs->hwndParent ))
991 WARN("Bad parent %04x\n", cs->hwndParent );
992 return 0;
994 if (cs->style & WS_CHILD) parent = WIN_GetFullHandle(cs->hwndParent);
995 else owner = GetAncestor( cs->hwndParent, GA_ROOT );
997 else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
999 WARN("No parent for child window\n" );
1000 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
1003 /* Find the window class */
1004 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
1005 &wndExtra, &winproc, &clsStyle, &dce )))
1007 WARN("Bad class '%s'\n", cs->lpszClass );
1008 return 0;
1011 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
1013 /* Correct the window style - stage 1
1015 * These are patches that appear to affect both the style loaded into the
1016 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
1018 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1019 * why does the user get to set it?
1022 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
1023 * tested for WS_POPUP
1025 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
1026 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
1027 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
1028 cs->dwExStyle |= WS_EX_WINDOWEDGE;
1029 else
1030 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
1032 /* Create the window structure */
1034 if (!(wndPtr = create_window_handle( parent, owner, classAtom,
1035 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
1037 TRACE("out of memory\n" );
1038 return 0;
1040 hwnd = wndPtr->hwndSelf;
1042 /* Fill the window structure */
1044 wndPtr->tid = GetCurrentThreadId();
1045 wndPtr->owner = owner;
1046 wndPtr->parent = parent;
1047 wndPtr->class = classPtr;
1048 wndPtr->winproc = winproc;
1049 wndPtr->hInstance = cs->hInstance;
1050 wndPtr->text = NULL;
1051 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
1052 wndPtr->hrgnUpdate = 0;
1053 wndPtr->hrgnWnd = 0;
1054 wndPtr->hwndLastActive = hwnd;
1055 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1056 wndPtr->dwExStyle = cs->dwExStyle;
1057 wndPtr->clsStyle = clsStyle;
1058 wndPtr->wIDmenu = 0;
1059 wndPtr->helpContext = 0;
1060 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
1061 wndPtr->pVScroll = NULL;
1062 wndPtr->pHScroll = NULL;
1063 wndPtr->userdata = 0;
1064 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
1065 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
1066 wndPtr->cbWndExtra = wndExtra;
1068 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
1070 /* Correct the window style - stage 2 */
1072 if (!(cs->style & WS_CHILD))
1074 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1075 if (!(cs->style & WS_POPUP))
1077 wndPtr->dwStyle |= WS_CAPTION;
1078 wndPtr->flags |= WIN_NEED_SIZE;
1081 SERVER_START_REQ( set_window_info )
1083 req->handle = hwnd;
1084 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE;
1085 req->style = wndPtr->dwStyle;
1086 req->ex_style = wndPtr->dwExStyle;
1087 req->instance = (void *)wndPtr->hInstance;
1088 wine_server_call( req );
1090 SERVER_END_REQ;
1092 /* Get class or window DC if needed */
1094 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
1095 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
1096 else wndPtr->dce = NULL;
1098 /* Set the window menu */
1100 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
1102 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
1103 else
1105 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
1106 if (menuName)
1108 if (HIWORD(cs->hInstance))
1109 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1110 else
1111 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
1113 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
1117 else SetWindowLongW( hwnd, GWL_ID, (UINT)cs->hMenu );
1118 WIN_ReleaseWndPtr( wndPtr );
1120 if (!USER_Driver.pCreateWindow( hwnd, cs, unicode))
1122 WIN_DestroyWindow( hwnd );
1123 return 0;
1126 /* Notify the parent window only */
1128 send_parent_notify( hwnd, WM_CREATE );
1129 if (!IsWindow( hwnd )) return 0;
1131 if (cs->style & WS_VISIBLE)
1133 /* in case WS_VISIBLE got set in the meantime */
1134 if (!(wndPtr = WIN_GetPtr( hwnd ))) return 0;
1135 WIN_SetStyle( hwnd, wndPtr->dwStyle & ~WS_VISIBLE );
1136 WIN_ReleasePtr( wndPtr );
1137 ShowWindow( hwnd, sw );
1140 /* Call WH_SHELL hook */
1142 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1143 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
1145 TRACE("created window %04x\n", hwnd);
1146 return hwnd;
1150 /***********************************************************************
1151 * CreateWindow (USER.41)
1153 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1154 DWORD style, INT16 x, INT16 y, INT16 width,
1155 INT16 height, HWND16 parent, HMENU16 menu,
1156 HINSTANCE16 instance, LPVOID data )
1158 return CreateWindowEx16( 0, className, windowName, style,
1159 x, y, width, height, parent, menu, instance, data );
1163 /***********************************************************************
1164 * CreateWindowEx (USER.452)
1166 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1167 LPCSTR windowName, DWORD style, INT16 x,
1168 INT16 y, INT16 width, INT16 height,
1169 HWND16 parent, HMENU16 menu,
1170 HINSTANCE16 instance, LPVOID data )
1172 ATOM classAtom;
1173 CREATESTRUCTA cs;
1174 char buffer[256];
1176 /* Find the class atom */
1178 if (HIWORD(className))
1180 if (!(classAtom = GlobalFindAtomA( className )))
1182 ERR( "bad class name %s\n", debugres_a(className) );
1183 return 0;
1186 else
1188 classAtom = LOWORD(className);
1189 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1191 ERR( "bad atom %x\n", classAtom);
1192 return 0;
1194 className = buffer;
1197 /* Fix the coordinates */
1199 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1200 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1201 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1202 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1204 /* Create the window */
1206 cs.lpCreateParams = data;
1207 cs.hInstance = (HINSTANCE)instance;
1208 cs.hMenu = (HMENU)menu;
1209 cs.hwndParent = WIN_Handle32( parent );
1210 cs.style = style;
1211 cs.lpszName = windowName;
1212 cs.lpszClass = className;
1213 cs.dwExStyle = exStyle;
1215 return WIN_Handle16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
1219 /***********************************************************************
1220 * CreateWindowExA (USER32.@)
1222 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1223 LPCSTR windowName, DWORD style, INT x,
1224 INT y, INT width, INT height,
1225 HWND parent, HMENU menu,
1226 HINSTANCE instance, LPVOID data )
1228 ATOM classAtom;
1229 CREATESTRUCTA cs;
1230 char buffer[256];
1232 if(!instance)
1233 instance=GetModuleHandleA(NULL);
1235 if(exStyle & WS_EX_MDICHILD)
1236 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1238 /* Find the class atom */
1240 if (HIWORD(className))
1242 if (!(classAtom = GlobalFindAtomA( className )))
1244 ERR( "bad class name %s\n", debugres_a(className) );
1245 return 0;
1248 else
1250 classAtom = LOWORD(className);
1251 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1253 ERR( "bad atom %x\n", classAtom);
1254 return 0;
1256 className = buffer;
1259 /* Create the window */
1261 cs.lpCreateParams = data;
1262 cs.hInstance = instance;
1263 cs.hMenu = menu;
1264 cs.hwndParent = parent;
1265 cs.x = x;
1266 cs.y = y;
1267 cs.cx = width;
1268 cs.cy = height;
1269 cs.style = style;
1270 cs.lpszName = windowName;
1271 cs.lpszClass = className;
1272 cs.dwExStyle = exStyle;
1274 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1278 /***********************************************************************
1279 * CreateWindowExW (USER32.@)
1281 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1282 LPCWSTR windowName, DWORD style, INT x,
1283 INT y, INT width, INT height,
1284 HWND parent, HMENU menu,
1285 HINSTANCE instance, LPVOID data )
1287 ATOM classAtom;
1288 CREATESTRUCTW cs;
1289 WCHAR buffer[256];
1291 if(!instance)
1292 instance=GetModuleHandleA(NULL);
1294 if(exStyle & WS_EX_MDICHILD)
1295 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1297 /* Find the class atom */
1299 if (HIWORD(className))
1301 if (!(classAtom = GlobalFindAtomW( className )))
1303 ERR( "bad class name %s\n", debugres_w(className) );
1304 return 0;
1307 else
1309 classAtom = LOWORD(className);
1310 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1312 ERR( "bad atom %x\n", classAtom);
1313 return 0;
1315 className = buffer;
1318 /* Create the window */
1320 cs.lpCreateParams = data;
1321 cs.hInstance = instance;
1322 cs.hMenu = menu;
1323 cs.hwndParent = parent;
1324 cs.x = x;
1325 cs.y = y;
1326 cs.cx = width;
1327 cs.cy = height;
1328 cs.style = style;
1329 cs.lpszName = windowName;
1330 cs.lpszClass = className;
1331 cs.dwExStyle = exStyle;
1333 /* Note: we rely on the fact that CREATESTRUCTA and */
1334 /* CREATESTRUCTW have the same layout. */
1335 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1339 /***********************************************************************
1340 * WIN_SendDestroyMsg
1342 static void WIN_SendDestroyMsg( HWND hwnd )
1344 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1345 if (USER_Driver.pResetSelectionOwner)
1346 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1349 * Send the WM_DESTROY to the window.
1351 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1354 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1355 * make sure that the window still exists when we come back.
1357 if (IsWindow(hwnd))
1359 HWND* pWndArray;
1360 int i;
1362 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1364 /* start from the end (FIXME: is this needed?) */
1365 for (i = 0; pWndArray[i]; i++) ;
1367 while (--i >= 0)
1369 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1371 HeapFree( GetProcessHeap(), 0, pWndArray );
1373 else
1374 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1378 /***********************************************************************
1379 * DestroyWindow (USER32.@)
1381 BOOL WINAPI DestroyWindow( HWND hwnd )
1383 BOOL is_child;
1384 HWND h;
1386 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1388 SetLastError( ERROR_ACCESS_DENIED );
1389 return FALSE;
1392 TRACE("(%04x)\n", hwnd);
1394 /* Look whether the focus is within the tree of windows we will
1395 * be destroying.
1397 h = GetFocus();
1398 if (h == hwnd || IsChild( hwnd, h ))
1400 HWND parent = GetAncestor( hwnd, GA_PARENT );
1401 if (parent == GetDesktopWindow()) parent = 0;
1402 SetFocus( parent );
1405 /* Call hooks */
1407 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1409 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1411 if (is_child)
1413 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1414 send_parent_notify( hwnd, WM_DESTROY );
1416 else if (!GetWindow( hwnd, GW_OWNER ))
1418 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1419 /* FIXME: clean up palette - see "Internals" p.352 */
1422 if (!IsWindow(hwnd)) return TRUE;
1424 if (USER_Driver.pResetSelectionOwner)
1425 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1427 /* Hide the window */
1429 ShowWindow( hwnd, SW_HIDE );
1430 if (!IsWindow(hwnd)) return TRUE;
1432 /* Recursively destroy owned windows */
1434 if (!is_child)
1436 HWND owner;
1438 for (;;)
1440 int i, got_one = 0;
1441 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1442 if (list)
1444 for (i = 0; list[i]; i++)
1446 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1447 if (WIN_IsCurrentThread( list[i] ))
1449 DestroyWindow( list[i] );
1450 got_one = 1;
1451 continue;
1453 WIN_SetOwner( list[i], 0 );
1455 HeapFree( GetProcessHeap(), 0, list );
1457 if (!got_one) break;
1460 WINPOS_ActivateOtherWindow( hwnd );
1462 if ((owner = GetWindow( hwnd, GW_OWNER )))
1464 WND *ptr = WIN_FindWndPtr( owner );
1465 if (ptr)
1467 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1468 WIN_ReleaseWndPtr( ptr );
1473 /* Send destroy messages */
1475 WIN_SendDestroyMsg( hwnd );
1476 if (!IsWindow( hwnd )) return TRUE;
1478 /* Unlink now so we won't bother with the children later on */
1480 WIN_UnlinkWindow( hwnd );
1482 /* Destroy the window storage */
1484 WIN_DestroyWindow( hwnd );
1485 return TRUE;
1489 /***********************************************************************
1490 * CloseWindow (USER32.@)
1492 BOOL WINAPI CloseWindow( HWND hwnd )
1494 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1495 ShowWindow( hwnd, SW_MINIMIZE );
1496 return TRUE;
1500 /***********************************************************************
1501 * OpenIcon (USER32.@)
1503 BOOL WINAPI OpenIcon( HWND hwnd )
1505 if (!IsIconic( hwnd )) return FALSE;
1506 ShowWindow( hwnd, SW_SHOWNORMAL );
1507 return TRUE;
1511 /***********************************************************************
1512 * WIN_FindWindow
1514 * Implementation of FindWindow() and FindWindowEx().
1516 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1518 HWND *list = NULL;
1519 HWND retvalue = 0;
1520 int i = 0, len = 0;
1521 WCHAR *buffer = NULL;
1523 if (!parent) parent = GetDesktopWindow();
1524 if (title)
1526 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1527 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1530 if (!(list = list_window_children( parent, className, 0 ))) goto done;
1532 if (child)
1534 child = WIN_GetFullHandle( child );
1535 while (list[i] && list[i] != child) i++;
1536 if (!list[i]) goto done;
1537 i++; /* start from next window */
1540 if (title)
1542 while (list[i])
1544 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1545 i++;
1548 retvalue = list[i];
1550 done:
1551 if (list) HeapFree( GetProcessHeap(), 0, list );
1552 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1553 return retvalue;
1558 /***********************************************************************
1559 * FindWindowA (USER32.@)
1561 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1563 HWND ret = FindWindowExA( 0, 0, className, title );
1564 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1565 return ret;
1569 /***********************************************************************
1570 * FindWindowExA (USER32.@)
1572 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1573 LPCSTR className, LPCSTR title )
1575 ATOM atom = 0;
1576 LPWSTR buffer;
1577 HWND hwnd;
1578 INT len;
1580 if (className)
1582 /* If the atom doesn't exist, then no class */
1583 /* with this name exists either. */
1584 if (!(atom = GlobalFindAtomA( className )))
1586 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1587 return 0;
1590 if (!title) return WIN_FindWindow( parent, child, atom, NULL );
1592 len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1593 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1594 MultiByteToWideChar( CP_ACP, 0, title, -1, buffer, len );
1595 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1596 HeapFree( GetProcessHeap(), 0, buffer );
1597 return hwnd;
1601 /***********************************************************************
1602 * FindWindowExW (USER32.@)
1604 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1605 LPCWSTR className, LPCWSTR title )
1607 ATOM atom = 0;
1609 if (className)
1611 /* If the atom doesn't exist, then no class */
1612 /* with this name exists either. */
1613 if (!(atom = GlobalFindAtomW( className )))
1615 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1616 return 0;
1619 return WIN_FindWindow( parent, child, atom, title );
1623 /***********************************************************************
1624 * FindWindowW (USER32.@)
1626 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1628 return FindWindowExW( 0, 0, className, title );
1632 /**********************************************************************
1633 * GetDesktopWindow (USER32.@)
1635 HWND WINAPI GetDesktopWindow(void)
1637 if (pWndDesktop) return pWndDesktop->hwndSelf;
1638 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" );
1639 ExitProcess(1);
1640 return 0;
1644 /*******************************************************************
1645 * EnableWindow (USER32.@)
1647 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1649 WND *wndPtr;
1650 BOOL retvalue;
1651 LONG style;
1652 HWND full_handle;
1654 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1655 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1657 hwnd = full_handle;
1659 TRACE("( %x, %d )\n", hwnd, enable);
1661 if (!(wndPtr = WIN_GetPtr( hwnd ))) return FALSE;
1662 style = wndPtr->dwStyle;
1663 retvalue = ((style & WS_DISABLED) != 0);
1664 WIN_ReleasePtr( wndPtr );
1666 if (enable && retvalue)
1668 WIN_SetStyle( hwnd, style & ~WS_DISABLED );
1669 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1671 else if (!enable && !retvalue)
1673 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1675 WIN_SetStyle( hwnd, style | WS_DISABLED );
1677 if (hwnd == GetFocus())
1678 SetFocus( 0 ); /* A disabled window can't have the focus */
1680 if (hwnd == GetCapture())
1681 ReleaseCapture(); /* A disabled window can't capture the mouse */
1683 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1685 return retvalue;
1689 /***********************************************************************
1690 * IsWindowEnabled (USER32.@)
1692 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1694 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1698 /***********************************************************************
1699 * IsWindowUnicode (USER32.@)
1701 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1703 WND * wndPtr;
1704 BOOL retvalue;
1706 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1707 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1708 WIN_ReleaseWndPtr(wndPtr);
1709 return retvalue;
1713 /**********************************************************************
1714 * GetWindowWord (USER32.@)
1716 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1718 if (offset >= 0)
1720 WORD retvalue = 0;
1721 WND *wndPtr = WIN_GetPtr( hwnd );
1722 if (!wndPtr)
1724 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1725 return 0;
1727 if (wndPtr == WND_OTHER_PROCESS)
1729 if (IsWindow( hwnd ))
1730 FIXME( "(%d) not supported yet on other process window %x\n", offset, hwnd );
1731 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1732 return 0;
1734 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1736 WARN("Invalid offset %d\n", offset );
1737 SetLastError( ERROR_INVALID_INDEX );
1739 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1740 WIN_ReleasePtr( wndPtr );
1741 return retvalue;
1744 switch(offset)
1746 case GWL_HWNDPARENT:
1747 return GetWindowLongW( hwnd, offset );
1748 case GWL_ID:
1749 case GWL_HINSTANCE:
1751 LONG ret = GetWindowLongW( hwnd, offset );
1752 if (HIWORD(ret))
1753 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1754 return LOWORD(ret);
1756 default:
1757 WARN("Invalid offset %d\n", offset );
1758 return 0;
1763 /**********************************************************************
1764 * SetWindowWord (USER32.@)
1766 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1768 WORD *ptr, retval;
1769 WND * wndPtr;
1771 switch(offset)
1773 case GWL_ID:
1774 case GWL_HINSTANCE:
1775 case GWL_HWNDPARENT:
1776 return SetWindowLongW( hwnd, offset, (UINT)newval );
1777 default:
1778 if (offset < 0)
1780 WARN("Invalid offset %d\n", offset );
1781 SetLastError( ERROR_INVALID_INDEX );
1782 return 0;
1786 wndPtr = WIN_GetPtr( hwnd );
1787 if (wndPtr == WND_OTHER_PROCESS)
1789 if (IsWindow(hwnd))
1790 FIXME( "set %d <- %x not supported yet on other process window %x\n",
1791 offset, newval, hwnd );
1792 wndPtr = NULL;
1794 if (!wndPtr)
1796 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1797 return 0;
1800 if (offset > wndPtr->cbWndExtra - sizeof(WORD))
1802 WARN("Invalid offset %d\n", offset );
1803 WIN_ReleasePtr(wndPtr);
1804 SetLastError( ERROR_INVALID_INDEX );
1805 return 0;
1807 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1808 retval = *ptr;
1809 *ptr = newval;
1810 WIN_ReleasePtr(wndPtr);
1811 return retval;
1815 /**********************************************************************
1816 * WIN_GetWindowLong
1818 * Helper function for GetWindowLong().
1820 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1822 LONG retvalue = 0;
1823 WND *wndPtr;
1825 if (offset == GWL_HWNDPARENT) return (LONG)GetParent( hwnd );
1827 if (!(wndPtr = WIN_GetPtr( hwnd )))
1829 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1830 return 0;
1833 if (wndPtr == WND_OTHER_PROCESS)
1835 if (offset >= 0)
1837 if (IsWindow(hwnd))
1838 FIXME( "(%d) not supported on other process window %x\n", offset, hwnd );
1839 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1840 return 0;
1842 if (offset == GWL_WNDPROC)
1844 SetLastError( ERROR_ACCESS_DENIED );
1845 return 0;
1847 SERVER_START_REQ( set_window_info )
1849 req->handle = hwnd;
1850 req->flags = 0; /* don't set anything, just retrieve */
1851 if (!wine_server_call_err( req ))
1853 switch(offset)
1855 case GWL_STYLE: retvalue = reply->old_style; break;
1856 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1857 case GWL_ID: retvalue = reply->old_id; break;
1858 case GWL_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1859 case GWL_USERDATA: retvalue = (ULONG_PTR)reply->old_user_data; break;
1860 default:
1861 SetLastError( ERROR_INVALID_INDEX );
1862 break;
1866 SERVER_END_REQ;
1867 return retvalue;
1870 /* now we have a valid wndPtr */
1872 if (offset >= 0)
1874 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1876 WARN("Invalid offset %d\n", offset );
1877 WIN_ReleasePtr( wndPtr );
1878 SetLastError( ERROR_INVALID_INDEX );
1879 return 0;
1881 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1882 /* Special case for dialog window procedure */
1883 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1884 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1885 WIN_ReleasePtr( wndPtr );
1886 return retvalue;
1889 switch(offset)
1891 case GWL_USERDATA: retvalue = wndPtr->userdata; break;
1892 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1893 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1894 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu; break;
1895 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc, type ); break;
1896 case GWL_HINSTANCE: retvalue = wndPtr->hInstance; break;
1897 default:
1898 WARN("Unknown offset %d\n", offset );
1899 SetLastError( ERROR_INVALID_INDEX );
1900 break;
1902 WIN_ReleasePtr(wndPtr);
1903 return retvalue;
1907 /**********************************************************************
1908 * WIN_SetWindowLong
1910 * Helper function for SetWindowLong().
1912 * 0 is the failure code. However, in the case of failure SetLastError
1913 * must be set to distinguish between a 0 return value and a failure.
1915 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1916 WINDOWPROCTYPE type )
1918 LONG retval = 0;
1919 WND *wndPtr;
1921 TRACE( "%x %d %lx %x\n", hwnd, offset, newval, type );
1923 if (!WIN_IsCurrentProcess( hwnd ))
1925 if (offset == GWL_WNDPROC)
1927 SetLastError( ERROR_ACCESS_DENIED );
1928 return 0;
1930 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, offset, newval );
1933 wndPtr = WIN_GetPtr( hwnd );
1935 if (offset >= 0)
1937 LONG *ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1938 if (offset > wndPtr->cbWndExtra - sizeof(LONG))
1940 WARN("Invalid offset %d\n", offset );
1941 WIN_ReleasePtr( wndPtr );
1942 SetLastError( ERROR_INVALID_INDEX );
1943 return 0;
1945 /* Special case for dialog window procedure */
1946 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1948 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1949 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1950 type, WIN_PROC_WINDOW );
1951 WIN_ReleasePtr( wndPtr );
1952 return retval;
1954 retval = *ptr;
1955 *ptr = newval;
1956 WIN_ReleasePtr( wndPtr );
1958 else
1960 STYLESTRUCT style;
1961 BOOL ok;
1963 /* first some special cases */
1964 switch( offset )
1966 case GWL_STYLE:
1967 case GWL_EXSTYLE:
1968 style.styleOld = wndPtr->dwStyle;
1969 style.styleNew = newval;
1970 WIN_ReleasePtr( wndPtr );
1971 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1972 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1973 newval = style.styleNew;
1974 break;
1975 case GWL_HWNDPARENT:
1976 WIN_ReleasePtr( wndPtr );
1977 return (LONG)SetParent( hwnd, (HWND)newval );
1978 case GWL_WNDPROC:
1979 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1980 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1981 type, WIN_PROC_WINDOW );
1982 WIN_ReleasePtr( wndPtr );
1983 return retval;
1984 case GWL_ID:
1985 case GWL_HINSTANCE:
1986 case GWL_USERDATA:
1987 break;
1988 default:
1989 WIN_ReleasePtr( wndPtr );
1990 WARN("Invalid offset %d\n", offset );
1991 SetLastError( ERROR_INVALID_INDEX );
1992 return 0;
1995 SERVER_START_REQ( set_window_info )
1997 req->handle = hwnd;
1998 switch(offset)
2000 case GWL_STYLE:
2001 req->flags = SET_WIN_STYLE;
2002 req->style = newval;
2003 break;
2004 case GWL_EXSTYLE:
2005 req->flags = SET_WIN_EXSTYLE;
2006 req->ex_style = newval;
2007 break;
2008 case GWL_ID:
2009 req->flags = SET_WIN_ID;
2010 req->id = newval;
2011 break;
2012 case GWL_HINSTANCE:
2013 req->flags = SET_WIN_INSTANCE;
2014 req->instance = (void *)newval;
2015 break;
2016 case GWL_USERDATA:
2017 req->flags = SET_WIN_USERDATA;
2018 req->user_data = (void *)newval;
2019 break;
2021 if ((ok = !wine_server_call_err( req )))
2023 switch(offset)
2025 case GWL_STYLE:
2026 wndPtr->dwStyle = newval;
2027 retval = reply->old_style;
2028 break;
2029 case GWL_EXSTYLE:
2030 wndPtr->dwExStyle = newval;
2031 retval = reply->old_ex_style;
2032 break;
2033 case GWL_ID:
2034 wndPtr->wIDmenu = newval;
2035 retval = reply->old_id;
2036 break;
2037 case GWL_HINSTANCE:
2038 wndPtr->hInstance = newval;
2039 retval = (HINSTANCE)reply->old_instance;
2040 break;
2041 case GWL_USERDATA:
2042 wndPtr->userdata = newval;
2043 retval = (ULONG_PTR)reply->old_user_data;
2044 break;
2048 SERVER_END_REQ;
2049 WIN_ReleasePtr( wndPtr );
2051 if (!ok) return 0;
2053 if (offset == GWL_STYLE && USER_Driver.pSetWindowStyle)
2054 USER_Driver.pSetWindowStyle( hwnd, retval );
2056 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2057 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2060 return retval;
2064 /**********************************************************************
2065 * GetWindowLong (USER.135)
2067 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2069 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
2073 /**********************************************************************
2074 * GetWindowLongA (USER32.@)
2076 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2078 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
2082 /**********************************************************************
2083 * GetWindowLongW (USER32.@)
2085 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2087 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
2091 /**********************************************************************
2092 * SetWindowLong (USER.136)
2094 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2096 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
2100 /**********************************************************************
2101 * SetWindowLongA (USER32.@)
2103 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2105 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
2109 /**********************************************************************
2110 * SetWindowLongW (USER32.@) Set window attribute
2112 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2113 * value in a window's extra memory.
2115 * The _hwnd_ parameter specifies the window. is the handle to a
2116 * window that has extra memory. The _newval_ parameter contains the
2117 * new attribute or extra memory value. If positive, the _offset_
2118 * parameter is the byte-addressed location in the window's extra
2119 * memory to set. If negative, _offset_ specifies the window
2120 * attribute to set, and should be one of the following values:
2122 * GWL_EXSTYLE The window's extended window style
2124 * GWL_STYLE The window's window style.
2126 * GWL_WNDPROC Pointer to the window's window procedure.
2128 * GWL_HINSTANCE The window's pplication instance handle.
2130 * GWL_ID The window's identifier.
2132 * GWL_USERDATA The window's user-specified data.
2134 * If the window is a dialog box, the _offset_ parameter can be one of
2135 * the following values:
2137 * DWL_DLGPROC The address of the window's dialog box procedure.
2139 * DWL_MSGRESULT The return value of a message
2140 * that the dialog box procedure processed.
2142 * DWL_USER Application specific information.
2144 * RETURNS
2146 * If successful, returns the previous value located at _offset_. Otherwise,
2147 * returns 0.
2149 * NOTES
2151 * Extra memory for a window class is specified by a nonzero cbWndExtra
2152 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2153 * time of class creation.
2155 * Using GWL_WNDPROC to set a new window procedure effectively creates
2156 * a window subclass. Use CallWindowProc() in the new windows procedure
2157 * to pass messages to the superclass's window procedure.
2159 * The user data is reserved for use by the application which created
2160 * the window.
2162 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2163 * instead, call the EnableWindow() function to change the window's
2164 * disabled state.
2166 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2167 * SetParent() instead.
2169 * Win95:
2170 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2171 * it sends WM_STYLECHANGING before changing the settings
2172 * and WM_STYLECHANGED afterwards.
2173 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2175 LONG WINAPI SetWindowLongW(
2176 HWND hwnd, /* [in] window to alter */
2177 INT offset, /* [in] offset, in bytes, of location to alter */
2178 LONG newval /* [in] new value of location */
2180 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
2184 /*******************************************************************
2185 * GetWindowTextA (USER32.@)
2187 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2189 WCHAR *buffer;
2191 if (WIN_IsCurrentProcess( hwnd ))
2192 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2194 /* when window belongs to other process, don't send a message */
2195 if (nMaxCount <= 0) return 0;
2196 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2197 get_server_window_text( hwnd, buffer, nMaxCount );
2198 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2199 lpString[nMaxCount-1] = 0;
2200 HeapFree( GetProcessHeap(), 0, buffer );
2201 return strlen(lpString);
2205 /*******************************************************************
2206 * InternalGetWindowText (USER32.@)
2208 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2210 WND *win;
2212 if (nMaxCount <= 0) return 0;
2213 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2214 if (win != WND_OTHER_PROCESS)
2216 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2217 else lpString[0] = 0;
2218 WIN_ReleasePtr( win );
2220 else
2222 get_server_window_text( hwnd, lpString, nMaxCount );
2224 return strlenW(lpString);
2228 /*******************************************************************
2229 * GetWindowTextW (USER32.@)
2231 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2233 if (WIN_IsCurrentProcess( hwnd ))
2234 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2236 /* when window belongs to other process, don't send a message */
2237 if (nMaxCount <= 0) return 0;
2238 get_server_window_text( hwnd, lpString, nMaxCount );
2239 return strlenW(lpString);
2243 /*******************************************************************
2244 * SetWindowText (USER32.@)
2245 * SetWindowTextA (USER32.@)
2247 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2249 if (!WIN_IsCurrentProcess( hwnd ))
2251 FIXME( "cannot set text %s of other process window %x\n", debugstr_a(lpString), hwnd );
2252 SetLastError( ERROR_ACCESS_DENIED );
2253 return FALSE;
2255 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2259 /*******************************************************************
2260 * SetWindowTextW (USER32.@)
2262 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2264 if (!WIN_IsCurrentProcess( hwnd ))
2266 FIXME( "cannot set text %s of other process window %x\n", debugstr_w(lpString), hwnd );
2267 SetLastError( ERROR_ACCESS_DENIED );
2268 return FALSE;
2270 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2274 /*******************************************************************
2275 * GetWindowTextLengthA (USER32.@)
2277 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2279 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2282 /*******************************************************************
2283 * GetWindowTextLengthW (USER32.@)
2285 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2287 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2291 /*******************************************************************
2292 * IsWindow (USER32.@)
2294 BOOL WINAPI IsWindow( HWND hwnd )
2296 WND *ptr;
2297 BOOL ret;
2299 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2301 if (ptr != WND_OTHER_PROCESS)
2303 WIN_ReleasePtr( ptr );
2304 return TRUE;
2307 /* check other processes */
2308 SERVER_START_REQ( get_window_info )
2310 req->handle = hwnd;
2311 ret = !wine_server_call_err( req );
2313 SERVER_END_REQ;
2314 return ret;
2318 /***********************************************************************
2319 * GetWindowThreadProcessId (USER32.@)
2321 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2323 WND *ptr;
2324 DWORD tid = 0;
2326 if (!(ptr = WIN_GetPtr( hwnd )))
2328 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2329 return 0;
2332 if (ptr != WND_OTHER_PROCESS)
2334 /* got a valid window */
2335 tid = ptr->tid;
2336 if (process) *process = GetCurrentProcessId();
2337 WIN_ReleasePtr( ptr );
2338 return tid;
2341 /* check other processes */
2342 SERVER_START_REQ( get_window_info )
2344 req->handle = hwnd;
2345 if (!wine_server_call_err( req ))
2347 tid = (DWORD)reply->tid;
2348 if (process) *process = (DWORD)reply->pid;
2351 SERVER_END_REQ;
2352 return tid;
2356 /*****************************************************************
2357 * GetParent (USER32.@)
2359 HWND WINAPI GetParent( HWND hwnd )
2361 WND *wndPtr;
2362 HWND retvalue = 0;
2364 if (!(wndPtr = WIN_GetPtr( hwnd )))
2366 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2367 return 0;
2369 if (wndPtr == WND_OTHER_PROCESS)
2371 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2372 if (style & (WS_POPUP | WS_CHILD))
2374 SERVER_START_REQ( get_window_tree )
2376 req->handle = hwnd;
2377 if (!wine_server_call_err( req ))
2379 if (style & WS_CHILD) retvalue = reply->parent;
2380 else retvalue = reply->owner;
2383 SERVER_END_REQ;
2386 else
2388 if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2389 else if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2390 WIN_ReleasePtr( wndPtr );
2392 return retvalue;
2396 /*****************************************************************
2397 * GetAncestor (USER32.@)
2399 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2401 WND *win;
2402 HWND *list, ret = 0;
2404 if (type == GA_PARENT)
2406 if (!(win = WIN_GetPtr( hwnd )))
2408 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2409 return 0;
2411 if (win != WND_OTHER_PROCESS)
2413 ret = win->parent;
2414 WIN_ReleasePtr( win );
2416 else /* need to query the server */
2418 SERVER_START_REQ( get_window_tree )
2420 req->handle = hwnd;
2421 if (!wine_server_call_err( req )) ret = reply->parent;
2423 SERVER_END_REQ;
2425 return ret;
2428 if (!(list = WIN_ListParents( hwnd ))) return 0;
2430 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2431 else
2433 int count = 2;
2434 while (list[count]) count++;
2435 ret = list[count - 2]; /* get the one before the desktop */
2437 HeapFree( GetProcessHeap(), 0, list );
2439 if (ret && type == GA_ROOTOWNER)
2441 for (;;)
2443 HWND owner = GetWindow( ret, GW_OWNER );
2444 if (!owner) break;
2445 ret = owner;
2448 return ret;
2452 /*****************************************************************
2453 * SetParent (USER32.@)
2455 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2457 WND *wndPtr;
2458 HWND retvalue, full_handle;
2459 BOOL was_visible;
2461 if (!parent) parent = GetDesktopWindow();
2462 else parent = WIN_GetFullHandle( parent );
2464 if (!IsWindow( parent ))
2466 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2467 return 0;
2470 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2471 return SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2473 hwnd = full_handle;
2475 if (USER_Driver.pSetParent)
2476 return USER_Driver.pSetParent( hwnd, parent );
2478 /* Windows hides the window first, then shows it again
2479 * including the WM_SHOWWINDOW messages and all */
2480 was_visible = ShowWindow( hwnd, SW_HIDE );
2482 if (!IsWindow( parent )) return 0;
2483 if (!(wndPtr = WIN_GetPtr(hwnd)) || wndPtr == WND_OTHER_PROCESS) return 0;
2485 retvalue = wndPtr->parent; /* old parent */
2486 if (parent != retvalue)
2488 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2490 if (parent != GetDesktopWindow()) /* a child window */
2492 if (!(wndPtr->dwStyle & WS_CHILD))
2494 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2495 if (menu) DestroyMenu( menu );
2499 WIN_ReleasePtr( wndPtr );
2501 /* SetParent additionally needs to make hwnd the topmost window
2502 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2503 WM_WINDOWPOSCHANGED notification messages.
2505 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2506 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2507 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2508 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2509 return retvalue;
2513 /*******************************************************************
2514 * IsChild (USER32.@)
2516 BOOL WINAPI IsChild( HWND parent, HWND child )
2518 HWND *list = WIN_ListParents( child );
2519 int i;
2520 BOOL ret;
2522 if (!list) return FALSE;
2523 parent = WIN_GetFullHandle( parent );
2524 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2525 ret = (list[i] != 0);
2526 HeapFree( GetProcessHeap(), 0, list );
2527 return ret;
2531 /***********************************************************************
2532 * IsWindowVisible (USER32.@)
2534 BOOL WINAPI IsWindowVisible( HWND hwnd )
2536 HWND *list;
2537 BOOL retval;
2538 int i;
2540 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2541 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2542 for (i = 0; list[i]; i++)
2543 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2544 retval = !list[i];
2545 HeapFree( GetProcessHeap(), 0, list );
2546 return retval;
2550 /***********************************************************************
2551 * WIN_IsWindowDrawable
2553 * hwnd is drawable when it is visible, all parents are not
2554 * minimized, and it is itself not minimized unless we are
2555 * trying to draw its default class icon.
2557 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2559 HWND *list;
2560 BOOL retval;
2561 int i;
2562 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2564 if (!(style & WS_VISIBLE)) return FALSE;
2565 if ((style & WS_MINIMIZE) && icon && GetClassLongA( hwnd, GCL_HICON )) return FALSE;
2567 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2568 for (i = 0; list[i]; i++)
2569 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2570 break;
2571 retval = !list[i];
2572 HeapFree( GetProcessHeap(), 0, list );
2573 return retval;
2577 /*******************************************************************
2578 * GetTopWindow (USER32.@)
2580 HWND WINAPI GetTopWindow( HWND hwnd )
2582 if (!hwnd) hwnd = GetDesktopWindow();
2583 return GetWindow( hwnd, GW_CHILD );
2587 /*******************************************************************
2588 * GetWindow (USER32.@)
2590 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2592 HWND retval = 0;
2594 if (rel == GW_OWNER) /* this one may be available locally */
2596 WND *wndPtr = WIN_GetPtr( hwnd );
2597 if (!wndPtr)
2599 SetLastError( ERROR_INVALID_HANDLE );
2600 return 0;
2602 if (wndPtr != WND_OTHER_PROCESS)
2604 retval = wndPtr->owner;
2605 WIN_ReleasePtr( wndPtr );
2606 return retval;
2608 /* else fall through to server call */
2611 SERVER_START_REQ( get_window_tree )
2613 req->handle = hwnd;
2614 if (!wine_server_call_err( req ))
2616 switch(rel)
2618 case GW_HWNDFIRST:
2619 retval = reply->first_sibling;
2620 break;
2621 case GW_HWNDLAST:
2622 retval = reply->last_sibling;
2623 break;
2624 case GW_HWNDNEXT:
2625 retval = reply->next_sibling;
2626 break;
2627 case GW_HWNDPREV:
2628 retval = reply->prev_sibling;
2629 break;
2630 case GW_OWNER:
2631 retval = reply->owner;
2632 break;
2633 case GW_CHILD:
2634 retval = reply->first_child;
2635 break;
2639 SERVER_END_REQ;
2640 return retval;
2644 /***********************************************************************
2645 * WIN_InternalShowOwnedPopups
2647 * Internal version of ShowOwnedPopups; Wine functions should use this
2648 * to avoid interfering with application calls to ShowOwnedPopups
2649 * and to make sure the application can't prevent showing/hiding.
2651 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2655 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2657 int count = 0;
2658 WND *pWnd;
2659 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2661 if (!win_array) return TRUE;
2664 * Show windows Lowest first, Highest last to preserve Z-Order
2666 while (win_array[count]) count++;
2667 while (--count >= 0)
2669 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2670 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2672 if (pWnd->dwStyle & WS_POPUP)
2674 if (fShow)
2676 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2677 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2680 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2682 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2683 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2686 else
2688 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2689 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2690 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2693 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2695 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2696 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2697 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2701 WIN_ReleaseWndPtr( pWnd );
2703 HeapFree( GetProcessHeap(), 0, win_array );
2705 return TRUE;
2708 /*******************************************************************
2709 * ShowOwnedPopups (USER32.@)
2711 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2713 int count = 0;
2714 WND *pWnd;
2715 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2717 if (!win_array) return TRUE;
2719 while (win_array[count]) count++;
2720 while (--count >= 0)
2722 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2723 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2725 if (pWnd->dwStyle & WS_POPUP)
2727 if (fShow)
2729 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2731 /* In Windows, ShowOwnedPopups(TRUE) generates
2732 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2733 * regardless of the state of the owner
2735 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2736 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2739 else
2741 if (IsWindowVisible(pWnd->hwndSelf))
2743 /* In Windows, ShowOwnedPopups(FALSE) generates
2744 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2745 * regardless of the state of the owner
2747 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2748 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2752 WIN_ReleaseWndPtr( pWnd );
2754 HeapFree( GetProcessHeap(), 0, win_array );
2755 return TRUE;
2759 /*******************************************************************
2760 * GetLastActivePopup (USER32.@)
2762 HWND WINAPI GetLastActivePopup( HWND hwnd )
2764 HWND retval;
2765 WND *wndPtr =WIN_FindWndPtr(hwnd);
2766 if (!wndPtr) return hwnd;
2767 retval = wndPtr->hwndLastActive;
2768 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2769 WIN_ReleaseWndPtr(wndPtr);
2770 return retval;
2774 /*******************************************************************
2775 * WIN_ListParents
2777 * Build an array of all parents of a given window, starting with
2778 * the immediate parent. The array must be freed with HeapFree.
2779 * Returns NULL if window is a top-level window.
2781 HWND *WIN_ListParents( HWND hwnd )
2783 WND *win;
2784 HWND current, *list;
2785 int pos = 0, size = 16, count = 0;
2787 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2789 current = hwnd;
2790 for (;;)
2792 if (!(win = WIN_GetPtr( current ))) goto empty;
2793 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
2794 list[pos] = win->parent;
2795 WIN_ReleasePtr( win );
2796 if (!(current = list[pos]))
2798 if (!pos) goto empty;
2799 return list;
2801 if (++pos == size - 1)
2803 /* need to grow the list */
2804 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
2805 if (!new_list) goto empty;
2806 list = new_list;
2807 size += 16;
2811 /* at least one parent belongs to another process, have to query the server */
2813 for (;;)
2815 count = 0;
2816 SERVER_START_REQ( get_window_parents )
2818 req->handle = hwnd;
2819 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
2820 if (!wine_server_call( req )) count = reply->count;
2822 SERVER_END_REQ;
2823 if (!count) goto empty;
2824 if (size > count)
2826 list[count] = 0;
2827 return list;
2829 HeapFree( GetProcessHeap(), 0, list );
2830 size = count + 1;
2831 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
2834 empty:
2835 HeapFree( GetProcessHeap(), 0, list );
2836 return NULL;
2840 /*******************************************************************
2841 * WIN_ListChildren
2843 * Build an array of the children of a given window. The array must be
2844 * freed with HeapFree. Returns NULL when no windows are found.
2846 HWND *WIN_ListChildren( HWND hwnd )
2848 return list_window_children( hwnd, 0, 0 );
2852 /*******************************************************************
2853 * EnumWindows (USER32.@)
2855 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2857 HWND *list;
2858 BOOL ret = TRUE;
2859 int i, iWndsLocks;
2861 /* We have to build a list of all windows first, to avoid */
2862 /* unpleasant side-effects, for instance if the callback */
2863 /* function changes the Z-order of the windows. */
2865 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2867 /* Now call the callback function for every window */
2869 iWndsLocks = WIN_SuspendWndsLock();
2870 for (i = 0; list[i]; i++)
2872 /* Make sure that the window still exists */
2873 if (!IsWindow( list[i] )) continue;
2874 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2876 WIN_RestoreWndsLock(iWndsLocks);
2877 HeapFree( GetProcessHeap(), 0, list );
2878 return ret;
2882 /**********************************************************************
2883 * EnumThreadWindows (USER32.@)
2885 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2887 HWND *list;
2888 int i, iWndsLocks;
2890 if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
2891 return TRUE ;
2893 /* Now call the callback function for every window */
2895 iWndsLocks = WIN_SuspendWndsLock();
2896 for (i = 0; list[i]; i++)
2897 if (!func( list[i], lParam )) break;
2898 WIN_RestoreWndsLock(iWndsLocks);
2899 HeapFree( GetProcessHeap(), 0, list );
2900 return TRUE;
2904 /**********************************************************************
2905 * WIN_EnumChildWindows
2907 * Helper function for EnumChildWindows().
2909 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2911 HWND *childList;
2912 BOOL ret = FALSE;
2914 for ( ; *list; list++)
2916 /* Make sure that the window still exists */
2917 if (!IsWindow( *list )) continue;
2918 /* skip owned windows */
2919 if (GetWindow( *list, GW_OWNER )) continue;
2920 /* Build children list first */
2921 childList = WIN_ListChildren( *list );
2923 ret = func( *list, lParam );
2925 if (childList)
2927 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2928 HeapFree( GetProcessHeap(), 0, childList );
2930 if (!ret) return FALSE;
2932 return TRUE;
2936 /**********************************************************************
2937 * EnumChildWindows (USER32.@)
2939 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2941 HWND *list;
2942 int iWndsLocks;
2944 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2945 iWndsLocks = WIN_SuspendWndsLock();
2946 WIN_EnumChildWindows( list, func, lParam );
2947 WIN_RestoreWndsLock(iWndsLocks);
2948 HeapFree( GetProcessHeap(), 0, list );
2949 return TRUE;
2953 /*******************************************************************
2954 * AnyPopup (USER.52)
2956 BOOL16 WINAPI AnyPopup16(void)
2958 return AnyPopup();
2962 /*******************************************************************
2963 * AnyPopup (USER32.@)
2965 BOOL WINAPI AnyPopup(void)
2967 int i;
2968 BOOL retvalue;
2969 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2971 if (!list) return FALSE;
2972 for (i = 0; list[i]; i++)
2974 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2976 retvalue = (list[i] != 0);
2977 HeapFree( GetProcessHeap(), 0, list );
2978 return retvalue;
2982 /*******************************************************************
2983 * FlashWindow (USER32.@)
2985 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2987 WND *wndPtr = WIN_FindWndPtr(hWnd);
2989 TRACE("%04x\n", hWnd);
2991 if (!wndPtr) return FALSE;
2992 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2994 if (wndPtr->dwStyle & WS_MINIMIZE)
2996 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2998 HDC hDC = GetDC(hWnd);
3000 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
3001 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
3003 ReleaseDC( hWnd, hDC );
3004 wndPtr->flags |= WIN_NCACTIVATED;
3006 else
3008 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3009 wndPtr->flags &= ~WIN_NCACTIVATED;
3011 WIN_ReleaseWndPtr(wndPtr);
3012 return TRUE;
3014 else
3016 WPARAM16 wparam;
3017 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3018 else wparam = (hWnd == GetActiveWindow());
3020 WIN_ReleaseWndPtr(wndPtr);
3021 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3022 return wparam;
3027 /*******************************************************************
3028 * GetWindowContextHelpId (USER32.@)
3030 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3032 DWORD retval;
3033 WND *wnd = WIN_FindWndPtr( hwnd );
3034 if (!wnd) return 0;
3035 retval = wnd->helpContext;
3036 WIN_ReleaseWndPtr(wnd);
3037 return retval;
3041 /*******************************************************************
3042 * SetWindowContextHelpId (USER32.@)
3044 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3046 WND *wnd = WIN_FindWndPtr( hwnd );
3047 if (!wnd) return FALSE;
3048 wnd->helpContext = id;
3049 WIN_ReleaseWndPtr(wnd);
3050 return TRUE;
3054 /*******************************************************************
3055 * DRAG_QueryUpdate
3057 * recursively find a child that contains spDragInfo->pt point
3058 * and send WM_QUERYDROPOBJECT
3060 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
3062 BOOL16 wParam, bResult = 0;
3063 POINT pt;
3064 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
3065 RECT tempRect;
3067 if (!ptrDragInfo) return FALSE;
3069 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
3071 GetWindowRect(hQueryWnd,&tempRect);
3073 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
3075 if (!IsIconic( hQueryWnd ))
3077 GetClientRect( hQueryWnd, &tempRect );
3078 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
3080 if (PtInRect( &tempRect, pt))
3082 int i;
3083 HWND *list = WIN_ListChildren( hQueryWnd );
3085 wParam = 0;
3087 if (list)
3089 for (i = 0; list[i]; i++)
3091 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
3093 GetWindowRect( list[i], &tempRect );
3094 if (PtInRect( &tempRect, pt )) break;
3097 if (list[i])
3099 if (IsWindowEnabled( list[i] ))
3100 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
3102 HeapFree( GetProcessHeap(), 0, list );
3104 if(bResult) return bResult;
3106 else wParam = 1;
3108 else wParam = 1;
3110 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
3112 ptrDragInfo->hScope = hQueryWnd;
3114 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
3115 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
3117 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
3119 return bResult;
3123 /*******************************************************************
3124 * DragDetect (USER32.@)
3126 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3128 MSG msg;
3129 RECT rect;
3131 rect.left = pt.x - wDragWidth;
3132 rect.right = pt.x + wDragWidth;
3134 rect.top = pt.y - wDragHeight;
3135 rect.bottom = pt.y + wDragHeight;
3137 SetCapture(hWnd);
3139 while(1)
3141 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
3143 if( msg.message == WM_LBUTTONUP )
3145 ReleaseCapture();
3146 return 0;
3148 if( msg.message == WM_MOUSEMOVE )
3150 POINT tmp;
3151 tmp.x = LOWORD(msg.lParam);
3152 tmp.y = HIWORD(msg.lParam);
3153 if( !PtInRect( &rect, tmp ))
3155 ReleaseCapture();
3156 return 1;
3160 WaitMessage();
3162 return 0;
3165 /******************************************************************************
3166 * DragObject (USER.464)
3168 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
3169 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
3171 MSG msg;
3172 LPDRAGINFO16 lpDragInfo;
3173 SEGPTR spDragInfo;
3174 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
3175 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
3176 HCURSOR16 hCurrentCursor = 0;
3177 HWND16 hCurrentWnd = 0;
3179 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
3180 spDragInfo = K32WOWGlobalLock16(hDragInfo);
3182 if( !lpDragInfo || !spDragInfo ) return 0L;
3184 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
3186 GlobalFree16(hDragInfo);
3187 return 0L;
3190 if(hCursor)
3192 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
3194 GlobalFree16(hDragInfo);
3195 return 0L;
3198 if( hDragCursor == hCursor ) hDragCursor = 0;
3199 else hCursor = hDragCursor;
3201 hOldCursor = SetCursor(hDragCursor);
3204 lpDragInfo->hWnd = hWnd;
3205 lpDragInfo->hScope = 0;
3206 lpDragInfo->wFlags = wObj;
3207 lpDragInfo->hList = szList; /* near pointer! */
3208 lpDragInfo->hOfStruct = hOfStruct;
3209 lpDragInfo->l = 0L;
3211 SetCapture(hWnd);
3212 ShowCursor( TRUE );
3216 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
3218 *(lpDragInfo+1) = *lpDragInfo;
3220 lpDragInfo->pt.x = msg.pt.x;
3221 lpDragInfo->pt.y = msg.pt.y;
3223 /* update DRAGINFO struct */
3224 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
3226 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
3227 hCurrentCursor = hCursor;
3228 else
3230 hCurrentCursor = hBummer;
3231 lpDragInfo->hScope = 0;
3233 if( hCurrentCursor )
3234 SetCursor(hCurrentCursor);
3236 /* send WM_DRAGLOOP */
3237 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
3238 (LPARAM) spDragInfo );
3239 /* send WM_DRAGSELECT or WM_DRAGMOVE */
3240 if( hCurrentWnd != lpDragInfo->hScope )
3242 if( hCurrentWnd )
3243 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
3244 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
3245 HIWORD(spDragInfo)) );
3246 hCurrentWnd = lpDragInfo->hScope;
3247 if( hCurrentWnd )
3248 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
3250 else
3251 if( hCurrentWnd )
3252 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
3254 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
3256 ReleaseCapture();
3257 ShowCursor( FALSE );
3259 if( hCursor )
3261 SetCursor( hOldCursor );
3262 if (hDragCursor) DestroyCursor( hDragCursor );
3265 if( hCurrentCursor != hBummer )
3266 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
3267 (WPARAM16)hWnd, (LPARAM)spDragInfo );
3268 else
3269 msg.lParam = 0;
3270 GlobalFree16(hDragInfo);
3272 return (DWORD)(msg.lParam);
3276 /******************************************************************************
3277 * GetWindowModuleFileNameA (USER32.@)
3279 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3281 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3282 hwnd, lpszFileName, cchFileNameMax);
3283 return 0;
3286 /******************************************************************************
3287 * GetWindowModuleFileNameW (USER32.@)
3289 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
3291 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
3292 hwnd, lpszFileName, cchFileNameMax);
3293 return 0;