* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Win32k subsystem
* PURPOSE: Windows
- * FILE: subsystems/win32/win32k/ntuser/window.c
+ * FILE: win32ss/user/ntuser/window.c
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
*/
{
HWND hWnd;
UINT State, State2;
+ ULONG Error;
if (!pWnd) return NULL;
+ Error = EngGetLastError();
+
_SEH2_TRY
{
hWnd = UserHMGetHandle(pWnd);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
+ EngSetLastError(Error);
_SEH2_YIELD(return NULL);
}
_SEH2_END
if ( UserObjectInDestroy(hWnd) ||
State & WNDS_DESTROYED ||
State2 & WNDS2_INDESTROY )
- return NULL;
+ pWnd = NULL;
+ EngSetLastError(Error);
return pWnd;
}
pwnd->style = styleNew;
if ((styleOld ^ styleNew) & WS_VISIBLE) // State Change.
{
- if (styleOld & WS_VISIBLE) pwnd->head.pti->cVisWindows--;
+ if (styleOld & WS_VISIBLE) pwnd->head.pti->cVisWindows--;
if (styleNew & WS_VISIBLE) pwnd->head.pti->cVisWindows++;
DceResetActiveDCEs( pwnd );
}
HWND* FASTCALL
IntWinListChildren(PWND Window)
{
- PWND Child;
- HWND *List;
- UINT Index, NumChildren = 0;
+ PWND Child;
+ HWND *List;
+ UINT Index, NumChildren = 0;
- if (!Window) return NULL;
+ if (!Window) return NULL;
- for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
- ++NumChildren;
+ for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
+ {
+ ++NumChildren;
+ }
- List = ExAllocatePoolWithTag(PagedPool, (NumChildren + 1) * sizeof(HWND), USERTAG_WINDOWLIST);
- if(!List)
- {
- ERR("Failed to allocate memory for children array\n");
- EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return NULL;
- }
- for (Child = Window->spwndChild, Index = 0;
- Child != NULL;
- Child = Child->spwndNext, ++Index)
- List[Index] = Child->head.h;
- List[Index] = NULL;
+ List = ExAllocatePoolWithTag(PagedPool, (NumChildren + 1) * sizeof(HWND), USERTAG_WINDOWLIST);
+ if(!List)
+ {
+ ERR("Failed to allocate memory for children array\n");
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
+ }
+
+ Index = 0;
+ for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
+ {
+ List[Index++] = Child->head.h;
+ }
+ List[Index] = NULL;
+
+ return List;
+}
+
+HWND* FASTCALL
+IntWinListOwnedPopups(PWND Window)
+{
+ PWND Child, Desktop;
+ HWND *List;
+ UINT Index, NumOwned = 0;
+
+ Desktop = co_GetDesktopWindow(Window);
+ if (!Desktop)
+ return NULL;
+
+ for (Child = Desktop->spwndChild; Child; Child = Child->spwndNext)
+ {
+ if (Child->spwndOwner == Window)
+ ++NumOwned;
+ }
+
+ List = ExAllocatePoolWithTag(PagedPool, (NumOwned + 1) * sizeof(HWND), USERTAG_WINDOWLIST);
+ if (!List)
+ {
+ ERR("Failed to allocate memory for children array\n");
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
+ }
+
+ Index = 0;
+ for (Child = Desktop->spwndChild; Child; Child = Child->spwndNext)
+ {
+ if (Child->spwndOwner == Window)
+ List[Index++] = Child->head.h;
+ }
+ List[Index] = NULL;
- return List;
+ return List;
}
PWND FASTCALL
if (Wnd->spwndPrev != NULL)
FoundWnd = Wnd->spwndPrev;
break;
-
+
case GW_CHILD:
if (Wnd->spwndChild != NULL)
FoundWnd = Wnd->spwndChild;
return Ret;
}
+DWORD FASTCALL IntGetWindowContextHelpId( PWND pWnd )
+{
+ DWORD HelpId;
+
+ do
+ {
+ HelpId = (DWORD)(DWORD_PTR)UserGetProp(pWnd, gpsi->atomContextHelpIdProp, TRUE);
+ if (!HelpId) break;
+ pWnd = IntGetParent(pWnd);
+ }
+ while (pWnd && pWnd->fnid != FNID_DESKTOP);
+ return HelpId;
+}
+
+
+VOID
+FASTCALL
+IntRemoveTrackMouseEvent(
+ PDESKTOP pDesk);
+
/***********************************************************************
* IntSendDestroyMsg
*/
static void IntSendDestroyMsg(HWND hWnd)
{
-
+ PTHREADINFO ti;
PWND Window;
-#if 0 /* FIXME */
- GUITHREADINFO info;
+ ti = PsGetCurrentThreadWin32Thread();
+ Window = UserGetWindowObject(hWnd);
- if (GetGUIThreadInfo(GetCurrentThreadId(), &info))
+ if (Window)
{
- if (hWnd == info.hwndCaret)
+ /*
+ * Look whether the focus is within the tree of windows
+ * we will be destroying.
+ */
+ // Rule #1
+ if ( ti->MessageQueue->spwndActive == Window || // Fixes CORE-106 RegSvr32 exit and return focus to CMD.
+ (ti->MessageQueue->spwndActive == NULL && ti->MessageQueue == IntGetFocusMessageQueue()) )
{
- DestroyCaret();
+ co_WinPosActivateOtherWindow(Window);
}
- }
-#endif
- Window = UserGetWindowObject(hWnd);
- if (Window)
- {
-// USER_REFERENCE_ENTRY Ref;
-// UserRefObjectCo(Window, &Ref);
+ /* Fixes CMD properties closing and returning focus to CMD */
+ if (ti->MessageQueue->spwndFocus == Window)
+ {
+ if ((Window->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
+ {
+ co_UserSetFocus(Window->spwndParent);
+ }
+ else
+ {
+ co_UserSetFocus(NULL);
+ }
+ }
- if (!Window->spwndOwner && !IntGetParent(Window))
+ if (ti->MessageQueue->CaretInfo.hWnd == UserHMGetHandle(Window))
{
- co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (WPARAM) hWnd, 0);
+ co_IntDestroyCaret(ti);
}
-// UserDerefObjectCo(Window);
+ /* If the window being destroyed is currently tracked... */
+ if (ti->rpdesk->spwndTrack == Window)
+ {
+ IntRemoveTrackMouseEvent(ti->rpdesk);
+ }
}
- /* The window could already be destroyed here */
-
- /*
- * Send the WM_DESTROY to the window.
- */
+ /* If the window being destroyed is the current clipboard owner... */
+ if (ti->ppi->prpwinsta != NULL && Window == ti->ppi->prpwinsta->spwndClipOwner)
+ {
+ /* ... make it release the clipboard */
+ UserClipboardRelease(Window);
+ }
+ /* Send the WM_DESTROY to the window */
co_IntSendMessage(hWnd, WM_DESTROY, 0, 0);
/*
* This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
* make sure that the window still exists when we come back.
*/
-#if 0 /* FIXME */
-
- if (IsWindow(Wnd))
+ if (IntIsWindow(hWnd))
{
HWND* pWndArray;
int i;
- if (!(pWndArray = WIN_ListChildren( hwnd )))
- return;
+ if (!(pWndArray = IntWinListChildren( Window ))) return;
- /* start from the end (FIXME: is this needed?) */
for (i = 0; pWndArray[i]; i++)
- ;
-
- while (--i >= 0)
{
- if (IsWindow( pWndArray[i] ))
- WIN_SendDestroyMsg( pWndArray[i] );
+ if (IntIsWindow( pWndArray[i] )) IntSendDestroyMsg( pWndArray[i] );
}
- HeapFree(GetProcessHeap(), 0, pWndArray);
+ ExFreePoolWithTag(pWndArray, USERTAG_WINDOWLIST);
}
else
{
TRACE("destroyed itself while in WM_DESTROY!\n");
}
-#endif
}
static VOID
}
/***********************************************************************
- * IntDestroyWindow
+ * co_UserFreeWindow
*
* Destroy storage associated to a window. "Internals" p.358
*
- * This is the "functional" DestroyWindows function ei. all stuff
- * done in CreateWindow is undone here and not in DestroyWindow:-P
-
+ * This is the "functional" DestroyWindows function i.e. all stuff
+ * done in CreateWindow is undone here and not in DestroyWindow :-P
*/
-static LRESULT co_UserFreeWindow(PWND Window,
- PPROCESSINFO ProcessData,
- PTHREADINFO ThreadData,
- BOOLEAN SendMessages)
+LRESULT co_UserFreeWindow(PWND Window,
+ PPROCESSINFO ProcessData,
+ PTHREADINFO ThreadData,
+ BOOLEAN SendMessages)
{
HWND *Children;
HWND *ChildHandle;
if(Window->state2 & WNDS2_INDESTROY)
{
- TRACE("Tried to call IntDestroyWindow() twice\n");
+ TRACE("Tried to call co_UserFreeWindow() twice\n");
return 0;
}
Window->state2 |= WNDS2_INDESTROY;
Window->style &= ~WS_VISIBLE;
Window->head.pti->cVisWindows--;
- IntNotifyWinEvent(EVENT_OBJECT_DESTROY, Window, OBJID_WINDOW, CHILDID_SELF, 0);
/* remove the window already at this point from the thread window list so we
don't get into trouble when destroying the thread windows while we're still
- in IntDestroyWindow() */
+ in co_UserFreeWindow() */
RemoveEntryList(&Window->ThreadListEntry);
BelongsToThreadData = IntWndBelongsToThread(Window, ThreadData);
- IntDeRegisterShellHookWindow(Window->head.h);
-
- if(SendMessages)
- {
- /* Send destroy messages */
- IntSendDestroyMsg(Window->head.h);
- }
+ IntDeRegisterShellHookWindow(UserHMGetHandle(Window));
/* free child windows */
Children = IntWinListChildren(Window);
{
if ((Child = IntGetWindowObject(*ChildHandle)))
{
- if(!IntWndBelongsToThread(Child, ThreadData))
+ if (!IntWndBelongsToThread(Child, ThreadData))
{
/* send WM_DESTROY messages to windows not belonging to the same thread */
- IntSendDestroyMsg(Child->head.h);
+ co_IntSendMessage( UserHMGetHandle(Child), WM_ASYNC_DESTROYWINDOW, 0, 0 );
}
else
co_UserFreeWindow(Child, ProcessData, ThreadData, SendMessages);
ExFreePoolWithTag(Children, USERTAG_WINDOWLIST);
}
- if(SendMessages)
+ if (SendMessages)
{
/*
* Clear the update region to make sure no WM_PAINT messages will be
co_UserRedrawWindow(Window, NULL, 0,
RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE |
RDW_NOINTERNALPAINT | RDW_NOCHILDREN);
- if(BelongsToThreadData)
- co_IntSendMessage(Window->head.h, WM_NCDESTROY, 0, 0);
+ if (BelongsToThreadData)
+ co_IntSendMessage(UserHMGetHandle(Window), WM_NCDESTROY, 0, 0);
}
+ UserClipboardFreeWindow(Window);
+
DestroyTimersForWindow(ThreadData, Window);
/* Unregister hot keys */
- UnregisterWindowHotKeys (Window);
+ UnregisterWindowHotKeys(Window);
/* flush the message queue */
MsqRemoveWindowMessagesFromQueue(Window);
/* don't remove the WINDOWSTATUS_DESTROYING bit */
/* reset shell window handles */
- if(ThreadData->rpdesk)
+ if (ThreadData->rpdesk)
{
if (Window->head.h == ThreadData->rpdesk->rpwinstaParent->ShellWindow)
ThreadData->rpdesk->rpwinstaParent->ShellWindow = NULL;
ThreadData->rpdesk->rpwinstaParent->ShellListView = NULL;
}
- /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
+ /* Fixes dialog test_focus breakage due to r66237. */
+ if (ThreadData->MessageQueue->spwndFocus == Window)
+ ThreadData->MessageQueue->spwndFocus = NULL;
-#if 0 /* FIXME */
+ if (ThreadData->MessageQueue->spwndActive == Window)
+ ThreadData->MessageQueue->spwndActive = NULL;
- WinPosCheckInternalPos(Window->head.h);
- if (Window->head.h == GetCapture())
+ if (ThreadData->MessageQueue->spwndCapture == Window)
{
- ReleaseCapture();
+ IntReleaseCapture();
}
- /* free resources associated with the window */
- TIMER_RemoveWindowTimers(Window->head.h);
-#endif
+ //// Now kill those remaining "PAINTING BUG: Thread marked as containing dirty windows" spam!!!
+ if ( Window->hrgnUpdate != NULL || Window->state & WNDS_INTERNALPAINT )
+ {
+ MsqDecPaintCountQueue(Window->head.pti);
+ if (Window->hrgnUpdate > HRGN_WINDOW && GreIsHandleValid(Window->hrgnUpdate))
+ {
+ IntGdiSetRegionOwner(Window->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
+ GreDeleteObject(Window->hrgnUpdate);
+ }
+ Window->hrgnUpdate = NULL;
+ Window->state &= ~WNDS_INTERNALPAINT;
+ }
+
+ if (Window->state & (WNDS_SENDERASEBACKGROUND|WNDS_SENDNCPAINT))
+ {
+ Window->state &= ~(WNDS_SENDERASEBACKGROUND|WNDS_SENDNCPAINT);
+ }
if ( ((Window->style & (WS_CHILD|WS_POPUP)) != WS_CHILD) &&
Window->IDMenu &&
(Menu = UserGetMenuObject((HMENU)Window->IDMenu)))
{
- IntDestroyMenuObject(Menu, TRUE, TRUE);
+ TRACE("UFW: IDMenu %p\n",Window->IDMenu);
+ IntDestroyMenuObject(Menu, TRUE);
Window->IDMenu = 0;
}
- if(Window->SystemMenu
- && (Menu = UserGetMenuObject(Window->SystemMenu)))
+ if (Window->SystemMenu
+ && (Menu = UserGetMenuObject(Window->SystemMenu)))
{
- IntDestroyMenuObject(Menu, TRUE, TRUE);
+ IntDestroyMenuObject(Menu, TRUE);
Window->SystemMenu = (HMENU)0;
}
DceFreeWindowDCE(Window); /* Always do this to catch orphaned DCs */
-#if 0 /* FIXME */
-
- WINPROC_FreeProc(Window->winproc, WIN_PROC_WINDOW);
- CLASS_RemoveWindow(Window->Class);
-#endif
IntUnlinkWindow(Window);
if (Window->PropListItems)
{
- IntRemoveWindowProp(Window);
- TRACE("Window->PropListItems %d\n",Window->PropListItems);
+ UserRemoveWindowProps(Window);
+ TRACE("Window->PropListItems %lu\n",Window->PropListItems);
ASSERT(Window->PropListItems==0);
}
UserReferenceObject(Window);
- UserDeleteObject(Window->head.h, TYPE_WINDOW);
+ UserMarkObjectDestroy(Window);
IntDestroyScrollBars(Window);
+ if (Window->pcls->atomClassName == gaGuiConsoleWndClass)
+ {
+ /* Count only console windows manually */
+ co_IntUserManualGuiCheck(FALSE);
+ }
+
/* dereference the class */
+ NT_ASSERT(Window->head.pti != NULL);
IntDereferenceClass(Window->pcls,
Window->head.pti->pDeskInfo,
Window->head.pti->ppi);
Window->pcls = NULL;
- if(Window->hrgnClip)
+ if (Window->hrgnClip)
{
IntGdiSetRegionOwner(Window->hrgnClip, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(Window->hrgnClip);
UserFreeWindowInfo(Window->head.pti, Window);
UserDereferenceObject(Window);
-
- UserClipboardFreeWindow(Window);
+ UserDeleteObject(UserHMGetHandle(Window), TYPE_WINDOW);
return 0;
}
return Ret;
}
-static BOOL FASTCALL
-IntSetMenu(
- PWND Wnd,
- HMENU Menu,
- BOOL *Changed)
-{
- PMENU OldMenu, NewMenu = NULL;
-
- if ((Wnd->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
- {
- ERR("SetMenu: Invalid handle 0x%p!\n",UserHMGetHandle(Wnd));
- EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
- return FALSE;
- }
-
- *Changed = (Wnd->IDMenu != (UINT) Menu);
- if (! *Changed)
- {
- return TRUE;
- }
-
- if (Wnd->IDMenu)
- {
- OldMenu = IntGetMenuObject((HMENU) Wnd->IDMenu);
- ASSERT(NULL == OldMenu || OldMenu->hWnd == Wnd->head.h);
- }
- else
- {
- OldMenu = NULL;
- }
-
- if (NULL != Menu)
- {
- NewMenu = IntGetMenuObject(Menu);
- if (NULL == NewMenu)
- {
- if (NULL != OldMenu)
- {
- IntReleaseMenuObject(OldMenu);
- }
- EngSetLastError(ERROR_INVALID_MENU_HANDLE);
- return FALSE;
- }
- if (NULL != NewMenu->hWnd)
- {
- /* Can't use the same menu for two windows */
- if (NULL != OldMenu)
- {
- IntReleaseMenuObject(OldMenu);
- }
- EngSetLastError(ERROR_INVALID_MENU_HANDLE);
- return FALSE;
- }
-
- }
-
- Wnd->IDMenu = (UINT) Menu;
- if (NULL != NewMenu)
- {
- NewMenu->hWnd = Wnd->head.h;
- IntReleaseMenuObject(NewMenu);
- }
- if (NULL != OldMenu)
- {
- OldMenu->hWnd = NULL;
- IntReleaseMenuObject(OldMenu);
- }
-
- return TRUE;
-}
-
/* INTERNAL ******************************************************************/
-
-VOID FASTCALL
-co_DestroyThreadWindows(struct _ETHREAD *Thread)
-{
- PTHREADINFO WThread;
- PLIST_ENTRY Current;
- PWND Wnd;
- USER_REFERENCE_ENTRY Ref;
- WThread = (PTHREADINFO)Thread->Tcb.Win32Thread;
-
- while (!IsListEmpty(&WThread->WindowListHead))
- {
- Current = WThread->WindowListHead.Flink;
- Wnd = CONTAINING_RECORD(Current, WND, ThreadListEntry);
-
- TRACE("thread cleanup: while destroy wnds, wnd=%p\n", Wnd);
-
- /* Window removes itself from the list */
-
- /*
- * FIXME: It is critical that the window removes itself! If now, we will loop
- * here forever...
- */
-
- //ASSERT(co_UserDestroyWindow(Wnd));
-
- UserRefObjectCo(Wnd, &Ref); // FIXME: Temp HACK??
- if (!co_UserDestroyWindow(Wnd))
- {
- ERR("Unable to destroy window %p at thread cleanup... This is _VERY_ bad!\n", Wnd);
- }
- UserDerefObjectCo(Wnd); // FIXME: Temp HACK??
- }
-}
-
+////
+// This fixes a check for children messages that need paint while searching the parents messages!
+// Fixes wine msg:test_paint_messages:WmParentErasePaint ..
+////
BOOL FASTCALL
IntIsChildWindow(PWND Parent, PWND BaseWindow)
{
- PWND Window;
-
- Window = BaseWindow;
- while (Window && ((Window->style & (WS_POPUP|WS_CHILD)) == WS_CHILD))
+ PWND Window = BaseWindow;
+ do
{
- if (Window == Parent)
- {
- return(TRUE);
- }
+ if ( Window == NULL || (Window->style & (WS_POPUP|WS_CHILD)) != WS_CHILD )
+ return FALSE;
- Window = Window->spwndParent;
+ Window = Window->spwndParent;
}
-
- return(FALSE);
+ while(Parent != Window);
+ return TRUE;
}
+////
-/*
- Link the window into siblings list
- children and parent are kept in place.
-*/
+/* Link the window into siblings list. Children and parent are kept in place. */
VOID FASTCALL
IntLinkWindow(
- PWND Wnd,
- PWND WndInsertAfter /* set to NULL if top sibling */
+ PWND Wnd,
+ PWND WndInsertAfter /* Set to NULL if top sibling */
)
{
- if ((Wnd->spwndPrev = WndInsertAfter))
- {
- /* link after WndInsertAfter */
- if ((Wnd->spwndNext = WndInsertAfter->spwndNext))
- Wnd->spwndNext->spwndPrev = Wnd;
+ if (Wnd == WndInsertAfter)
+ {
+ ERR("IntLinkWindow -- Trying to link window 0x%p to itself!!\n", Wnd);
+ return;
+ }
- Wnd->spwndPrev->spwndNext = Wnd;
- }
- else
- {
- /* link at top */
- if ((Wnd->spwndNext = Wnd->spwndParent->spwndChild))
- Wnd->spwndNext->spwndPrev = Wnd;
+ Wnd->spwndPrev = WndInsertAfter;
+ if (Wnd->spwndPrev)
+ {
+ /* Link after WndInsertAfter */
+ ASSERT(Wnd != WndInsertAfter->spwndNext);
+ Wnd->spwndNext = WndInsertAfter->spwndNext;
+ if (Wnd->spwndNext)
+ Wnd->spwndNext->spwndPrev = Wnd;
+
+ ASSERT(Wnd != Wnd->spwndPrev);
+ Wnd->spwndPrev->spwndNext = Wnd;
+ }
+ else
+ {
+ /* Link at the top */
+ ASSERT(Wnd != Wnd->spwndParent->spwndChild);
+ Wnd->spwndNext = Wnd->spwndParent->spwndChild;
+ if (Wnd->spwndNext)
+ Wnd->spwndNext->spwndPrev = Wnd;
- Wnd->spwndParent->spwndChild = Wnd;
- }
+ Wnd->spwndParent->spwndChild = Wnd;
+ }
}
/*
{
if (hWndPrev == HWND_NOTOPMOST)
{
- if (!(Wnd->ExStyle & WS_EX_TOPMOST) &&
- (Wnd->ExStyle2 & WS_EX2_LINKED)) return; /* nothing to do */
+ if (!(Wnd->ExStyle & WS_EX_TOPMOST) && (Wnd->ExStyle2 & WS_EX2_LINKED))
+ return; /* nothing to do */
Wnd->ExStyle &= ~WS_EX_TOPMOST;
hWndPrev = HWND_TOP; /* fallback to the HWND_TOP case */
}
PWND WndInsertAfter;
WndInsertAfter = Wnd->spwndParent->spwndChild;
- while( WndInsertAfter && WndInsertAfter->spwndNext)
+ while (WndInsertAfter && WndInsertAfter->spwndNext)
+ {
WndInsertAfter = WndInsertAfter->spwndNext;
+ }
IntLinkWindow(Wnd, WndInsertAfter);
Wnd->ExStyle &= ~WS_EX_TOPMOST;
{
/* Link in the top of the list */
IntLinkWindow(Wnd, NULL);
-
Wnd->ExStyle |= WS_EX_TOPMOST;
}
else if (hWndPrev == HWND_TOP)
{
while (WndInsertBefore != NULL && WndInsertBefore->spwndNext != NULL)
{
- if (!(WndInsertBefore->ExStyle & WS_EX_TOPMOST)) break;
+ if (!(WndInsertBefore->ExStyle & WS_EX_TOPMOST))
+ break;
+
if (WndInsertBefore == Wnd->spwndOwner) /* keep it above owner */
{
Wnd->ExStyle |= WS_EX_TOPMOST;
WndInsertAfter = UserGetWindowObject(hWndPrev);
/* Are we called with an erroneous handle */
- if(WndInsertAfter == NULL)
+ if (WndInsertAfter == NULL)
{
/* Link in a default position */
IntLinkHwnd(Wnd, HWND_TOP);
return;
}
+ if (Wnd == WndInsertAfter)
+ ERR("IntLinkHwnd -- Trying to link window 0x%p to itself!!\n", Wnd);
IntLinkWindow(Wnd, WndInsertAfter);
/* Fix the WS_EX_TOPMOST flag */
}
else
{
- if(WndInsertAfter->spwndNext &&
- WndInsertAfter->spwndNext->ExStyle & WS_EX_TOPMOST)
+ if (WndInsertAfter->spwndNext &&
+ (WndInsertAfter->spwndNext->ExStyle & WS_EX_TOPMOST))
{
Wnd->ExStyle |= WS_EX_TOPMOST;
}
/* Link the window with its new siblings */
IntLinkHwnd( Wnd,
((0 == (Wnd->ExStyle & WS_EX_TOPMOST) &&
- WndNewParent == UserGetDesktopWindow() ) ? HWND_TOP : HWND_TOPMOST ) );
-
+ UserIsDesktopWindow(WndNewParent) ) ? HWND_TOP : HWND_TOPMOST ) );
}
if ( WndNewParent == co_GetDesktopWindow(Wnd) &&
{
if ( Wnd->spwndParent != co_GetDesktopWindow(Wnd))
{
- if (Wnd->head.pti != WndOldParent->head.pti)
+ if (WndOldParent && (Wnd->head.pti != WndOldParent->head.pti))
{
//ERR("SetParent Old out.\n");
UserAttachThreadInput(Wnd->head.pti, WndOldParent->head.pti, FALSE);
}
}
- if (WndOldParent == UserGetMessageWindow() || WndNewParent == UserGetMessageWindow())
+ if (UserIsMessageWindow(WndOldParent) || UserIsMessageWindow(WndNewParent))
swFlags |= SWP_NOACTIVATE;
IntNotifyWinEvent(EVENT_OBJECT_PARENTCHANGE, Wnd ,OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
return( hWndOldParent);
}
-/* Unlink the window from siblings. children and parent are kept in place. */
+/* Unlink the window from siblings. Children and parent are kept in place. */
VOID FASTCALL
IntUnlinkWindow(PWND Wnd)
{
- if (Wnd->spwndNext)
- Wnd->spwndNext->spwndPrev = Wnd->spwndPrev;
+ ASSERT(Wnd != Wnd->spwndNext);
+ ASSERT(Wnd != Wnd->spwndPrev);
- if (Wnd->spwndPrev)
- Wnd->spwndPrev->spwndNext = Wnd->spwndNext;
+ if (Wnd->spwndNext)
+ Wnd->spwndNext->spwndPrev = Wnd->spwndPrev;
- if (Wnd->spwndParent && Wnd->spwndParent->spwndChild == Wnd)
- Wnd->spwndParent->spwndChild = Wnd->spwndNext;
+ if (Wnd->spwndPrev)
+ Wnd->spwndPrev->spwndNext = Wnd->spwndNext;
- Wnd->spwndPrev = Wnd->spwndNext = NULL;
+ if (Wnd->spwndParent && Wnd->spwndParent->spwndChild == Wnd)
+ Wnd->spwndParent->spwndChild = Wnd->spwndNext;
+
+ Wnd->spwndPrev = Wnd->spwndNext = NULL;
}
/* FUNCTIONS *****************************************************************/
{
PETHREAD Thread;
PTHREADINFO W32Thread;
- PLIST_ENTRY Current;
PWND Window;
+ HWND *List = NULL;
- Status = PsLookupThreadByThreadId((HANDLE)dwThreadId, &Thread);
+ Status = PsLookupThreadByThreadId(UlongToHandle(dwThreadId), &Thread);
if (!NT_SUCCESS(Status))
{
ERR("Thread Id is not valid!\n");
if (!(W32Thread = (PTHREADINFO)Thread->Tcb.Win32Thread))
{
ObDereferenceObject(Thread);
- ERR("Thread is not initialized!\n");
+ TRACE("Tried to enumerate windows of a non gui thread\n");
return ERROR_INVALID_PARAMETER;
}
- Current = W32Thread->WindowListHead.Flink;
- while (Current != &(W32Thread->WindowListHead))
+ // Do not use Thread link list due to co_UserFreeWindow!!!
+ // Current = W32Thread->WindowListHead.Flink;
+ // Fixes Api:CreateWindowEx tests!!!
+ List = IntWinListChildren(UserGetDesktopWindow());
+ if (List)
{
- Window = CONTAINING_RECORD(Current, WND, ThreadListEntry);
- ASSERT(Window);
-
- if (dwCount < *pBufSize && pWnd)
+ int i;
+ for (i = 0; List[i]; i++)
{
- _SEH2_TRY
+ Window = ValidateHwndNoErr(List[i]);
+ if (Window && Window->head.pti == W32Thread)
{
- ProbeForWrite(pWnd, sizeof(HWND), 1);
- *pWnd = Window->head.h;
- pWnd++;
- }
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
- {
- Status = _SEH2_GetExceptionCode();
- }
- _SEH2_END
- if (!NT_SUCCESS(Status))
- {
- ERR("Failure to build window list!\n");
- SetLastNtError(Status);
- break;
+ if (dwCount < *pBufSize && pWnd)
+ {
+ _SEH2_TRY
+ {
+ ProbeForWrite(pWnd, sizeof(HWND), 1);
+ *pWnd = Window->head.h;
+ pWnd++;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("Failure to build window list!\n");
+ SetLastNtError(Status);
+ break;
+ }
+ }
+ dwCount++;
}
}
- dwCount++;
- Current = Window->ThreadListEntry.Flink;
+ ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
}
ObDereferenceObject(Thread);
static void IntSendParentNotify( PWND pWindow, UINT msg )
{
if ( (pWindow->style & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
- !(pWindow->style & WS_EX_NOPARENTNOTIFY))
+ !(pWindow->ExStyle & WS_EX_NOPARENTNOTIFY))
{
- if (pWindow->spwndParent && pWindow->spwndParent != UserGetDesktopWindow())
+ if (VerifyWnd(pWindow->spwndParent) && !UserIsDesktopWindow(pWindow->spwndParent))
{
USER_REFERENCE_ENTRY Ref;
UserRefObjectCo(pWindow->spwndParent, &Ref);
pWnd->head.pti->cWindows++;
- if (Class->hIcon && !Class->hIconSm)
+ if (Class->spicn && !Class->spicnSm)
{
- Class->hIconSmIntern = co_IntCopyImage( Class->hIcon, IMAGE_ICON,
- UserGetSystemMetrics( SM_CXSMICON ),
- UserGetSystemMetrics( SM_CYSMICON ), 0 );
- TRACE("IntCreateWindow hIconSmIntern %p\n",Class->hIconSmIntern);
- Class->CSF_flags |= CSF_CACHEDSMICON;
+ HICON IconSmHandle = NULL;
+ if((Class->spicn->CURSORF_flags & (CURSORF_LRSHARED | CURSORF_FROMRESOURCE))
+ == (CURSORF_LRSHARED | CURSORF_FROMRESOURCE))
+ {
+ IconSmHandle = co_IntCopyImage(
+ UserHMGetHandle(Class->spicn),
+ IMAGE_ICON,
+ UserGetSystemMetrics( SM_CXSMICON ),
+ UserGetSystemMetrics( SM_CYSMICON ),
+ LR_COPYFROMRESOURCE);
+ }
+ if (!IconSmHandle)
+ {
+ /* Retry without copying from resource */
+ IconSmHandle = co_IntCopyImage(
+ UserHMGetHandle(Class->spicn),
+ IMAGE_ICON,
+ UserGetSystemMetrics( SM_CXSMICON ),
+ UserGetSystemMetrics( SM_CYSMICON ),
+ 0);
+ }
+
+ if (IconSmHandle)
+ {
+ Class->spicnSm = UserGetCurIconObject(IconSmHandle);
+ Class->CSF_flags |= CSF_CACHEDSMICON;
+ }
}
if (pWnd->pcls->CSF_flags & CSF_SERVERSIDEPROC)
if (Class->atomClassName == gpsi->atomSysClass[ICLS_EDIT])
{
PCALLPROCDATA CallProc;
- CallProc = CreateCallProc(NULL, pWnd->lpfnWndProc, pWnd->Unicode , pWnd->head.pti->ppi);
+ CallProc = CreateCallProc(pWnd->head.rpdesk, pWnd->lpfnWndProc, pWnd->Unicode , pWnd->head.pti->ppi);
if (!CallProc)
{
}
InitializeListHead(&pWnd->PropListHead);
+ pWnd->PropListItems = 0;
if ( WindowName->Buffer != NULL && WindowName->Length > 0 )
{
}
}
else // Not a child
- pWnd->IDMenu = (UINT) Cs->hMenu;
+ pWnd->IDMenu = (UINT_PTR)Cs->hMenu;
if ( ParentWindow &&
Class = IntGetAndReferenceClass(ClassName, Cs->hInstance, FALSE);
if(!Class)
{
+ EngSetLastError(ERROR_CANNOT_FIND_WND_CLASS);
ERR("Failed to find class %wZ\n", ClassName);
goto cleanup;
}
}
else if ((Cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
{
- ERR("Cannot create a child window without a parrent!\n");
+ ERR("Cannot create a child window without a parent!\n");
EngSetLastError(ERROR_TLW_WITH_WSCHILD);
goto cleanup; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
}
ParentWindow = hWndParent ? UserGetWindowObject(hWndParent): NULL;
OwnerWindow = hWndOwner ? UserGetWindowObject(hWndOwner): NULL;
- /* FIXME: Is this correct? */
+ if (hWndParent && !ParentWindow)
+ {
+ ERR("Got invalid parent window handle\n");
+ goto cleanup;
+ }
+ else if (hWndOwner && !OwnerWindow)
+ {
+ ERR("Got invalid owner window handle\n");
+ ParentWindow = NULL;
+ goto cleanup;
+ }
+
if(OwnerWindow)
- OwnerWindow = UserGetAncestor(OwnerWindow, GA_ROOT);
+ {
+ if (IntIsDesktopWindow(OwnerWindow)) OwnerWindow = NULL;
+ else if (ParentWindow && !IntIsDesktopWindow(ParentWindow))
+ {
+ ERR("an owned window must be created as top-level\n");
+ EngSetLastError( STATUS_ACCESS_DENIED );
+ goto cleanup;
+ }
+ else /* owner must be a top-level window */
+ {
+ while ((OwnerWindow->style & (WS_POPUP|WS_CHILD)) == WS_CHILD && !IntIsDesktopWindow(OwnerWindow->spwndParent))
+ OwnerWindow = OwnerWindow->spwndParent;
+ }
+ }
/* Fix the position and the size of the window */
if (ParentWindow)
if (ParentWindow != co_GetDesktopWindow(Window))
{
Cs->x += ParentWindow->rcClient.left;
- Cs->y += ParentWindow->rcClient.top;
+ Cs->y += ParentWindow->rcClient.top;
}
}
/* correct child window coordinates if mirroring on parent is enabled */
if (ParentWindow != NULL)
{
- if ( ((Cs->style & WS_CHILD) == WS_CHILD) &&
+ if ( ((Cs->style & WS_CHILD) == WS_CHILD) &&
((ParentWindow->ExStyle & WS_EX_LAYOUTRTL) == WS_EX_LAYOUTRTL))
{
Window->rcWindow.right = ParentWindow->rcClient.right - (Window->rcWindow.left - ParentWindow->rcClient.left);
IntSendParentNotify(Window, WM_CREATE);
/* Notify the shell that a new window was created */
- if (Window->spwndParent == UserGetDesktopWindow() &&
+ if (UserIsDesktopWindow(Window->spwndParent) &&
Window->spwndOwner == NULL &&
(Window->style & WS_VISIBLE) &&
(!(Window->ExStyle & WS_EX_TOOLWINDOW) ||
}
}
+ if (Class->atomClassName == gaGuiConsoleWndClass)
+ {
+ /* Count only console windows manually */
+ co_IntUserManualGuiCheck(TRUE);
+ }
+
TRACE("co_UserCreateWindowEx(): Created window %p\n", hWnd);
ret = Window;
}
if (ParentWindow) UserDerefObjectCo(ParentWindow);
+ // See CORE-13717, not setting error on success.
+ if (ret)
+ EngSetLastError(ERROR_SUCCESS);
+
return ret;
}
NTSTATUS Status;
LARGE_STRING lstrWindowName;
LARGE_STRING lstrClassName;
+ LARGE_STRING lstrClsVersion;
UNICODE_STRING ustrClassName;
+ UNICODE_STRING ustrClsVersion;
CREATESTRUCTW Cs;
HWND hwnd = NULL;
PWND pwnd;
lstrWindowName.Buffer = NULL;
lstrClassName.Buffer = NULL;
+ lstrClsVersion.Buffer = NULL;
ASSERT(plstrWindowName);
- if ( (dwStyle & (WS_POPUP|WS_CHILD)) != WS_CHILD)
+ if ( (dwStyle & (WS_POPUP|WS_CHILD)) != WS_CHILD)
{
/* check hMenu is valid handle */
- if (hMenu && !ValidateHandle(hMenu, TYPE_MENU))
+ if (hMenu && !UserGetMenuObject(hMenu))
{
- /* error is set in ValidateHandle */
+ ERR("NtUserCreateWindowEx: Got an invalid menu handle!\n");
+ EngSetLastError(ERROR_INVALID_MENU_HANDLE);
return NULL;
}
- }
+ }
/* Copy the window name to kernel mode */
Status = ProbeAndCaptureLargeString(&lstrWindowName, plstrWindowName);
ustrClassName.MaximumLength = (USHORT)min(lstrClassName.MaximumLength, MAXUSHORT);
}
+ /* Check if the class version is an atom */
+ if (IS_ATOM(plstrClsVersion))
+ {
+ /* It is, pass the atom in the UNICODE_STRING */
+ ustrClsVersion.Buffer = (PVOID)plstrClsVersion;
+ ustrClsVersion.Length = 0;
+ ustrClsVersion.MaximumLength = 0;
+ }
+ else
+ {
+ /* It's not, capture the class name */
+ Status = ProbeAndCaptureLargeString(&lstrClsVersion, plstrClsVersion);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("NtUserCreateWindowEx: failed to capture plstrClsVersion\n");
+ /* Set last error, cleanup and return */
+ SetLastNtError(Status);
+ goto cleanup;
+ }
+
+ /* We pass it on as a UNICODE_STRING */
+ ustrClsVersion.Buffer = lstrClsVersion.Buffer;
+ ustrClsVersion.Length = (USHORT)min(lstrClsVersion.Length, MAXUSHORT); // FIXME: LARGE_STRING truncated
+ ustrClsVersion.MaximumLength = (USHORT)min(lstrClsVersion.MaximumLength, MAXUSHORT);
+ }
+
/* Fill the CREATESTRUCTW */
/* we will keep here the original parameters */
Cs.style = dwStyle;
Cs.x = x;
Cs.y = y;
Cs.lpszName = (LPCWSTR) plstrWindowName->Buffer;
- if (IS_ATOM(plstrClassName))
- Cs.lpszClass = (LPCWSTR) plstrClassName;
- else
- Cs.lpszClass = (LPCWSTR) plstrClassName->Buffer;
+ Cs.lpszClass = ustrClassName.Buffer;
Cs.dwExStyle = dwExStyle;
UserEnterExclusive();
/* Call the internal function */
- pwnd = co_UserCreateWindowEx(&Cs, &ustrClassName, plstrWindowName, acbiBuffer);
+ pwnd = co_UserCreateWindowEx(&Cs, &ustrClsVersion, plstrWindowName, acbiBuffer);
if(!pwnd)
{
{
ExFreePoolWithTag(lstrClassName.Buffer, TAG_STRING);
}
+ if (lstrClsVersion.Buffer)
+ {
+ ExFreePoolWithTag(lstrClsVersion.Buffer, TAG_STRING);
+ }
return hwnd;
}
-BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window)
+BOOLEAN co_UserDestroyWindow(PVOID Object)
{
HWND hWnd;
PWND pwndTemp;
PTHREADINFO ti;
MSG msg;
+ PWND Window = Object;
ASSERT_REFS_CO(Window); // FIXME: Temp HACK?
hWnd = Window->head.h;
ti = PsGetCurrentThreadWin32Thread();
- TRACE("co_UserDestroyWindow \n");
+ TRACE("co_UserDestroyWindow(Window = 0x%p, hWnd = 0x%p)\n", Window, hWnd);
/* Check for owner thread */
if ( Window->head.pti != PsGetCurrentThreadWin32Thread())
IntSendParentNotify(Window, WM_DESTROY);
}
- /* Look whether the focus is within the tree of windows we will
- * be destroying.
- */
- if (!co_WinPosShowWindow(Window, SW_HIDE))
- { // Rule #1.
- if (ti->MessageQueue->spwndActive == Window && ti->MessageQueue == IntGetFocusMessageQueue())
+ if (!Window->spwndOwner && !IntGetParent(Window))
+ {
+ co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (WPARAM) hWnd, 0);
+ }
+
+ /* Hide the window */
+ if (Window->style & WS_VISIBLE)
+ {
+ if (Window->style & WS_CHILD)
{
- co_WinPosActivateOtherWindow(Window);
+ /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
+ co_WinPosShowWindow(Window, SW_HIDE);
+ }
+ else
+ {
+ co_WinPosSetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE|SWP_HIDEWINDOW );
}
}
- // Adjust last active.
+ /* Adjust last active */
if ((pwndTemp = Window->spwndOwner))
{
while (pwndTemp->spwndOwner)
pwndTemp->spwndLastActive = Window->spwndOwner;
}
- if (Window->spwndParent && IntIsWindow(Window->head.h))
+ if (Window->spwndParent && IntIsWindow(UserHMGetHandle(Window)))
{
if ((Window->style & (WS_POPUP | WS_CHILD)) == WS_CHILD)
{
IntEngWindowChanged(Window, WOC_DELETE);
- if (!IntIsWindow(Window->head.h))
+ if (!IntIsWindow(UserHMGetHandle(Window)))
{
return TRUE;
}
- /* Recursively destroy owned windows */
-
- if (! (Window->style & WS_CHILD))
- {
- for (;;)
- {
- BOOL GotOne = FALSE;
- HWND *Children;
- HWND *ChildHandle;
- PWND Child, Desktop;
-
- Desktop = IntIsDesktopWindow(Window) ? Window :
- UserGetWindowObject(IntGetDesktopWindow());
- Children = IntWinListChildren(Desktop);
+ /* Recursively destroy owned windows */
+ if (!(Window->style & WS_CHILD))
+ {
+ HWND* List;
+ HWND* phWnd;
+ PWND pWnd;
- if (Children)
- {
- for (ChildHandle = Children; *ChildHandle; ++ChildHandle)
+ List = IntWinListOwnedPopups(Window);
+ if (List)
+ {
+ for (phWnd = List; *phWnd; ++phWnd)
{
- Child = UserGetWindowObject(*ChildHandle);
- if (Child == NULL)
- continue;
- if (Child->spwndOwner != Window)
- {
- continue;
- }
-
- if (IntWndBelongsToThread(Child, PsGetCurrentThreadWin32Thread()))
- {
- USER_REFERENCE_ENTRY ChildRef;
- UserRefObjectCo(Child, &ChildRef); // Temp HACK?
- co_UserDestroyWindow(Child);
- UserDerefObjectCo(Child); // Temp HACK?
-
- GotOne = TRUE;
- continue;
- }
-
- if (Child->spwndOwner != NULL)
- {
- Child->spwndOwner = NULL;
- }
-
+ pWnd = ValidateHwndNoErr(*phWnd);
+ if (pWnd == NULL)
+ continue;
+ ASSERT(pWnd->spwndOwner == Window);
+ ASSERT(pWnd != Window);
+
+ pWnd->spwndOwner = NULL;
+ if (IntWndBelongsToThread(pWnd, PsGetCurrentThreadWin32Thread()))
+ {
+ USER_REFERENCE_ENTRY Ref;
+ UserRefObjectCo(pWnd, &Ref); // Temp HACK?
+ co_UserDestroyWindow(pWnd);
+ UserDerefObjectCo(pWnd); // Temp HACK?
+ }
+ else
+ {
+ ERR("IntWndBelongsToThread(0x%p) is FALSE, ignoring.\n", pWnd);
+ }
}
- ExFreePoolWithTag(Children, USERTAG_WINDOWLIST);
- }
- if (! GotOne)
- {
- break;
- }
- }
- }
+
+ ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
+ }
+ }
/* Generate mouse move message for the next window */
msg.message = WM_MOUSEMOVE;
msg.pt = gpsi->ptCursor;
co_MsqInsertMouseMessage(&msg, 0, 0, TRUE);
- if (!IntIsWindow(Window->head.h))
+ IntNotifyWinEvent(EVENT_OBJECT_DESTROY, Window, OBJID_WINDOW, CHILDID_SELF, 0);
+
+ /* Send destroy messages */
+ IntSendDestroyMsg(UserHMGetHandle(Window));
+
+ if (!IntIsWindow(UserHMGetHandle(Window)))
{
return TRUE;
}
/* Do not send WM_GETTEXT messages in the kernel mode version!
The user mode version however calls GetWindowText() which will
send WM_GETTEXT messages to windows belonging to its processes */
- if (!ClassAtom || Child->pcls->atomClassName == ClassAtom)
+ if (!ClassAtom || Child->pcls->atomNVClassName == ClassAtom)
{
// FIXME: LARGE_STRING truncated
CurrentWindowName.Buffer = Child->strName.Buffer;
(Child->strName.Length < 0xFFFF &&
!RtlCompareUnicodeString(WindowName, &CurrentWindowName, TRUE)))
{
- Ret = Child->head.h;
- break;
+ Ret = Child->head.h;
+ break;
+ }
}
}
- }
ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
}
if (!IntGetAtomFromStringOrAtom(&ClassName,
&ClassAtom))
{
+ EngSetLastError(ERROR_CANNOT_FIND_WND_CLASS);
_SEH2_LEAVE;
}
}
(TopLevelWindow->strName.Length < 0xFFFF &&
!RtlCompareUnicodeString(&WindowName, &ustr, TRUE));
ClassMatches = (ClassAtom == (RTL_ATOM)0) ||
- ClassAtom == TopLevelWindow->pcls->atomClassName;
+ ClassAtom == TopLevelWindow->pcls->atomNVClassName;
if (WindowMatches && ClassMatches)
{
}
else
{
- ERR("FindWindowEx: Not Desktop Parent!\n");
+ TRACE("FindWindowEx: Not Desktop Parent!\n");
Ret = IntFindWindow(Parent, ChildAfter, ClassAtom, &WindowName);
}
}
_SEH2_TRY
{
- if(pcbi)
- {
- ProbeForWrite(pcbi,
- sizeof(COMBOBOXINFO),
- 1);
- }
+ ProbeForWrite(pcbi, sizeof(COMBOBOXINFO), 1);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
SetLastNtError(_SEH2_GetExceptionCode());
}
_SEH2_END;
-
+
RETURN( Ret);
CLEANUP:
SetLastNtError(_SEH2_GetExceptionCode());
}
_SEH2_END;
-
+
RETURN( Ret);
CLEANUP:
HWND Ret;
NTSTATUS Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
- KernelMode,
+ UserMode,
0,
- &WinStaObject);
+ &WinStaObject,
+ 0);
if (!NT_SUCCESS(Status))
{
RETURN(FALSE);
}
- if(!(WndListView = UserGetWindowObject(hwndListView)))
+ if (!(WndListView = UserGetWindowObject(hwndListView)))
{
RETURN(FALSE);
}
Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
- KernelMode,
+ UserMode,
0,
- &WinStaObject);
+ &WinStaObject,
+ 0);
if (!NT_SUCCESS(Status))
{
{
ti->pDeskInfo->hShellWindow = hwndShell;
ti->pDeskInfo->spwndShell = WndShell;
+ ti->pDeskInfo->spwndBkGnd = WndListView;
ti->pDeskInfo->ppiShellProcess = ti->ppi;
}
return FALSE;
}
-LONG FASTCALL
-co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
+static LONG_PTR
+co_IntSetWindowLongPtr(HWND hWnd, DWORD Index, LONG_PTR NewValue, BOOL Ansi, ULONG Size, BOOL bAlter)
{
PWND Window, Parent;
PWINSTATION_OBJECT WindowStation;
- LONG OldValue;
+ LONG_PTR OldValue;
STYLESTRUCT Style;
if (!(Window = UserGetWindowObject(hWnd)))
if ((INT)Index >= 0)
{
- if ((Index + sizeof(LONG)) > Window->cbwndExtra)
+ if ((Index + Size) > Window->cbwndExtra)
{
EngSetLastError(ERROR_INVALID_INDEX);
return( 0);
}
- OldValue = *((LONG *)((PCHAR)(Window + 1) + Index));
-/*
- if ( Index == DWLP_DLGPROC && Wnd->state & WNDS_DIALOGWINDOW)
+#ifdef _WIN64
+ if (Size == sizeof(LONG))
{
- OldValue = (LONG)IntSetWindowProc( Wnd,
- (WNDPROC)NewValue,
- Ansi);
- if (!OldValue) return 0;
+ OldValue = *((LONG *)((PCHAR)(Window + 1) + Index));
+ *((LONG*)((PCHAR)(Window + 1) + Index)) = (LONG)NewValue;
}
-*/
- *((LONG *)((PCHAR)(Window + 1) + Index)) = NewValue;
+ else
+#endif
+ {
+ OldValue = *((LONG_PTR *)((PCHAR)(Window + 1) + Index));
+ /*
+ if ( Index == DWLP_DLGPROC && Wnd->state & WNDS_DIALOGWINDOW)
+ {
+ OldValue = (LONG_PTR)IntSetWindowProc( Wnd, (WNDPROC)NewValue, Ansi);
+ if (!OldValue) return 0;
+ }
+ */
+ *((LONG_PTR*)((PCHAR)(Window + 1) + Index)) = NewValue;
+ }
+
}
else
{
+#ifdef _WIN64
+ if (Size == sizeof(LONG))
+ {
+ if ((Index != GWL_STYLE) &&
+ (Index != GWL_EXSTYLE) &&
+ (Index != GWL_ID) &&
+ (Index != GWL_USERDATA))
+ {
+ ERR("NtUserSetWindowLong(): Index requires pointer size: %lu\n", Index);
+ EngSetLastError(ERROR_INVALID_INDEX);
+ return 0;
+ }
+ }
+#endif
+
switch (Index)
{
- case GWL_EXSTYLE:
+ case GWL_EXSTYLE: // LONG
OldValue = (LONG) Window->ExStyle;
Style.styleOld = OldValue;
Style.styleNew = NewValue;
else
Style.styleNew &= ~WS_EX_WINDOWEDGE;
+ if (!(Window->ExStyle & WS_EX_LAYERED))
+ {
+ SetLayeredStatus(Window, 0);
+ }
+
Window->ExStyle = (DWORD)Style.styleNew;
+
co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_EXSTYLE, (LPARAM) &Style);
break;
- case GWL_STYLE:
+ case GWL_STYLE: // LONG
OldValue = (LONG) Window->style;
Style.styleOld = OldValue;
Style.styleNew = NewValue;
- co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_STYLE, (LPARAM) &Style);
- /* WS_CLIPSIBLINGS can't be reset on top-level windows */
- if (Window->spwndParent == UserGetDesktopWindow()) Style.styleNew |= WS_CLIPSIBLINGS;
+ if (!bAlter)
+ co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_STYLE, (LPARAM) &Style);
+
+ /* WS_CLIPSIBLINGS can't be reset on top-level windows */
+ if (UserIsDesktopWindow(Window->spwndParent)) Style.styleNew |= WS_CLIPSIBLINGS;
+ /* WS_MINIMIZE can't be reset */
+ if (OldValue & WS_MINIMIZE) Style.styleNew |= WS_MINIMIZE;
/* Fixes wine FIXME: changing WS_DLGFRAME | WS_THICKFRAME is supposed to change WS_EX_WINDOWEDGE too */
if (IntCheckFrameEdge(NewValue, Window->ExStyle))
Window->ExStyle |= WS_EX_WINDOWEDGE;
else
Window->ExStyle &= ~WS_EX_WINDOWEDGE;
+ if ((OldValue & (WS_CHILD | WS_POPUP)) == WS_CHILD)
+ {
+ if ((NewValue & (WS_CHILD | WS_POPUP)) != WS_CHILD)
+ {
+ //// From child to non-child it should be null already.
+ ERR("IDMenu going null! %d\n",Window->IDMenu);
+ Window->IDMenu = 0; // Window->spmenu = 0;
+ }
+ }
+ else
+ {
+ if ((NewValue & (WS_CHILD | WS_POPUP)) == WS_CHILD)
+ {
+ PMENU pMenu = UserGetMenuObject(UlongToHandle(Window->IDMenu));
+ Window->state &= ~WNDS_HASMENU;
+ if (pMenu)
+ {
+ ERR("IDMenu released 0x%p\n",pMenu);
+ // ROS may not hold a lock after setting menu to window. But it should!
+ //IntReleaseMenuObject(pMenu);
+ }
+ }
+ }
+
if ((Style.styleOld ^ Style.styleNew) & WS_VISIBLE)
{
if (Style.styleOld & WS_VISIBLE) Window->head.pti->cVisWindows--;
DceResetActiveDCEs( Window );
}
Window->style = (DWORD)Style.styleNew;
- co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_STYLE, (LPARAM) &Style);
+
+ if (!bAlter)
+ co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_STYLE, (LPARAM) &Style);
break;
- case GWL_WNDPROC:
+ case GWLP_WNDPROC: // LONG_PTR
{
if ( Window->head.pti->ppi != PsGetCurrentProcessWin32Process() ||
Window->fnid & FNID_FREED)
EngSetLastError(ERROR_ACCESS_DENIED);
return( 0);
}
- OldValue = (LONG)IntSetWindowProc(Window,
- (WNDPROC)NewValue,
- Ansi);
+ OldValue = (LONG_PTR)IntSetWindowProc(Window,
+ (WNDPROC)NewValue,
+ Ansi);
break;
}
- case GWL_HINSTANCE:
- OldValue = (LONG) Window->hModule;
+ case GWLP_HINSTANCE: // LONG_PTR
+ OldValue = (LONG_PTR) Window->hModule;
Window->hModule = (HINSTANCE) NewValue;
break;
- case GWL_HWNDPARENT:
+ case GWLP_HWNDPARENT: // LONG_PTR
Parent = Window->spwndParent;
if (Parent && (Parent->head.h == IntGetDesktopWindow()))
- OldValue = (LONG) IntSetOwner(Window->head.h, (HWND) NewValue);
+ OldValue = (LONG_PTR) IntSetOwner(Window->head.h, (HWND) NewValue);
else
- OldValue = (LONG) co_UserSetParent(Window->head.h, (HWND) NewValue);
+ OldValue = (LONG_PTR) co_UserSetParent(Window->head.h, (HWND) NewValue);
break;
- case GWL_ID:
+ case GWLP_ID: // LONG
OldValue = (LONG) Window->IDMenu;
Window->IDMenu = (UINT) NewValue;
break;
- case GWL_USERDATA:
+ case GWLP_USERDATA: // LONG or LONG_PTR
OldValue = Window->dwUserData;
Window->dwUserData = NewValue;
break;
return( OldValue);
}
+LONG FASTCALL
+co_UserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
+{
+ return (LONG)co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG), FALSE);
+}
+
+LONG_PTR FASTCALL
+co_UserSetWindowLongPtr(HWND hWnd, DWORD Index, LONG_PTR NewValue, BOOL Ansi)
+{
+ return co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG_PTR), FALSE);
+}
+
/*
* NtUserSetWindowLong
*
LONG APIENTRY
NtUserSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi)
{
- DECLARE_RETURN(LONG);
+ LONG ret;
- TRACE("Enter NtUserSetWindowLong\n");
UserEnterExclusive();
if (hWnd == IntGetDesktopWindow())
{
EngSetLastError(STATUS_ACCESS_DENIED);
- RETURN( 0);
+ UserLeave();
+ return 0;
}
- RETURN( co_UserSetWindowLong(hWnd, Index, NewValue, Ansi));
+ ret = (LONG)co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG), FALSE);
-CLEANUP:
- TRACE("Leave NtUserSetWindowLong, ret=%i\n",_ret_);
UserLeave();
- END_CLEANUP;
+
+ return ret;
+}
+
+#ifdef _WIN64
+LONG_PTR APIENTRY
+NtUserSetWindowLongPtr(HWND hWnd, DWORD Index, LONG_PTR NewValue, BOOL Ansi)
+{
+ LONG_PTR ret;
+
+ UserEnterExclusive();
+
+ if (hWnd == IntGetDesktopWindow())
+ {
+ EngSetLastError(STATUS_ACCESS_DENIED);
+ UserLeave();
+ return 0;
+ }
+
+ ret = co_IntSetWindowLongPtr(hWnd, Index, NewValue, Ansi, sizeof(LONG_PTR), FALSE);
+
+ UserLeave();
+
+ return ret;
+}
+#endif // _WIN64
+
+DWORD APIENTRY
+NtUserAlterWindowStyle(HWND hWnd, DWORD Index, LONG NewValue)
+{
+ LONG ret;
+
+ UserEnterExclusive();
+
+ if (hWnd == IntGetDesktopWindow())
+ {
+ EngSetLastError(STATUS_ACCESS_DENIED);
+ UserLeave();
+ return 0;
+ }
+
+ ret = co_IntSetWindowLongPtr(hWnd, Index, NewValue, FALSE, sizeof(LONG), TRUE);
+
+ UserLeave();
+
+ return ret;
}
+
/*
* NtUserSetWindowWord
*
/*
* @implemented
*/
-DWORD APIENTRY
+DWORD_PTR APIENTRY
NtUserQueryWindow(HWND hWnd, DWORD Index)
{
/* Console Leader Process CID Window offsets */
#define GWLP_CONSOLE_LEADER_TID 4
PWND pWnd;
- DWORD Result;
+ DWORD_PTR Result;
DECLARE_RETURN(UINT);
TRACE("Enter NtUserQueryWindow\n");
(pWnd->pcls->atomClassName == gaGuiConsoleWndClass) )
{
// IntGetWindowLong(offset == GWLP_CONSOLE_LEADER_PID)
- Result = (DWORD)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_PID)));
+ Result = (DWORD_PTR)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_PID)));
}
else
{
- Result = (DWORD)IntGetWndProcessId(pWnd);
+ Result = (DWORD_PTR)IntGetWndProcessId(pWnd);
}
break;
}
(pWnd->pcls->atomClassName == gaGuiConsoleWndClass) )
{
// IntGetWindowLong(offset == GWLP_CONSOLE_LEADER_TID)
- Result = (DWORD)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_TID)));
+ Result = (DWORD_PTR)(*((LONG_PTR*)((PCHAR)(pWnd + 1) + GWLP_CONSOLE_LEADER_TID)));
}
else
{
- Result = (DWORD)IntGetWndThreadId(pWnd);
+ Result = (DWORD_PTR)IntGetWndThreadId(pWnd);
}
break;
}
case QUERY_WINDOW_ACTIVE:
- Result = (DWORD)(pWnd->head.pti->MessageQueue->spwndActive ? UserHMGetHandle(pWnd->head.pti->MessageQueue->spwndActive) : 0);
+ Result = (DWORD_PTR)(pWnd->head.pti->MessageQueue->spwndActive ? UserHMGetHandle(pWnd->head.pti->MessageQueue->spwndActive) : 0);
break;
case QUERY_WINDOW_FOCUS:
- Result = (DWORD)(pWnd->head.pti->MessageQueue->spwndFocus ? UserHMGetHandle(pWnd->head.pti->MessageQueue->spwndFocus) : 0);
+ Result = (DWORD_PTR)(pWnd->head.pti->MessageQueue->spwndFocus ? UserHMGetHandle(pWnd->head.pti->MessageQueue->spwndFocus) : 0);
break;
case QUERY_WINDOW_ISHUNG:
- Result = (DWORD)MsqIsHung(pWnd->head.pti);
+ Result = (DWORD_PTR)MsqIsHung(pWnd->head.pti);
break;
case QUERY_WINDOW_REAL_ID:
- Result = (DWORD)pWnd->head.pti->pEThread->Cid.UniqueProcess;
+ Result = (DWORD_PTR)pWnd->head.pti->pEThread->Cid.UniqueProcess;
break;
case QUERY_WINDOW_FOREGROUND:
break;
default:
- Result = (DWORD)NULL;
+ Result = 0;
break;
}
END_CLEANUP;
}
-
/*
* @implemented
*/
END_CLEANUP;
}
-
-/*
- * @implemented
- */
-BOOL APIENTRY
-NtUserSetMenu(
- HWND hWnd,
- HMENU Menu,
- BOOL Repaint)
-{
- PWND Window;
- BOOL Changed;
- DECLARE_RETURN(BOOL);
-
- TRACE("Enter NtUserSetMenu\n");
- UserEnterExclusive();
-
- if (!(Window = UserGetWindowObject(hWnd)))
- {
- RETURN( FALSE);
- }
-
- if (! IntSetMenu(Window, Menu, &Changed))
- {
- RETURN( FALSE);
- }
-
- if (Changed && Repaint)
- {
- USER_REFERENCE_ENTRY Ref;
-
- UserRefObjectCo(Window, &Ref);
- co_WinPosSetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
- SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
-
- UserDerefObjectCo(Window);
- }
-
- RETURN( TRUE);
-
-CLEANUP:
- TRACE("Leave NtUserSetMenu, ret=%i\n",_ret_);
- UserLeave();
- END_CLEANUP;
-}
-
/*
* @implemented
*/
// From user land we only set these.
if (fnID != FNID_DESTROY)
- { // Hacked so we can mark desktop~!
- if ( (/*(fnID < FNID_BUTTON)*/ (fnID < FNID_FIRST) && (fnID > FNID_GHOST)) ||
- Wnd->fnid != 0 )
+ {
+ /* HACK: The minimum should be FNID_BUTTON, but menu code relies on this */
+ if (fnID < FNID_FIRST || fnID > FNID_GHOST ||
+ Wnd->fnid != 0)
{
EngSetLastError(ERROR_INVALID_PARAMETER);
RETURN( FALSE);
END_CLEANUP;
}
+BOOL APIENTRY
+DefSetText(PWND Wnd, PCWSTR WindowText)
+{
+ UNICODE_STRING UnicodeString;
+ BOOL Ret = FALSE;
+
+ RtlInitUnicodeString(&UnicodeString, WindowText);
+
+ if (UnicodeString.Length != 0)
+ {
+ if (Wnd->strName.MaximumLength > 0 &&
+ UnicodeString.Length <= Wnd->strName.MaximumLength - sizeof(UNICODE_NULL))
+ {
+ ASSERT(Wnd->strName.Buffer != NULL);
+
+ Wnd->strName.Length = UnicodeString.Length;
+ Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
+ RtlCopyMemory(Wnd->strName.Buffer,
+ UnicodeString.Buffer,
+ UnicodeString.Length);
+ }
+ else
+ {
+ PWCHAR buf;
+ Wnd->strName.MaximumLength = Wnd->strName.Length = 0;
+ buf = Wnd->strName.Buffer;
+ Wnd->strName.Buffer = NULL;
+ if (buf != NULL)
+ {
+ DesktopHeapFree(Wnd->head.rpdesk, buf);
+ }
+
+ Wnd->strName.Buffer = DesktopHeapAlloc(Wnd->head.rpdesk,
+ UnicodeString.Length + sizeof(UNICODE_NULL));
+ if (Wnd->strName.Buffer != NULL)
+ {
+ Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
+ RtlCopyMemory(Wnd->strName.Buffer,
+ UnicodeString.Buffer,
+ UnicodeString.Length);
+ Wnd->strName.MaximumLength = UnicodeString.Length + sizeof(UNICODE_NULL);
+ Wnd->strName.Length = UnicodeString.Length;
+ }
+ else
+ {
+ EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto Exit;
+ }
+ }
+ }
+ else
+ {
+ Wnd->strName.Length = 0;
+ if (Wnd->strName.Buffer != NULL)
+ Wnd->strName.Buffer[0] = L'\0';
+ }
+
+ // FIXME: HAX! Windows does not do this in here!
+ // In User32, these are called after: NotifyWinEvent EVENT_OBJECT_NAMECHANGE than
+ // RepaintButton, StaticRepaint, NtUserCallHwndLock HWNDLOCK_ROUTINE_REDRAWFRAMEANDHOOK, etc.
+ /* Send shell notifications */
+ if (!Wnd->spwndOwner && !IntGetParent(Wnd))
+ {
+ co_IntShellHookNotify(HSHELL_REDRAW, (WPARAM) UserHMGetHandle(Wnd), FALSE); // FIXME Flashing?
+ }
+
+ Ret = TRUE;
+Exit:
+ if (UnicodeString.Buffer) RtlFreeUnicodeString(&UnicodeString);
+ return Ret;
+}
+
/*
* NtUserDefSetText
*
// ASSERT(OwnerWnd);
TRACE("Enter ShowOwnedPopups Show: %s\n", (fShow ? "TRUE" : "FALSE"));
- win_array = IntWinListChildren(OwnerWnd);
+
+ /* NOTE: Popups are not children */
+ win_array = IntWinListOwnedPopups(OwnerWnd);
if (!win_array)
return TRUE;
* regardless of the state of the owner
*/
co_IntSendMessage(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
+ pWnd->state &= ~WNDS_HIDDENPOPUP;
continue;
}
}
* regardless of the state of the owner
*/
co_IntSendMessage(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
+ pWnd->state |= WNDS_HIDDENPOPUP;
continue;
}
}
-
}
ExFreePoolWithTag(win_array, USERTAG_WINDOWLIST);
TRACE("Leave ShowOwnedPopups\n");