}
}
- /*
- * 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);
/*
co_IntSendMessage(UserHMGetHandle(Window), WM_NCDESTROY, 0, 0);
}
+ UserClipboardFreeWindow(Window);
+
DestroyTimersForWindow(ThreadData, Window);
/* Unregister hot keys */
}
UserReferenceObject(Window);
- UserDeleteObject(UserHMGetHandle(Window), TYPE_WINDOW);
+ UserMarkObjectDestroy(Window);
IntDestroyScrollBars(Window);
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;
}
/* 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--;