if (Window)
{
- /* Look whether the focus is within the tree of windows we will
- * be destroying.
+ /*
+ * 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.
}
}
- /*
- * 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 (IntIsWindow(hWnd))
{
HWND* pWndArray;
}
/***********************************************************************
- * 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
*/
LRESULT co_UserFreeWindow(PWND Window,
PPROCESSINFO ProcessData,
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;
/* 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);
{
if ((Child = IntGetWindowObject(*ChildHandle)))
{
- if(!IntWndBelongsToThread(Child, ThreadData))
+ if (!IntWndBelongsToThread(Child, ThreadData))
{
/* send WM_DESTROY messages to windows not belonging to the same thread */
co_IntSendMessage( UserHMGetHandle(Child), WM_ASYNC_DESTROYWINDOW, 0, 0 );
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)
+ if (BelongsToThreadData)
co_IntSendMessage(UserHMGetHandle(Window), WM_NCDESTROY, 0, 0);
}
+ UserClipboardFreeWindow(Window);
+
DestroyTimersForWindow(ThreadData, Window);
/* Unregister hot keys */
/* 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;
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->IDMenu = 0;
}
- if(Window->SystemMenu
- && (Menu = UserGetMenuObject(Window->SystemMenu)))
+ if (Window->SystemMenu
+ && (Menu = UserGetMenuObject(Window->SystemMenu)))
{
IntDestroyMenuObject(Menu, TRUE);
Window->SystemMenu = (HMENU)0;
}
UserReferenceObject(Window);
- UserDeleteObject(UserHMGetHandle(Window), TYPE_WINDOW);
+ UserMarkObjectDestroy(Window);
IntDestroyScrollBars(Window);
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;
}
Class = IntGetAndReferenceClass(ClassName, Cs->hInstance, FALSE);
if(!Class)
{
+ EngSetLastError(ERROR_CANNOT_FIND_WND_CLASS);
ERR("Failed to find class %wZ\n", ClassName);
goto cleanup;
}
goto cleanup;
}
- /* FIXME: Is this correct? */
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)
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);
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;
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;
}
IntNotifyWinEvent(EVENT_OBJECT_DESTROY, Window, OBJID_WINDOW, CHILDID_SELF, 0);
/* Send destroy messages */
-
IntSendDestroyMsg(UserHMGetHandle(Window));
if (!IntIsWindow(UserHMGetHandle(Window)))
/* 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;
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);
}
{
ti->pDeskInfo->hShellWindow = hwndShell;
ti->pDeskInfo->spwndShell = WndShell;
+ ti->pDeskInfo->spwndBkGnd = WndListView;
ti->pDeskInfo->ppiShellProcess = ti->ppi;
}
if (!bAlter)
co_IntSendMessage(hWnd, WM_STYLECHANGING, GWL_STYLE, (LPARAM) &Style);
- /* WS_CLIPSIBLINGS can't be reset on top-level windows */
+ /* WS_CLIPSIBLINGS can't be reset on top-level windows */
if (Window->spwndParent == UserGetDesktopWindow()) 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--;