2 * Window related functions
4 * Copyright 1993, 1994 Alexandre Julliard
10 #include "wine/winbase16.h"
11 #include "wine/winuser16.h"
12 #include "wine/server.h"
13 #include "wine/unicode.h"
19 #include "cursoricon.h"
26 #include "stackframe.h"
27 #include "debugtools.h"
29 DEFAULT_DEBUG_CHANNEL(win);
30 DECLARE_DEBUG_CHANNEL(msg);
32 /**********************************************************************/
35 static WND *pWndDesktop = NULL;
37 static WORD wDragWidth = 4;
38 static WORD wDragHeight= 3;
40 static void *user_handles[65536];
43 extern SYSLEVEL USER_SysLevel; /* FIXME */
45 /***********************************************************************
48 * Suspend the lock on WND structures.
49 * Returns the number of locks suspended
51 int WIN_SuspendWndsLock( void )
53 int isuspendedLocks = _ConfirmSysLevel( &USER_SysLevel );
54 int count = isuspendedLocks;
57 _LeaveSysLevel( &USER_SysLevel );
59 return isuspendedLocks;
62 /***********************************************************************
65 * Restore the suspended locks on WND structures
67 void WIN_RestoreWndsLock( int ipreviousLocks )
69 while ( ipreviousLocks-- > 0 )
70 _EnterSysLevel( &USER_SysLevel );
73 /***********************************************************************
74 * create_window_handle
76 * Create a window handle with the server.
78 static WND *create_window_handle( HWND parent, HWND owner, INT size )
81 user_handle_t handle = 0;
82 WND *win = HeapAlloc( GetProcessHeap(), 0, size );
84 if (!win) return NULL;
88 SERVER_START_REQ( create_window )
92 if ((res = !SERVER_CALL_ERR())) handle = req->handle;
99 HeapFree( GetProcessHeap(), 0, win );
102 user_handles[LOWORD(handle)] = win;
103 win->hwndSelf = handle;
104 win->dwMagic = WND_MAGIC;
110 /***********************************************************************
113 * Free a window handle.
115 static WND *free_window_handle( HWND hwnd )
120 if ((ptr = user_handles[LOWORD(hwnd)]))
122 SERVER_START_REQ( destroy_window )
125 if (!SERVER_CALL_ERR())
126 user_handles[LOWORD(hwnd)] = NULL;
133 if (ptr) HeapFree( GetProcessHeap(), 0, ptr );
138 /***********************************************************************
141 * Return a pointer to the WND structure if local to the process.
142 * If ret value is non-NULL, the user lock is held.
144 static WND *get_wnd_ptr( HWND hwnd )
148 if (!hwnd) return NULL;
151 if ((ptr = user_handles[LOWORD(hwnd)]))
153 if (ptr->dwMagic == WND_MAGIC && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
161 /***********************************************************************
164 * Convert a 16-bit window handle to a full 32-bit handle.
166 HWND WIN_Handle32( HWND16 hwnd16 )
169 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
171 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
172 /* do sign extension for -2 and -3 */
173 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
175 if ((ptr = get_wnd_ptr( hwnd )))
177 hwnd = ptr->hwndSelf;
180 else /* may belong to another process */
182 SERVER_START_REQ( get_window_info )
185 if (!SERVER_CALL_ERR()) hwnd = req->full_handle;
193 /***********************************************************************
196 * Return a pointer to the WND structure corresponding to a HWND.
198 WND * WIN_FindWndPtr( HWND hwnd )
202 if (!hwnd) return NULL;
204 if ((ptr = get_wnd_ptr( hwnd )))
206 /* increment destruction monitoring */
211 /* check other processes */
212 if (IsWindow( hwnd ))
214 ERR( "window %04x belongs to other process\n", hwnd );
215 /* DbgBreakPoint(); */
217 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
222 /***********************************************************************
225 * Use in case the wnd ptr is not initialized with WIN_FindWndPtr
227 * Returns the locked initialisation pointer
229 WND *WIN_LockWndPtr(WND *initWndPtr)
231 if(!initWndPtr) return 0;
233 /* Lock all WND structures for thread safeness*/
235 /*and increment destruction monitoring*/
236 initWndPtr->irefCount++;
242 /***********************************************************************
245 * Release the pointer to the WND structure.
247 void WIN_ReleaseWndPtr(WND *wndPtr)
251 /*Decrement destruction monitoring value*/
253 /* Check if it's time to release the memory*/
254 if(wndPtr->irefCount == 0 && !wndPtr->dwMagic)
257 free_window_handle( wndPtr->hwndSelf );
259 else if(wndPtr->irefCount < 0)
261 /* This else if is useful to monitor the WIN_ReleaseWndPtr function */
262 ERR("forgot a Lock on %p somewhere\n",wndPtr);
264 /*unlock all WND structures for thread safeness*/
268 /***********************************************************************
271 * Updates the value of oldPtr to newPtr.
273 void WIN_UpdateWndPtr(WND **oldPtr, WND *newPtr)
277 tmpWnd = WIN_LockWndPtr(newPtr);
278 WIN_ReleaseWndPtr(*oldPtr);
284 /***********************************************************************
287 * Remove a window from the siblings linked list.
289 void WIN_UnlinkWindow( HWND hwnd )
291 WIN_LinkWindow( hwnd, 0, 0 );
295 /***********************************************************************
298 * Insert a window into the siblings linked list.
299 * The window is inserted after the specified window, which can also
300 * be specified as HWND_TOP or HWND_BOTTOM.
301 * If parent is 0, window is unlinked from the tree.
303 void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter )
305 WND *wndPtr, **ppWnd, *parentPtr = NULL;
308 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
309 if (parent && !(parentPtr = WIN_FindWndPtr( parent )))
311 WIN_ReleaseWndPtr(wndPtr);
315 SERVER_START_REQ( link_window )
318 req->parent = parent;
319 req->previous = hwndInsertAfter;
320 ret = !SERVER_CALL_ERR();
325 /* first unlink it if it is linked */
328 ppWnd = &wndPtr->parent->child;
329 while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next;
330 if (*ppWnd) *ppWnd = wndPtr->next;
335 wndPtr->parent = parentPtr;
336 if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
338 ppWnd = &parentPtr->child; /* Point to first sibling hwnd */
339 if (hwndInsertAfter == HWND_BOTTOM) /* Find last sibling hwnd */
340 while (*ppWnd) ppWnd = &(*ppWnd)->next;
342 else /* Normal case */
344 WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
345 if (!afterPtr) goto done;
346 ppWnd = &afterPtr->next;
347 WIN_ReleaseWndPtr(afterPtr);
349 wndPtr->next = *ppWnd;
352 else wndPtr->next = NULL; /* unlinked */
355 WIN_ReleaseWndPtr( parentPtr );
356 WIN_ReleaseWndPtr( wndPtr );
360 /***********************************************************************
361 * WIN_FindWinToRepaint
363 * Find a window that needs repaint.
365 HWND WIN_FindWinToRepaint( HWND hwnd )
370 /* Note: the desktop window never gets WM_PAINT messages
371 * The real reason why is because Windows DesktopWndProc
372 * does ValidateRgn inside WM_ERASEBKGND handler.
374 if (hwnd == GetDesktopWindow()) hwnd = 0;
376 pWnd = hwnd ? WIN_FindWndPtr(hwnd) : WIN_LockWndPtr(pWndDesktop->child);
378 for ( ; pWnd ; WIN_UpdateWndPtr(&pWnd,pWnd->next))
380 if (!(pWnd->dwStyle & WS_VISIBLE)) continue;
381 if ((pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
382 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
386 if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf )) )
388 WIN_ReleaseWndPtr(pWnd);
396 TRACE("nothing found\n");
399 hwndRet = pWnd->hwndSelf;
401 /* look among siblings if we got a transparent window */
404 if (!(pWnd->dwExStyle & WS_EX_TRANSPARENT) &&
405 (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT)) &&
406 GetWindowThreadProcessId( pWnd->hwndSelf, NULL ) == GetCurrentThreadId())
408 hwndRet = pWnd->hwndSelf;
409 WIN_ReleaseWndPtr(pWnd);
412 WIN_UpdateWndPtr(&pWnd,pWnd->next);
414 TRACE("found %04x\n",hwndRet);
419 /***********************************************************************
422 * Destroy storage associated to a window. "Internals" p.358
423 * returns a locked wndPtr->next
425 static WND* WIN_DestroyWindow( WND* wndPtr )
427 HWND hwnd = wndPtr->hwndSelf;
430 TRACE("%04x\n", wndPtr->hwndSelf );
432 /* free child windows */
433 WIN_LockWndPtr(wndPtr->child);
434 while ((pWnd = wndPtr->child))
436 wndPtr->child = WIN_DestroyWindow( pWnd );
437 WIN_ReleaseWndPtr(pWnd);
441 * Clear the update region to make sure no WM_PAINT messages will be
442 * generated for this window while processing the WM_NCDESTROY.
444 RedrawWindow( wndPtr->hwndSelf, NULL, 0,
445 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
448 * Send the WM_NCDESTROY to the window being destroyed.
450 SendMessageA( wndPtr->hwndSelf, WM_NCDESTROY, 0, 0);
452 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
454 WINPOS_CheckInternalPos( hwnd );
455 if( hwnd == GetCapture()) ReleaseCapture();
457 /* free resources associated with the window */
459 TIMER_RemoveWindowTimers( wndPtr->hwndSelf );
460 PROPERTY_RemoveWindowProps( wndPtr );
462 /* toss stale messages from the queue */
464 QUEUE_CleanupWindow( hwnd );
465 wndPtr->hmemTaskQ = 0;
467 if (!(wndPtr->dwStyle & WS_CHILD))
470 DestroyMenu( wndPtr->wIDmenu );
473 if (wndPtr->hSysMenu)
475 DestroyMenu( wndPtr->hSysMenu );
476 wndPtr->hSysMenu = 0;
478 USER_Driver.pDestroyWindow( wndPtr->hwndSelf );
479 DCE_FreeWindowDCE( wndPtr->hwndSelf ); /* Always do this to catch orphaned DCs */
480 WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW );
481 CLASS_RemoveWindow( wndPtr->class );
482 wndPtr->class = NULL;
483 wndPtr->dwMagic = 0; /* Mark it as invalid */
485 WIN_UpdateWndPtr(&pWnd,wndPtr->next);
490 /***********************************************************************
491 * WIN_DestroyThreadWindows
493 * Destroy all children of 'wnd' owned by the current thread.
494 * Return TRUE if something was done.
496 void WIN_DestroyThreadWindows( HWND hwnd )
501 if (!(list = WIN_ListChildren( hwnd ))) return;
502 for (i = 0; list[i]; i++)
504 if (!IsWindow( list[i] )) continue;
505 if (GetWindowThreadProcessId( list[i], NULL ) == GetCurrentThreadId())
506 DestroyWindow( list[i] );
508 WIN_DestroyThreadWindows( list[i] );
510 HeapFree( GetProcessHeap(), 0, list );
513 /***********************************************************************
514 * WIN_CreateDesktopWindow
516 * Create the desktop window.
518 BOOL WIN_CreateDesktopWindow(void)
520 struct tagCLASS *class;
528 TRACE("Creating desktop window\n");
531 if (!WINPOS_CreateInternalPosAtom() ||
532 !(class = CLASS_AddWindow( (ATOM)LOWORD(DESKTOP_CLASS_ATOM), 0, WIN_PROC_32W,
533 &wndExtra, &winproc, &clsStyle, &dce )))
536 pWndDesktop = create_window_handle( 0, 0, sizeof(WND) + wndExtra );
537 if (!pWndDesktop) return FALSE;
538 hwndDesktop = pWndDesktop->hwndSelf;
540 pWndDesktop->tid = 0; /* nobody owns the desktop */
541 pWndDesktop->next = NULL;
542 pWndDesktop->child = NULL;
543 pWndDesktop->parent = NULL;
544 pWndDesktop->owner = 0;
545 pWndDesktop->class = class;
546 pWndDesktop->hInstance = 0;
547 pWndDesktop->rectWindow.left = 0;
548 pWndDesktop->rectWindow.top = 0;
549 pWndDesktop->rectWindow.right = GetSystemMetrics(SM_CXSCREEN);
550 pWndDesktop->rectWindow.bottom = GetSystemMetrics(SM_CYSCREEN);
551 pWndDesktop->rectClient = pWndDesktop->rectWindow;
552 pWndDesktop->text = NULL;
553 pWndDesktop->hmemTaskQ = 0;
554 pWndDesktop->hrgnUpdate = 0;
555 pWndDesktop->hwndLastActive = hwndDesktop;
556 pWndDesktop->dwStyle = WS_VISIBLE | WS_CLIPCHILDREN |
558 pWndDesktop->dwExStyle = 0;
559 pWndDesktop->clsStyle = clsStyle;
560 pWndDesktop->dce = NULL;
561 pWndDesktop->pVScroll = NULL;
562 pWndDesktop->pHScroll = NULL;
563 pWndDesktop->pProp = NULL;
564 pWndDesktop->wIDmenu = 0;
565 pWndDesktop->helpContext = 0;
566 pWndDesktop->flags = 0;
567 pWndDesktop->hSysMenu = 0;
568 pWndDesktop->userdata = 0;
569 pWndDesktop->winproc = winproc;
570 pWndDesktop->cbWndExtra = wndExtra;
572 cs.lpCreateParams = NULL;
578 cs.cx = pWndDesktop->rectWindow.right;
579 cs.cy = pWndDesktop->rectWindow.bottom;
580 cs.style = pWndDesktop->dwStyle;
581 cs.dwExStyle = pWndDesktop->dwExStyle;
583 cs.lpszClass = DESKTOP_CLASS_ATOM;
585 if (!USER_Driver.pCreateWindow( hwndDesktop, &cs, FALSE )) return FALSE;
587 pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND;
588 WIN_ReleaseWndPtr( pWndDesktop );
593 /***********************************************************************
596 * Fix the coordinates - Helper for WIN_CreateWindowEx.
597 * returns default show mode in sw.
598 * Note: the feature presented as undocumented *is* in the MSDN since 1993.
600 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
602 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16 ||
603 cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
605 if (cs->style & (WS_CHILD | WS_POPUP))
607 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) cs->x = cs->y = 0;
608 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16) cs->cx = cs->cy = 0;
610 else /* overlapped window */
614 GetStartupInfoA( &info );
616 if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16)
618 /* Never believe Microsoft's documentation... CreateWindowEx doc says
619 * that if an overlapped window is created with WS_VISIBLE style bit
620 * set and the x parameter is set to CW_USEDEFAULT, the system ignores
621 * the y parameter. However, disassembling NT implementation (WIN32K.SYS)
624 * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16
625 * 2) it does not ignore the y parameter as the docs claim; instead, it
626 * uses it as second parameter to ShowWindow() unless y is either
627 * CW_USEDEFAULT or CW_USEDEFAULT16.
629 * The fact that we didn't do 2) caused bogus windows pop up when wine
630 * was running apps that were using this obscure feature. Example -
631 * calc.exe that comes with Win98 (only Win98, it's different from
632 * the one that comes with Win95 and NT)
634 if (cs->y != CW_USEDEFAULT && cs->y != CW_USEDEFAULT16) *sw = cs->y;
635 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
636 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
639 if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16)
641 if (info.dwFlags & STARTF_USESIZE)
643 cs->cx = info.dwXSize;
644 cs->cy = info.dwYSize;
646 else /* if no other hint from the app, pick 3/4 of the screen real estate */
649 SystemParametersInfoA( SPI_GETWORKAREA, 0, &r, 0);
650 cs->cx = (((r.right - r.left) * 3) / 4) - cs->x;
651 cs->cy = (((r.bottom - r.top) * 3) / 4) - cs->y;
658 /***********************************************************************
661 * Implementation of CreateWindowEx().
663 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
664 WINDOWPROCTYPE type )
667 struct tagCLASS *classPtr;
669 HWND hwnd, hwndLinkAfter, parent, owner;
670 POINT maxSize, maxPos, minTrack, maxTrack;
675 BOOL unicode = (type == WIN_PROC_32W);
677 TRACE("%s %s ex=%08lx style=%08lx %d,%d %dx%d parent=%04x menu=%04x inst=%08x params=%p\n",
678 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszName) : debugres_a(cs->lpszName),
679 (type == WIN_PROC_32W) ? debugres_w((LPWSTR)cs->lpszClass) : debugres_a(cs->lpszClass),
680 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
681 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
683 TRACE("winproc type is %d (%s)\n", type, (type == WIN_PROC_16) ? "WIN_PROC_16" :
684 ((type == WIN_PROC_32A) ? "WIN_PROC_32A" : "WIN_PROC_32W") );
686 /* Find the parent window */
688 parent = GetDesktopWindow();
692 /* Make sure parent is valid */
693 if (!IsWindow( cs->hwndParent ))
695 WARN("Bad parent %04x\n", cs->hwndParent );
698 if (cs->style & WS_CHILD) parent = cs->hwndParent;
699 else owner = GetAncestor( cs->hwndParent, GA_ROOT );
701 else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP))
703 WARN("No parent for child window\n" );
704 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
707 /* Find the window class */
708 if (!(classPtr = CLASS_AddWindow( classAtom, cs->hInstance, type,
709 &wndExtra, &winproc, &clsStyle, &dce )))
711 WARN("Bad class '%s'\n", cs->lpszClass );
715 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
717 /* Correct the window style - stage 1
719 * These are patches that appear to affect both the style loaded into the
720 * WIN structure and passed in the CreateStruct to the WM_CREATE etc.
722 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
723 * why does the user get to set it?
726 /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been
727 * tested for WS_POPUP
729 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
730 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
731 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
732 cs->dwExStyle |= WS_EX_WINDOWEDGE;
734 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
736 /* Create the window structure */
738 if (!(wndPtr = create_window_handle( parent, owner,
739 sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
741 TRACE("out of memory\n" );
744 hwnd = wndPtr->hwndSelf;
746 /* Fill the window structure */
748 wndPtr->tid = GetCurrentThreadId();
750 wndPtr->child = NULL;
751 wndPtr->owner = owner;
752 wndPtr->parent = WIN_FindWndPtr( parent );
753 WIN_ReleaseWndPtr(wndPtr->parent);
755 wndPtr->class = classPtr;
756 wndPtr->winproc = winproc;
757 wndPtr->hInstance = cs->hInstance;
759 wndPtr->hmemTaskQ = InitThreadInput16( 0, 0 );
760 wndPtr->hrgnUpdate = 0;
762 wndPtr->hwndLastActive = hwnd;
763 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
764 wndPtr->dwExStyle = cs->dwExStyle;
765 wndPtr->clsStyle = clsStyle;
767 wndPtr->helpContext = 0;
768 wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
769 wndPtr->pVScroll = NULL;
770 wndPtr->pHScroll = NULL;
771 wndPtr->pProp = NULL;
772 wndPtr->userdata = 0;
773 wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
774 ? MENU_GetSysMenu( hwnd, 0 ) : 0;
775 wndPtr->cbWndExtra = wndExtra;
777 if (wndExtra) memset( wndPtr->wExtra, 0, wndExtra);
779 /* Call the WH_CBT hook */
781 hwndLinkAfter = ((cs->style & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD)
782 ? HWND_BOTTOM : HWND_TOP;
784 if (HOOK_IsHooked( WH_CBT ))
790 cbtc.hwndInsertAfter = hwndLinkAfter;
791 ret = (type == WIN_PROC_32W) ? HOOK_CallHooksW(WH_CBT, HCBT_CREATEWND,
792 (WPARAM)hwnd, (LPARAM)&cbtc)
793 : HOOK_CallHooksA(WH_CBT, HCBT_CREATEWND,
794 (WPARAM)hwnd, (LPARAM)&cbtc);
797 TRACE("CBT-hook returned 0\n");
798 free_window_handle( hwnd );
799 CLASS_RemoveWindow( classPtr );
805 /* Correct the window style - stage 2 */
807 if (!(cs->style & WS_CHILD))
809 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
810 if (!(cs->style & WS_POPUP))
812 wndPtr->dwStyle |= WS_CAPTION;
813 wndPtr->flags |= WIN_NEED_SIZE;
817 /* Get class or window DC if needed */
819 if (clsStyle & CS_OWNDC) wndPtr->dce = DCE_AllocDCE(hwnd,DCE_WINDOW_DC);
820 else if (clsStyle & CS_CLASSDC) wndPtr->dce = dce;
821 else wndPtr->dce = NULL;
823 /* Initialize the dimensions before sending WM_GETMINMAXINFO */
825 wndPtr->rectWindow.left = cs->x;
826 wndPtr->rectWindow.top = cs->y;
827 wndPtr->rectWindow.right = cs->x + cs->cx;
828 wndPtr->rectWindow.bottom = cs->y + cs->cy;
829 wndPtr->rectClient = wndPtr->rectWindow;
831 /* Send the WM_GETMINMAXINFO message and fix the size if needed */
833 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
835 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
836 if (maxSize.x < cs->cx) cs->cx = maxSize.x;
837 if (maxSize.y < cs->cy) cs->cy = maxSize.y;
838 if (cs->cx < minTrack.x ) cs->cx = minTrack.x;
839 if (cs->cy < minTrack.y ) cs->cy = minTrack.y;
842 if (cs->cx < 0) cs->cx = 0;
843 if (cs->cy < 0) cs->cy = 0;
845 wndPtr->rectWindow.left = cs->x;
846 wndPtr->rectWindow.top = cs->y;
847 wndPtr->rectWindow.right = cs->x + cs->cx;
848 wndPtr->rectWindow.bottom = cs->y + cs->cy;
849 wndPtr->rectClient = wndPtr->rectWindow;
851 /* Set the window menu */
853 if ((wndPtr->dwStyle & (WS_CAPTION | WS_CHILD)) == WS_CAPTION )
855 if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
858 LPCSTR menuName = (LPCSTR)GetClassLongA( hwnd, GCL_MENUNAME );
861 if (HIWORD(cs->hInstance))
862 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
864 cs->hMenu = LoadMenu16(cs->hInstance,menuName);
866 if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
870 else wndPtr->wIDmenu = (UINT)cs->hMenu;
872 if (!USER_Driver.pCreateWindow( wndPtr->hwndSelf, cs, unicode))
874 WARN("aborted by WM_xxCREATE!\n");
875 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
876 CLASS_RemoveWindow( classPtr );
877 WIN_ReleaseWndPtr(wndPtr);
881 if( (wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
883 /* Notify the parent window only */
885 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
886 MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd );
887 if( !IsWindow(hwnd) )
894 if (cs->style & WS_VISIBLE)
896 /* in case WS_VISIBLE got set in the meantime */
897 wndPtr->dwStyle &= ~WS_VISIBLE;
898 ShowWindow( hwnd, sw );
901 /* Call WH_SHELL hook */
903 if (!(wndPtr->dwStyle & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
904 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 );
906 TRACE("created window %04x\n", hwnd);
908 WIN_ReleaseWndPtr(wndPtr);
913 /***********************************************************************
914 * CreateWindow (USER.41)
916 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
917 DWORD style, INT16 x, INT16 y, INT16 width,
918 INT16 height, HWND16 parent, HMENU16 menu,
919 HINSTANCE16 instance, LPVOID data )
921 return CreateWindowEx16( 0, className, windowName, style,
922 x, y, width, height, parent, menu, instance, data );
926 /***********************************************************************
927 * CreateWindowEx (USER.452)
929 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
930 LPCSTR windowName, DWORD style, INT16 x,
931 INT16 y, INT16 width, INT16 height,
932 HWND16 parent, HMENU16 menu,
933 HINSTANCE16 instance, LPVOID data )
939 /* Find the class atom */
941 if (HIWORD(className))
943 if (!(classAtom = GlobalFindAtomA( className )))
945 ERR( "bad class name %s\n", debugres_a(className) );
951 classAtom = LOWORD(className);
952 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
954 ERR( "bad atom %x\n", classAtom);
960 /* Fix the coordinates */
962 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
963 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
964 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
965 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
967 /* Create the window */
969 cs.lpCreateParams = data;
970 cs.hInstance = (HINSTANCE)instance;
971 cs.hMenu = (HMENU)menu;
972 cs.hwndParent = WIN_Handle32( parent );
974 cs.lpszName = windowName;
975 cs.lpszClass = className;
976 cs.dwExStyle = exStyle;
978 return WIN_Handle16( WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_16 ));
982 /***********************************************************************
983 * CreateWindowExA (USER32.@)
985 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
986 LPCSTR windowName, DWORD style, INT x,
987 INT y, INT width, INT height,
988 HWND parent, HMENU menu,
989 HINSTANCE instance, LPVOID data )
996 instance=GetModuleHandleA(NULL);
998 if(exStyle & WS_EX_MDICHILD)
999 return CreateMDIWindowA(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1001 /* Find the class atom */
1003 if (HIWORD(className))
1005 if (!(classAtom = GlobalFindAtomA( className )))
1007 ERR( "bad class name %s\n", debugres_a(className) );
1013 classAtom = LOWORD(className);
1014 if (!GlobalGetAtomNameA( classAtom, buffer, sizeof(buffer) ))
1016 ERR( "bad atom %x\n", classAtom);
1022 /* Create the window */
1024 cs.lpCreateParams = data;
1025 cs.hInstance = instance;
1027 cs.hwndParent = parent;
1033 cs.lpszName = windowName;
1034 cs.lpszClass = className;
1035 cs.dwExStyle = exStyle;
1037 return WIN_CreateWindowEx( &cs, classAtom, WIN_PROC_32A );
1041 /***********************************************************************
1042 * CreateWindowExW (USER32.@)
1044 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1045 LPCWSTR windowName, DWORD style, INT x,
1046 INT y, INT width, INT height,
1047 HWND parent, HMENU menu,
1048 HINSTANCE instance, LPVOID data )
1055 instance=GetModuleHandleA(NULL);
1057 if(exStyle & WS_EX_MDICHILD)
1058 return CreateMDIWindowW(className, windowName, style, x, y, width, height, parent, instance, (LPARAM)data);
1060 /* Find the class atom */
1062 if (HIWORD(className))
1064 if (!(classAtom = GlobalFindAtomW( className )))
1066 ERR( "bad class name %s\n", debugres_w(className) );
1072 classAtom = LOWORD(className);
1073 if (!GlobalGetAtomNameW( classAtom, buffer, sizeof(buffer)/sizeof(WCHAR) ))
1075 ERR( "bad atom %x\n", classAtom);
1081 /* Create the window */
1083 cs.lpCreateParams = data;
1084 cs.hInstance = instance;
1086 cs.hwndParent = parent;
1092 cs.lpszName = windowName;
1093 cs.lpszClass = className;
1094 cs.dwExStyle = exStyle;
1096 /* Note: we rely on the fact that CREATESTRUCTA and */
1097 /* CREATESTRUCTW have the same layout. */
1098 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, classAtom, WIN_PROC_32W );
1102 /***********************************************************************
1103 * WIN_SendDestroyMsg
1105 static void WIN_SendDestroyMsg( HWND hwnd )
1107 if( CARET_GetHwnd() == hwnd) DestroyCaret();
1108 if (USER_Driver.pResetSelectionOwner)
1109 USER_Driver.pResetSelectionOwner( hwnd, TRUE );
1112 * Send the WM_DESTROY to the window.
1114 SendMessageA( hwnd, WM_DESTROY, 0, 0);
1117 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1118 * make sure that the window still exists when we come back.
1125 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1127 /* start from the end (FIXME: is this needed?) */
1128 for (i = 0; pWndArray[i]; i++) ;
1132 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1134 HeapFree( GetProcessHeap(), 0, pWndArray );
1137 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1141 /***********************************************************************
1142 * DestroyWindow (USER32.@)
1144 BOOL WINAPI DestroyWindow( HWND hwnd )
1150 hwnd = WIN_GetFullHandle( hwnd );
1151 TRACE("(%04x)\n", hwnd);
1153 /* Initialization */
1155 if (hwnd == GetDesktopWindow()) return FALSE; /* Can't destroy desktop */
1157 /* Look whether the focus is within the tree of windows we will
1161 if (h == hwnd || IsChild( hwnd, h ))
1163 HWND parent = GetAncestor( hwnd, GA_PARENT );
1164 if (parent == GetDesktopWindow()) parent = 0;
1170 if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE;
1172 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1173 if (!(wndPtr->dwStyle & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1175 HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L );
1176 /* FIXME: clean up palette - see "Internals" p.352 */
1179 if( !QUEUE_IsExitingQueue(wndPtr->hmemTaskQ) )
1180 if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) )
1182 /* Notify the parent window only */
1183 SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY,
1184 MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd );
1185 if( !IsWindow(hwnd) )
1192 if (USER_Driver.pResetSelectionOwner)
1193 USER_Driver.pResetSelectionOwner( hwnd, FALSE ); /* before the window is unmapped */
1195 /* Hide the window */
1197 ShowWindow( hwnd, SW_HIDE );
1198 if (!IsWindow(hwnd))
1204 /* Recursively destroy owned windows */
1206 if( !(wndPtr->dwStyle & WS_CHILD) )
1213 HWND *list = WIN_ListChildren( wndPtr->parent->hwndSelf );
1216 for (i = 0; list[i]; i++)
1219 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1220 if (!(siblingPtr = WIN_FindWndPtr( list[i] ))) continue;
1221 if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ)
1223 WIN_ReleaseWndPtr( siblingPtr );
1224 DestroyWindow( list[i] );
1228 else siblingPtr->owner = 0;
1229 WIN_ReleaseWndPtr( siblingPtr );
1231 HeapFree( GetProcessHeap(), 0, list );
1233 if (!got_one) break;
1236 WINPOS_ActivateOtherWindow( hwnd );
1238 if ((owner = GetWindow( hwnd, GW_OWNER )))
1240 WND *ptr = WIN_FindWndPtr( owner );
1243 if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner;
1244 WIN_ReleaseWndPtr( ptr );
1249 /* Send destroy messages */
1251 WIN_SendDestroyMsg( hwnd );
1252 if (!IsWindow(hwnd))
1258 /* Unlink now so we won't bother with the children later on */
1260 if( wndPtr->parent ) WIN_UnlinkWindow(hwnd);
1262 /* Destroy the window storage */
1264 WIN_ReleaseWndPtr(WIN_DestroyWindow( wndPtr ));
1267 WIN_ReleaseWndPtr(wndPtr);
1272 /***********************************************************************
1273 * CloseWindow (USER32.@)
1275 BOOL WINAPI CloseWindow( HWND hwnd )
1277 WND * wndPtr = WIN_FindWndPtr( hwnd );
1280 if (!wndPtr || (wndPtr->dwStyle & WS_CHILD))
1285 ShowWindow( hwnd, SW_MINIMIZE );
1288 WIN_ReleaseWndPtr(wndPtr);
1294 /***********************************************************************
1295 * OpenIcon (USER32.@)
1297 BOOL WINAPI OpenIcon( HWND hwnd )
1299 if (!IsIconic( hwnd )) return FALSE;
1300 ShowWindow( hwnd, SW_SHOWNORMAL );
1305 /***********************************************************************
1308 * Implementation of FindWindow() and FindWindowEx().
1310 static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
1315 WCHAR *buffer = NULL;
1317 if (!parent) parent = GetDesktopWindow();
1320 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1321 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1324 if (!(list = WIN_ListChildren( parent )))
1326 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1332 child = WIN_GetFullHandle( child );
1333 while (list[i] && list[i] != child) i++;
1334 if (!list[i]) return 0;
1335 i++; /* start from next window */
1338 for ( ; list[i]; i++)
1340 if (className && (GetClassWord(list[i], GCW_ATOM) != className))
1341 continue; /* Not the right class */
1343 /* Now check the title */
1345 if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
1348 HeapFree( GetProcessHeap(), 0, list );
1349 if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
1351 /* In this case we need to check whether other processes
1352 own a window with the given paramters on the Desktop,
1353 but we don't, so let's at least warn about it */
1354 if (!retvalue) FIXME("Returning 0 without checking other processes\n");
1360 /***********************************************************************
1361 * FindWindowA (USER32.@)
1363 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1365 HWND ret = FindWindowExA( 0, 0, className, title );
1366 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1371 /***********************************************************************
1372 * FindWindowExA (USER32.@)
1374 HWND WINAPI FindWindowExA( HWND parent, HWND child,
1375 LPCSTR className, LPCSTR title )
1383 /* If the atom doesn't exist, then no class */
1384 /* with this name exists either. */
1385 if (!(atom = GlobalFindAtomA( className )))
1387 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1392 buffer = HEAP_strdupAtoW( GetProcessHeap(), 0, title );
1393 hwnd = WIN_FindWindow( parent, child, atom, buffer );
1394 HeapFree( GetProcessHeap(), 0, buffer );
1399 /***********************************************************************
1400 * FindWindowExW (USER32.@)
1402 HWND WINAPI FindWindowExW( HWND parent, HWND child,
1403 LPCWSTR className, LPCWSTR title )
1409 /* If the atom doesn't exist, then no class */
1410 /* with this name exists either. */
1411 if (!(atom = GlobalFindAtomW( className )))
1413 SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1417 return WIN_FindWindow( parent, child, atom, title );
1421 /***********************************************************************
1422 * FindWindowW (USER32.@)
1424 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1426 return FindWindowExW( 0, 0, className, title );
1430 /**********************************************************************
1431 * GetDesktopWindow (USER32.@)
1433 HWND WINAPI GetDesktopWindow(void)
1435 if (pWndDesktop) return pWndDesktop->hwndSelf;
1436 ERR( "You need the -desktop option when running with native USER\n" );
1442 /*******************************************************************
1443 * EnableWindow (USER32.@)
1445 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1450 TRACE("( %x, %d )\n", hwnd, enable);
1452 if (USER_Driver.pEnableWindow)
1453 return USER_Driver.pEnableWindow( hwnd, enable );
1455 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
1456 hwnd = wndPtr->hwndSelf; /* make it a full handle */
1458 retvalue = ((wndPtr->dwStyle & WS_DISABLED) != 0);
1460 if (enable && (wndPtr->dwStyle & WS_DISABLED))
1462 wndPtr->dwStyle &= ~WS_DISABLED; /* Enable window */
1463 SendMessageA( hwnd, WM_ENABLE, TRUE, 0 );
1465 else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
1467 SendMessageA( hwnd, WM_CANCELMODE, 0, 0);
1469 wndPtr->dwStyle |= WS_DISABLED; /* Disable window */
1471 if (hwnd == GetFocus())
1472 SetFocus( 0 ); /* A disabled window can't have the focus */
1474 if (hwnd == GetCapture())
1475 ReleaseCapture(); /* A disabled window can't capture the mouse */
1477 SendMessageA( hwnd, WM_ENABLE, FALSE, 0 );
1479 WIN_ReleaseWndPtr(wndPtr);
1484 /***********************************************************************
1485 * IsWindowEnabled (USER32.@)
1487 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1492 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1493 retvalue = !(wndPtr->dwStyle & WS_DISABLED);
1494 WIN_ReleaseWndPtr(wndPtr);
1500 /***********************************************************************
1501 * IsWindowUnicode (USER32.@)
1503 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1508 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
1509 retvalue = (WINPROC_GetProcType( wndPtr->winproc ) == WIN_PROC_32W);
1510 WIN_ReleaseWndPtr(wndPtr);
1515 /**********************************************************************
1516 * GetWindowWord (USER32.@)
1518 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
1521 WND * wndPtr = WIN_FindWndPtr( hwnd );
1522 if (!wndPtr) return 0;
1525 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1527 WARN("Invalid offset %d\n", offset );
1530 else retvalue = *(WORD *)(((char *)wndPtr->wExtra) + offset);
1531 WIN_ReleaseWndPtr(wndPtr);
1535 WIN_ReleaseWndPtr(wndPtr);
1538 case GWL_HWNDPARENT:
1539 return GetWindowLongW( hwnd, offset );
1543 LONG ret = GetWindowLongW( hwnd, offset );
1545 WARN("%d: discards high bits of 0x%08lx!\n", offset, ret );
1549 WARN("Invalid offset %d\n", offset );
1555 /**********************************************************************
1556 * SetWindowWord (USER32.@)
1558 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
1561 WND * wndPtr = WIN_FindWndPtr( hwnd );
1562 if (!wndPtr) return 0;
1565 if (offset + sizeof(WORD) > wndPtr->cbWndExtra)
1567 WARN("Invalid offset %d\n", offset );
1568 WIN_ReleaseWndPtr(wndPtr);
1571 ptr = (WORD *)(((char *)wndPtr->wExtra) + offset);
1574 WIN_ReleaseWndPtr(wndPtr);
1578 WIN_ReleaseWndPtr(wndPtr);
1583 case GWL_HWNDPARENT:
1584 return SetWindowLongW( hwnd, offset, (UINT)newval );
1586 WARN("Invalid offset %d\n", offset );
1592 /**********************************************************************
1595 * Helper function for GetWindowLong().
1597 static LONG WIN_GetWindowLong( HWND hwnd, INT offset, WINDOWPROCTYPE type )
1600 WND * wndPtr = WIN_FindWndPtr( hwnd );
1601 if (!wndPtr) return 0;
1604 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1606 WARN("Invalid offset %d\n", offset );
1610 retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset);
1611 /* Special case for dialog window procedure */
1612 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1614 retvalue = (LONG)WINPROC_GetProc( (HWINDOWPROC)retvalue, type );
1621 case GWL_USERDATA: retvalue = wndPtr->userdata;
1623 case GWL_STYLE: retvalue = wndPtr->dwStyle;
1625 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle;
1627 case GWL_ID: retvalue = (LONG)wndPtr->wIDmenu;
1629 case GWL_WNDPROC: retvalue = (LONG)WINPROC_GetProc( wndPtr->winproc,
1632 case GWL_HWNDPARENT: retvalue = (LONG)GetParent(hwnd);
1634 case GWL_HINSTANCE: retvalue = wndPtr->hInstance;
1637 WARN("Unknown offset %d\n", offset );
1641 WIN_ReleaseWndPtr(wndPtr);
1646 /**********************************************************************
1649 * Helper function for SetWindowLong().
1651 * 0 is the failure code. However, in the case of failure SetLastError
1652 * must be set to distinguish between a 0 return value and a failure.
1654 * FIXME: The error values for SetLastError may not be right. Can
1655 * someone check with the real thing?
1657 static LONG WIN_SetWindowLong( HWND hwnd, INT offset, LONG newval,
1658 WINDOWPROCTYPE type )
1661 WND * wndPtr = WIN_FindWndPtr( hwnd );
1664 TRACE("%x=%p %x %lx %x\n",hwnd, wndPtr, offset, newval, type);
1668 /* Is this the right error? */
1669 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1675 if (offset + sizeof(LONG) > wndPtr->cbWndExtra)
1677 WARN("Invalid offset %d\n", offset );
1679 /* Is this the right error? */
1680 SetLastError( ERROR_OUTOFMEMORY );
1685 ptr = (LONG *)(((char *)wndPtr->wExtra) + offset);
1686 /* Special case for dialog window procedure */
1687 if ((offset == DWL_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG))
1689 retval = (LONG)WINPROC_GetProc( (HWINDOWPROC)*ptr, type );
1690 WINPROC_SetProc( (HWINDOWPROC *)ptr, (WNDPROC16)newval,
1691 type, WIN_PROC_WINDOW );
1698 ptr = (DWORD*)&wndPtr->wIDmenu;
1701 ptr = (DWORD*)&wndPtr->hInstance;
1704 ptr = &wndPtr->userdata;
1706 case GWL_HWNDPARENT:
1707 retval = SetParent( hwnd, (HWND)newval );
1710 retval = (LONG)WINPROC_GetProc( wndPtr->winproc, type );
1711 WINPROC_SetProc( &wndPtr->winproc, (WNDPROC16)newval,
1712 type, WIN_PROC_WINDOW );
1715 style.styleOld = wndPtr->dwStyle;
1716 style.styleNew = newval;
1717 SendMessageA(hwnd,WM_STYLECHANGING,GWL_STYLE,(LPARAM)&style);
1718 wndPtr->dwStyle = style.styleNew;
1719 SendMessageA(hwnd,WM_STYLECHANGED,GWL_STYLE,(LPARAM)&style);
1720 retval = style.styleOld;
1723 style.styleOld = wndPtr->dwExStyle;
1724 style.styleNew = newval;
1725 SendMessageA(hwnd,WM_STYLECHANGING,GWL_EXSTYLE,(LPARAM)&style);
1726 wndPtr->dwExStyle = style.styleNew;
1727 SendMessageA(hwnd,WM_STYLECHANGED,GWL_EXSTYLE,(LPARAM)&style);
1728 retval = style.styleOld;
1732 WARN("Invalid offset %d\n", offset );
1734 /* Don't think this is right error but it should do */
1735 SetLastError( ERROR_OUTOFMEMORY );
1743 WIN_ReleaseWndPtr(wndPtr);
1748 /**********************************************************************
1749 * GetWindowLong (USER.135)
1751 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
1753 return WIN_GetWindowLong( WIN_Handle32(hwnd), offset, WIN_PROC_16 );
1757 /**********************************************************************
1758 * GetWindowLongA (USER32.@)
1760 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
1762 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32A );
1766 /**********************************************************************
1767 * GetWindowLongW (USER32.@)
1769 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
1771 return WIN_GetWindowLong( hwnd, offset, WIN_PROC_32W );
1775 /**********************************************************************
1776 * SetWindowLong (USER.136)
1778 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
1780 return WIN_SetWindowLong( WIN_Handle32(hwnd), offset, newval, WIN_PROC_16 );
1784 /**********************************************************************
1785 * SetWindowLongA (USER32.@)
1787 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
1789 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32A );
1793 /**********************************************************************
1794 * SetWindowLongW (USER32.@) Set window attribute
1796 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
1797 * value in a window's extra memory.
1799 * The _hwnd_ parameter specifies the window. is the handle to a
1800 * window that has extra memory. The _newval_ parameter contains the
1801 * new attribute or extra memory value. If positive, the _offset_
1802 * parameter is the byte-addressed location in the window's extra
1803 * memory to set. If negative, _offset_ specifies the window
1804 * attribute to set, and should be one of the following values:
1806 * GWL_EXSTYLE The window's extended window style
1808 * GWL_STYLE The window's window style.
1810 * GWL_WNDPROC Pointer to the window's window procedure.
1812 * GWL_HINSTANCE The window's pplication instance handle.
1814 * GWL_ID The window's identifier.
1816 * GWL_USERDATA The window's user-specified data.
1818 * If the window is a dialog box, the _offset_ parameter can be one of
1819 * the following values:
1821 * DWL_DLGPROC The address of the window's dialog box procedure.
1823 * DWL_MSGRESULT The return value of a message
1824 * that the dialog box procedure processed.
1826 * DWL_USER Application specific information.
1830 * If successful, returns the previous value located at _offset_. Otherwise,
1835 * Extra memory for a window class is specified by a nonzero cbWndExtra
1836 * parameter of the WNDCLASS structure passed to RegisterClass() at the
1837 * time of class creation.
1839 * Using GWL_WNDPROC to set a new window procedure effectively creates
1840 * a window subclass. Use CallWindowProc() in the new windows procedure
1841 * to pass messages to the superclass's window procedure.
1843 * The user data is reserved for use by the application which created
1846 * Do not use GWL_STYLE to change the window's WS_DISABLE style;
1847 * instead, call the EnableWindow() function to change the window's
1850 * Do not use GWL_HWNDPARENT to reset the window's parent, use
1851 * SetParent() instead.
1854 * When offset is GWL_STYLE and the calling app's ver is 4.0,
1855 * it sends WM_STYLECHANGING before changing the settings
1856 * and WM_STYLECHANGED afterwards.
1857 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
1861 * GWL_STYLE does not dispatch WM_STYLE... messages.
1868 LONG WINAPI SetWindowLongW(
1869 HWND hwnd, /* [in] window to alter */
1870 INT offset, /* [in] offset, in bytes, of location to alter */
1871 LONG newval /* [in] new value of location */
1873 return WIN_SetWindowLong( hwnd, offset, newval, WIN_PROC_32W );
1877 /*******************************************************************
1878 * GetWindowTextA (USER32.@)
1880 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
1882 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount,
1886 /*******************************************************************
1887 * InternalGetWindowText (USER32.@)
1889 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
1891 WND *win = WIN_FindWndPtr( hwnd );
1893 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
1894 else lpString[0] = 0;
1895 WIN_ReleaseWndPtr( win );
1896 return strlenW(lpString);
1900 /*******************************************************************
1901 * GetWindowTextW (USER32.@)
1903 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
1905 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount,
1910 /*******************************************************************
1911 * SetWindowText (USER32.@)
1912 * SetWindowTextA (USER32.@)
1914 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
1916 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1920 /*******************************************************************
1921 * SetWindowTextW (USER32.@)
1923 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
1925 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
1929 /*******************************************************************
1930 * GetWindowTextLengthA (USER32.@)
1932 INT WINAPI GetWindowTextLengthA( HWND hwnd )
1934 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1937 /*******************************************************************
1938 * GetWindowTextLengthW (USER32.@)
1940 INT WINAPI GetWindowTextLengthW( HWND hwnd )
1942 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
1946 /*******************************************************************
1947 * IsWindow (USER32.@)
1949 BOOL WINAPI IsWindow( HWND hwnd )
1955 if ((ptr = user_handles[LOWORD(hwnd)]))
1957 ret = ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf));
1963 /* check other processes */
1964 SERVER_START_REQ( get_window_info )
1967 ret = !SERVER_CALL_ERR();
1974 /***********************************************************************
1975 * GetWindowThreadProcessId (USER32.@)
1977 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
1983 if ((ptr = user_handles[LOWORD(hwnd)]))
1985 if ((ptr->dwMagic == WND_MAGIC) && (!HIWORD(hwnd) || hwnd == ptr->hwndSelf))
1987 /* got a valid window */
1989 if (process) *process = GetCurrentProcessId();
1991 else SetLastError( ERROR_INVALID_WINDOW_HANDLE);
1997 /* check other processes */
1998 SERVER_START_REQ( get_window_info )
2001 if (!SERVER_CALL_ERR())
2003 tid = (DWORD)req->tid;
2004 if (process) *process = (DWORD)req->pid;
2012 /*****************************************************************
2013 * GetParent (USER32.@)
2015 HWND WINAPI GetParent( HWND hwnd )
2020 if ((wndPtr = WIN_FindWndPtr(hwnd)))
2022 if (wndPtr->dwStyle & WS_CHILD)
2023 retvalue = wndPtr->parent->hwndSelf;
2024 else if (wndPtr->dwStyle & WS_POPUP)
2025 retvalue = wndPtr->owner;
2026 WIN_ReleaseWndPtr(wndPtr);
2032 /*****************************************************************
2033 * GetAncestor (USER32.@)
2035 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2040 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2041 if (wndPtr->hwndSelf == GetDesktopWindow()) goto done;
2046 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2049 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2050 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2053 while (wndPtr->parent->hwndSelf != GetDesktopWindow())
2054 WIN_UpdateWndPtr( &wndPtr, wndPtr->parent );
2055 while (wndPtr && wndPtr->owner)
2057 WND *ptr = WIN_FindWndPtr( wndPtr->owner );
2058 WIN_ReleaseWndPtr( wndPtr );
2063 ret = wndPtr ? wndPtr->hwndSelf : 0;
2065 WIN_ReleaseWndPtr( wndPtr );
2070 /*****************************************************************
2071 * SetParent (USER32.@)
2073 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2079 if (!parent) parent = GetDesktopWindow();
2080 else parent = WIN_GetFullHandle( parent );
2083 if (WIN_GetFullHandle(hwnd) == GetDesktopWindow() || !IsWindow( parent ))
2085 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2089 if (USER_Driver.pSetParent)
2090 return USER_Driver.pSetParent( hwnd, parent );
2092 if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
2094 dwStyle = wndPtr->dwStyle;
2096 /* Windows hides the window first, then shows it again
2097 * including the WM_SHOWWINDOW messages and all */
2098 if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE );
2100 retvalue = wndPtr->parent->hwndSelf; /* old parent */
2101 if (parent != retvalue)
2103 WIN_LinkWindow( hwnd, parent, HWND_TOP );
2105 if (parent != GetDesktopWindow()) /* a child window */
2107 if (!(dwStyle & WS_CHILD))
2109 HMENU menu = (HMENU)SetWindowLongW( hwnd, GWL_ID, 0 );
2110 if (menu) DestroyMenu( menu );
2114 WIN_ReleaseWndPtr( wndPtr );
2116 /* SetParent additionally needs to make hwnd the topmost window
2117 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2118 WM_WINDOWPOSCHANGED notification messages.
2120 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2121 SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|
2122 ((dwStyle & WS_VISIBLE)?SWP_SHOWWINDOW:0));
2123 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2124 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2129 /*******************************************************************
2130 * IsChild (USER32.@)
2132 BOOL WINAPI IsChild( HWND parent, HWND child )
2134 HWND *list = WIN_ListParents( child );
2138 if (!list) return FALSE;
2139 parent = WIN_GetFullHandle( parent );
2140 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2141 ret = (list[i] != 0);
2142 HeapFree( GetProcessHeap(), 0, list );
2147 /***********************************************************************
2148 * IsWindowVisible (USER32.@)
2150 BOOL WINAPI IsWindowVisible( HWND hwnd )
2156 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2157 if (!(list = WIN_ListParents( hwnd ))) return TRUE;
2158 for (i = 0; list[i]; i++)
2159 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2161 HeapFree( GetProcessHeap(), 0, list );
2166 /***********************************************************************
2167 * WIN_IsWindowDrawable
2169 * hwnd is drawable when it is visible, all parents are not
2170 * minimized, and it is itself not minimized unless we are
2171 * trying to draw its default class icon.
2173 BOOL WIN_IsWindowDrawable( WND* wnd, BOOL icon )
2179 if (!(wnd->dwStyle & WS_VISIBLE)) return FALSE;
2180 if ((wnd->dwStyle & WS_MINIMIZE) &&
2181 icon && GetClassLongA( wnd->hwndSelf, GCL_HICON )) return FALSE;
2183 if (!(list = WIN_ListParents( wnd->hwndSelf ))) return TRUE;
2184 for (i = 0; list[i]; i++)
2185 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2188 HeapFree( GetProcessHeap(), 0, list );
2193 /*******************************************************************
2194 * GetTopWindow (USER32.@)
2196 HWND WINAPI GetTopWindow( HWND hwnd )
2198 if (!hwnd) hwnd = GetDesktopWindow();
2199 return GetWindow( hwnd, GW_CHILD );
2203 /*******************************************************************
2204 * GetWindow (USER32.@)
2206 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2210 if (rel == GW_OWNER) /* special case: not fully supported in the server yet */
2212 WND *wndPtr = WIN_FindWndPtr( hwnd );
2213 if (!wndPtr) return 0;
2214 retval = wndPtr->owner;
2215 WIN_ReleaseWndPtr( wndPtr );
2219 SERVER_START_REQ( get_window_tree )
2222 if (!SERVER_CALL_ERR())
2227 retval = req->first_sibling;
2230 retval = req->last_sibling;
2233 retval = req->next_sibling;
2236 retval = req->prev_sibling;
2239 retval = req->first_child;
2249 /***********************************************************************
2250 * WIN_InternalShowOwnedPopups
2252 * Internal version of ShowOwnedPopups; Wine functions should use this
2253 * to avoid interfering with application calls to ShowOwnedPopups
2254 * and to make sure the application can't prevent showing/hiding.
2256 * Set unmanagedOnly to TRUE to show/hide unmanaged windows only.
2260 BOOL WIN_InternalShowOwnedPopups( HWND owner, BOOL fShow, BOOL unmanagedOnly )
2264 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2266 if (!win_array) return TRUE;
2269 * Show windows Lowest first, Highest last to preserve Z-Order
2271 while (win_array[count]) count++;
2272 while (--count >= 0)
2274 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2275 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2277 if (pWnd->dwStyle & WS_POPUP)
2281 /* check in window was flagged for showing in previous WIN_InternalShowOwnedPopups call */
2282 if (pWnd->flags & WIN_NEEDS_INTERNALSOP)
2285 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2287 ShowWindow(pWnd->hwndSelf,SW_SHOW);
2288 pWnd->flags &= ~WIN_NEEDS_INTERNALSOP; /* remove the flag */
2293 if ( IsWindowVisible(pWnd->hwndSelf) && /* hide only if window is visible */
2294 !( pWnd->flags & WIN_NEEDS_INTERNALSOP ) && /* don't hide if previous call already did it */
2295 !( unmanagedOnly && (pWnd->dwExStyle & WS_EX_MANAGED) ) ) /* don't hide managed windows if unmanagedOnly is TRUE */
2298 * Call ShowWindow directly because an application can intercept WM_SHOWWINDOW messages
2300 ShowWindow(pWnd->hwndSelf,SW_HIDE);
2301 /* flag the window for showing on next WIN_InternalShowOwnedPopups call */
2302 pWnd->flags |= WIN_NEEDS_INTERNALSOP;
2306 WIN_ReleaseWndPtr( pWnd );
2308 HeapFree( GetProcessHeap(), 0, win_array );
2313 /*******************************************************************
2314 * ShowOwnedPopups (USER32.@)
2316 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2320 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2322 if (!win_array) return TRUE;
2324 while (win_array[count]) count++;
2325 while (--count >= 0)
2327 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2328 if (!(pWnd = WIN_FindWndPtr( win_array[count] ))) continue;
2330 if (pWnd->dwStyle & WS_POPUP)
2334 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2336 /* In Windows, ShowOwnedPopups(TRUE) generates
2337 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2338 * regardless of the state of the owner
2340 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_SHOW, SW_PARENTOPENING);
2341 pWnd->flags &= ~WIN_NEEDS_SHOW_OWNEDPOPUP;
2346 if (IsWindowVisible(pWnd->hwndSelf))
2348 /* In Windows, ShowOwnedPopups(FALSE) generates
2349 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2350 * regardless of the state of the owner
2352 SendMessageA(pWnd->hwndSelf, WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2353 pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
2357 WIN_ReleaseWndPtr( pWnd );
2359 HeapFree( GetProcessHeap(), 0, win_array );
2364 /*******************************************************************
2365 * GetLastActivePopup (USER32.@)
2367 HWND WINAPI GetLastActivePopup( HWND hwnd )
2370 WND *wndPtr =WIN_FindWndPtr(hwnd);
2371 if (!wndPtr) return hwnd;
2372 retval = wndPtr->hwndLastActive;
2373 if (!IsWindow( retval )) retval = wndPtr->hwndSelf;
2374 WIN_ReleaseWndPtr(wndPtr);
2379 /*******************************************************************
2382 * Build an array of all parents of a given window, starting with
2383 * the immediate parent. The array must be freed with HeapFree.
2384 * Returns NULL if window is a top-level window.
2386 HWND *WIN_ListParents( HWND hwnd )
2390 SERVER_START_VAR_REQ( get_window_parents, REQUEST_MAX_VAR_SIZE )
2395 user_handle_t *data = server_data_ptr(req);
2396 int i, count = server_data_size(req) / sizeof(*data);
2397 if (count && ((list = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(HWND) ))))
2399 for (i = 0; i < count; i++) list[i] = data[i];
2409 /*******************************************************************
2412 * Build an array of the children of a given window. The array must be
2413 * freed with HeapFree. Returns NULL when no windows are found.
2415 HWND *WIN_ListChildren( HWND hwnd )
2419 SERVER_START_VAR_REQ( get_window_children, REQUEST_MAX_VAR_SIZE )
2424 user_handle_t *data = server_data_ptr(req);
2425 int i, count = server_data_size(req) / sizeof(*data);
2426 if (count && ((list = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(HWND) ))))
2428 for (i = 0; i < count; i++) list[i] = data[i];
2438 /*******************************************************************
2439 * EnumWindows (USER32.@)
2441 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2447 /* We have to build a list of all windows first, to avoid */
2448 /* unpleasant side-effects, for instance if the callback */
2449 /* function changes the Z-order of the windows. */
2451 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2453 /* Now call the callback function for every window */
2455 iWndsLocks = WIN_SuspendWndsLock();
2456 for (i = 0; list[i]; i++)
2458 /* Make sure that the window still exists */
2459 if (!IsWindow( list[i] )) continue;
2460 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2462 WIN_RestoreWndsLock(iWndsLocks);
2463 HeapFree( GetProcessHeap(), 0, list );
2468 /**********************************************************************
2469 * EnumTaskWindows16 (USER.225)
2471 BOOL16 WINAPI EnumTaskWindows16( HTASK16 hTask, WNDENUMPROC16 func,
2474 TDB *tdb = TASK_GetPtr( hTask );
2475 if (!tdb) return FALSE;
2476 return EnumThreadWindows( (DWORD)tdb->teb->tid, (WNDENUMPROC)func, lParam );
2480 /**********************************************************************
2481 * EnumThreadWindows (USER32.@)
2483 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2488 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
2490 /* Now call the callback function for every window */
2492 iWndsLocks = WIN_SuspendWndsLock();
2493 for (i = 0; list[i]; i++)
2495 if (GetWindowThreadProcessId( list[i], NULL ) != id) continue;
2496 if (!func( list[i], lParam )) break;
2498 WIN_RestoreWndsLock(iWndsLocks);
2499 HeapFree( GetProcessHeap(), 0, list );
2504 /**********************************************************************
2505 * WIN_EnumChildWindows
2507 * Helper function for EnumChildWindows().
2509 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2514 for ( ; *list; list++)
2516 /* Make sure that the window still exists */
2517 if (!IsWindow( *list )) continue;
2518 /* skip owned windows */
2519 if (GetWindow( *list, GW_OWNER )) continue;
2520 /* Build children list first */
2521 childList = WIN_ListChildren( *list );
2523 ret = func( *list, lParam );
2527 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2528 HeapFree( GetProcessHeap(), 0, childList );
2530 if (!ret) return FALSE;
2536 /**********************************************************************
2537 * EnumChildWindows (USER32.@)
2539 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2544 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2545 iWndsLocks = WIN_SuspendWndsLock();
2546 WIN_EnumChildWindows( list, func, lParam );
2547 WIN_RestoreWndsLock(iWndsLocks);
2548 HeapFree( GetProcessHeap(), 0, list );
2553 /*******************************************************************
2554 * AnyPopup (USER.52)
2556 BOOL16 WINAPI AnyPopup16(void)
2562 /*******************************************************************
2563 * AnyPopup (USER32.@)
2565 BOOL WINAPI AnyPopup(void)
2569 HWND *list = WIN_ListChildren( GetDesktopWindow() );
2571 if (!list) return FALSE;
2572 for (i = 0; list[i]; i++)
2574 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
2576 retvalue = (list[i] != 0);
2577 HeapFree( GetProcessHeap(), 0, list );
2582 /*******************************************************************
2583 * FlashWindow (USER32.@)
2585 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
2587 WND *wndPtr = WIN_FindWndPtr(hWnd);
2589 TRACE("%04x\n", hWnd);
2591 if (!wndPtr) return FALSE;
2592 hWnd = wndPtr->hwndSelf; /* make it a full handle */
2594 if (wndPtr->dwStyle & WS_MINIMIZE)
2596 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
2598 HDC hDC = GetDC(hWnd);
2600 if (!SendMessageW( hWnd, WM_ERASEBKGND, (WPARAM16)hDC, 0 ))
2601 wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
2603 ReleaseDC( hWnd, hDC );
2604 wndPtr->flags |= WIN_NCACTIVATED;
2608 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
2609 wndPtr->flags &= ~WIN_NCACTIVATED;
2611 WIN_ReleaseWndPtr(wndPtr);
2617 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
2618 else wparam = (hWnd == GetActiveWindow());
2620 WIN_ReleaseWndPtr(wndPtr);
2621 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
2627 /*******************************************************************
2628 * GetWindowContextHelpId (USER32.@)
2630 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
2633 WND *wnd = WIN_FindWndPtr( hwnd );
2635 retval = wnd->helpContext;
2636 WIN_ReleaseWndPtr(wnd);
2641 /*******************************************************************
2642 * SetWindowContextHelpId (USER32.@)
2644 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
2646 WND *wnd = WIN_FindWndPtr( hwnd );
2647 if (!wnd) return FALSE;
2648 wnd->helpContext = id;
2649 WIN_ReleaseWndPtr(wnd);
2654 /*******************************************************************
2657 * recursively find a child that contains spDragInfo->pt point
2658 * and send WM_QUERYDROPOBJECT
2660 BOOL16 DRAG_QueryUpdate( HWND hQueryWnd, SEGPTR spDragInfo, BOOL bNoSend )
2662 BOOL16 wParam, bResult = 0;
2664 LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
2667 if (!ptrDragInfo) return FALSE;
2669 CONV_POINT16TO32( &ptrDragInfo->pt, &pt );
2671 GetWindowRect(hQueryWnd,&tempRect);
2673 if( !PtInRect(&tempRect,pt) || !IsWindowEnabled(hQueryWnd)) return FALSE;
2675 if (!IsIconic( hQueryWnd ))
2677 GetClientRect( hQueryWnd, &tempRect );
2678 MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
2680 if (PtInRect( &tempRect, pt))
2683 HWND *list = WIN_ListChildren( hQueryWnd );
2689 for (i = 0; list[i]; i++)
2691 if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
2693 GetWindowRect( list[i], &tempRect );
2694 if (PtInRect( &tempRect, pt )) break;
2699 if (IsWindowEnabled( list[i] ))
2700 bResult = DRAG_QueryUpdate( list[i], spDragInfo, bNoSend );
2702 HeapFree( GetProcessHeap(), 0, list );
2704 if(bResult) return bResult;
2710 ScreenToClient16(hQueryWnd,&ptrDragInfo->pt);
2712 ptrDragInfo->hScope = hQueryWnd;
2714 if (bNoSend) bResult = (GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) != 0;
2715 else bResult = SendMessage16( hQueryWnd, WM_QUERYDROPOBJECT, (WPARAM16)wParam, spDragInfo );
2717 if( !bResult ) CONV_POINT32TO16( &pt, &ptrDragInfo->pt );
2723 /*******************************************************************
2724 * DragDetect (USER32.@)
2726 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
2731 rect.left = pt.x - wDragWidth;
2732 rect.right = pt.x + wDragWidth;
2734 rect.top = pt.y - wDragHeight;
2735 rect.bottom = pt.y + wDragHeight;
2741 while(PeekMessageA(&msg ,0 ,WM_MOUSEFIRST ,WM_MOUSELAST ,PM_REMOVE))
2743 if( msg.message == WM_LBUTTONUP )
2748 if( msg.message == WM_MOUSEMOVE )
2751 tmp.x = LOWORD(msg.lParam);
2752 tmp.y = HIWORD(msg.lParam);
2753 if( !PtInRect( &rect, tmp ))
2765 /******************************************************************************
2766 * DragObject (USER.464)
2768 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2769 HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2772 LPDRAGINFO16 lpDragInfo;
2774 HCURSOR16 hDragCursor=0, hOldCursor=0, hBummer=0;
2775 HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
2776 HCURSOR16 hCurrentCursor = 0;
2777 HWND16 hCurrentWnd = 0;
2779 lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
2780 spDragInfo = K32WOWGlobalLock16(hDragInfo);
2782 if( !lpDragInfo || !spDragInfo ) return 0L;
2784 if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
2786 GlobalFree16(hDragInfo);
2792 if( !(hDragCursor = CURSORICON_IconToCursor(hCursor, FALSE)) )
2794 GlobalFree16(hDragInfo);
2798 if( hDragCursor == hCursor ) hDragCursor = 0;
2799 else hCursor = hDragCursor;
2801 hOldCursor = SetCursor(hDragCursor);
2804 lpDragInfo->hWnd = hWnd;
2805 lpDragInfo->hScope = 0;
2806 lpDragInfo->wFlags = wObj;
2807 lpDragInfo->hList = szList; /* near pointer! */
2808 lpDragInfo->hOfStruct = hOfStruct;
2816 GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
2818 *(lpDragInfo+1) = *lpDragInfo;
2820 lpDragInfo->pt.x = msg.pt.x;
2821 lpDragInfo->pt.y = msg.pt.y;
2823 /* update DRAGINFO struct */
2824 TRACE_(msg)("lpDI->hScope = %04x\n",lpDragInfo->hScope);
2826 if( DRAG_QueryUpdate(hwndScope, spDragInfo, FALSE) > 0 )
2827 hCurrentCursor = hCursor;
2830 hCurrentCursor = hBummer;
2831 lpDragInfo->hScope = 0;
2833 if( hCurrentCursor )
2834 SetCursor(hCurrentCursor);
2836 /* send WM_DRAGLOOP */
2837 SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
2838 (LPARAM) spDragInfo );
2839 /* send WM_DRAGSELECT or WM_DRAGMOVE */
2840 if( hCurrentWnd != lpDragInfo->hScope )
2843 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2844 (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
2845 HIWORD(spDragInfo)) );
2846 hCurrentWnd = lpDragInfo->hScope;
2848 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
2852 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
2854 } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2857 ShowCursor( FALSE );
2861 SetCursor( hOldCursor );
2862 if (hDragCursor) DestroyCursor( hDragCursor );
2865 if( hCurrentCursor != hBummer )
2866 msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2867 (WPARAM16)hWnd, (LPARAM)spDragInfo );
2870 GlobalFree16(hDragInfo);
2872 return (DWORD)(msg.lParam);
2876 /******************************************************************************
2877 * GetWindowModuleFileNameA (USER32.@)
2879 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
2881 FIXME("GetWindowModuleFileNameA(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
2882 hwnd, lpszFileName, cchFileNameMax);
2886 /******************************************************************************
2887 * GetWindowModuleFileNameW (USER32.@)
2889 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPSTR lpszFileName, UINT cchFileNameMax)
2891 FIXME("GetWindowModuleFileNameW(hwnd 0x%x, lpszFileName %p, cchFileNameMax %u) stub!\n",
2892 hwnd, lpszFileName, cchFileNameMax);