mirror of
https://github.com/reactos/reactos.git
synced 2024-12-31 19:42:51 +00:00
[WIN32K:NTUSER] In UserSetProcessWindowStation(), use a duplicated window station handle to be set in the EPROCESS:Win32WindowStation cache.
Fixes most of the user32:desktop window station handle reference count tests.
This commit is contained in:
parent
e3b9152935
commit
d0632b0bca
1 changed files with 60 additions and 15 deletions
|
@ -972,7 +972,6 @@ NtUserCloseWindowStation(
|
||||||
0,
|
0,
|
||||||
&Object,
|
&Object,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
ERR("Validation of window station handle (%p) failed\n", hWinSta);
|
ERR("Validation of window station handle (%p) failed\n", hWinSta);
|
||||||
|
@ -1319,11 +1318,11 @@ NtUserGetProcessWindowStation(VOID)
|
||||||
BOOL FASTCALL
|
BOOL FASTCALL
|
||||||
UserSetProcessWindowStation(HWINSTA hWindowStation)
|
UserSetProcessWindowStation(HWINSTA hWindowStation)
|
||||||
{
|
{
|
||||||
PPROCESSINFO ppi;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
HWINSTA hwinstaOld;
|
PPROCESSINFO ppi;
|
||||||
OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
|
OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
|
||||||
PWINSTATION_OBJECT NewWinSta = NULL, OldWinSta;
|
PWINSTATION_OBJECT NewWinSta = NULL, OldWinSta;
|
||||||
|
HWINSTA hCacheWinSta;
|
||||||
|
|
||||||
ppi = PsGetCurrentProcessWin32Process();
|
ppi = PsGetCurrentProcessWin32Process();
|
||||||
|
|
||||||
|
@ -1337,15 +1336,14 @@ UserSetProcessWindowStation(HWINSTA hWindowStation)
|
||||||
&ObjectHandleInfo);
|
&ObjectHandleInfo);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
TRACE("Validation of window station handle (%p) failed\n",
|
TRACE("Validation of window station handle 0x%p failed\n", hWindowStation);
|
||||||
hWindowStation);
|
|
||||||
SetLastNtError(Status);
|
SetLastNtError(Status);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OldWinSta = ppi->prpwinsta;
|
OldWinSta = ppi->prpwinsta;
|
||||||
hwinstaOld = PsGetProcessWin32WindowStation(ppi->peProcess);
|
hCacheWinSta = PsGetProcessWin32WindowStation(ppi->peProcess);
|
||||||
|
|
||||||
/* Dereference the previous window station */
|
/* Dereference the previous window station */
|
||||||
if (OldWinSta != NULL)
|
if (OldWinSta != NULL)
|
||||||
|
@ -1353,17 +1351,64 @@ UserSetProcessWindowStation(HWINSTA hWindowStation)
|
||||||
ObDereferenceObject(OldWinSta);
|
ObDereferenceObject(OldWinSta);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we have a stale handle (it should happen for console apps) */
|
|
||||||
if (hwinstaOld != ppi->hwinsta)
|
|
||||||
{
|
|
||||||
ObCloseHandle(hwinstaOld, UserMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME: Don't allow changing the window station if there are threads that are attached to desktops and own GUI objects.
|
* FIXME: Don't allow changing the window station if there are threads that are attached to desktops and own GUI objects?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
PsSetProcessWindowStation(ppi->peProcess, hWindowStation);
|
/* Close the cached EPROCESS window station handle if needed */
|
||||||
|
if (hCacheWinSta != NULL)
|
||||||
|
{
|
||||||
|
/* Reference the window station */
|
||||||
|
Status = ObReferenceObjectByHandle(hCacheWinSta,
|
||||||
|
0,
|
||||||
|
ExWindowStationObjectType,
|
||||||
|
UserMode,
|
||||||
|
(PVOID*)&OldWinSta,
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ERR("Failed to reference the inherited window station, Status 0x%08lx\n", Status);
|
||||||
|
/* We failed, reset the cache */
|
||||||
|
hCacheWinSta = NULL;
|
||||||
|
PsSetProcessWindowStation(ppi->peProcess, hCacheWinSta);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Close the old handle and reset the cache only
|
||||||
|
* if we are setting a different window station.
|
||||||
|
*/
|
||||||
|
if (NewWinSta != OldWinSta)
|
||||||
|
{
|
||||||
|
ObCloseHandle(hCacheWinSta, UserMode);
|
||||||
|
hCacheWinSta = NULL;
|
||||||
|
PsSetProcessWindowStation(ppi->peProcess, hCacheWinSta);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dereference the window station */
|
||||||
|
ObDereferenceObject(OldWinSta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Duplicate and save a new cached EPROCESS window station handle */
|
||||||
|
if ((hCacheWinSta == NULL) && (hWindowStation != NULL))
|
||||||
|
{
|
||||||
|
Status = ZwDuplicateObject(ZwCurrentProcess(),
|
||||||
|
hWindowStation,
|
||||||
|
ZwCurrentProcess(),
|
||||||
|
(PHANDLE)&hCacheWinSta,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
DUPLICATE_SAME_ACCESS);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
ERR("UserSetProcessWindowStation: Failed to duplicate the window station handle, Status 0x%08lx\n", Status);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PsSetProcessWindowStation(ppi->peProcess, hCacheWinSta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ppi->prpwinsta = NewWinSta;
|
ppi->prpwinsta = NewWinSta;
|
||||||
ppi->hwinsta = hWindowStation;
|
ppi->hwinsta = hWindowStation;
|
||||||
|
@ -1383,7 +1428,7 @@ UserSetProcessWindowStation(HWINSTA hWindowStation)
|
||||||
{
|
{
|
||||||
ppi->W32PF_flags |= W32PF_IOWINSTA;
|
ppi->W32PF_flags |= W32PF_IOWINSTA;
|
||||||
}
|
}
|
||||||
else // Might be closed if the handle is null.
|
else /* Might be closed if the handle is NULL */
|
||||||
{
|
{
|
||||||
ppi->W32PF_flags &= ~W32PF_IOWINSTA;
|
ppi->W32PF_flags &= ~W32PF_IOWINSTA;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue