https://git.reactos.org/?p=reactos.git;a=commitdiff;h=d0632b0bca74e7aed85a5…
commit d0632b0bca74e7aed85a58d65245e951b31aa63b
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Mon Jul 23 01:17:14 2018 +0200
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Sun Aug 19 22:18:42 2018 +0200
[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.
---
win32ss/user/ntuser/winsta.c | 75 +++++++++++++++++++++++++++++++++++---------
1 file changed, 60 insertions(+), 15 deletions(-)
diff --git a/win32ss/user/ntuser/winsta.c b/win32ss/user/ntuser/winsta.c
index 13b968516c..12a1b90d3a 100644
--- a/win32ss/user/ntuser/winsta.c
+++ b/win32ss/user/ntuser/winsta.c
@@ -972,7 +972,6 @@ NtUserCloseWindowStation(
0,
&Object,
NULL);
-
if (!NT_SUCCESS(Status))
{
ERR("Validation of window station handle (%p) failed\n", hWinSta);
@@ -1319,11 +1318,11 @@ NtUserGetProcessWindowStation(VOID)
BOOL FASTCALL
UserSetProcessWindowStation(HWINSTA hWindowStation)
{
- PPROCESSINFO ppi;
NTSTATUS Status;
- HWINSTA hwinstaOld;
+ PPROCESSINFO ppi;
OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
PWINSTATION_OBJECT NewWinSta = NULL, OldWinSta;
+ HWINSTA hCacheWinSta;
ppi = PsGetCurrentProcessWin32Process();
@@ -1337,15 +1336,14 @@ UserSetProcessWindowStation(HWINSTA hWindowStation)
&ObjectHandleInfo);
if (!NT_SUCCESS(Status))
{
- TRACE("Validation of window station handle (%p) failed\n",
- hWindowStation);
+ TRACE("Validation of window station handle 0x%p failed\n",
hWindowStation);
SetLastNtError(Status);
return FALSE;
}
}
OldWinSta = ppi->prpwinsta;
- hwinstaOld = PsGetProcessWin32WindowStation(ppi->peProcess);
+ hCacheWinSta = PsGetProcessWin32WindowStation(ppi->peProcess);
/* Dereference the previous window station */
if (OldWinSta != NULL)
@@ -1353,17 +1351,64 @@ UserSetProcessWindowStation(HWINSTA hWindowStation)
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->hwinsta = hWindowStation;
@@ -1383,7 +1428,7 @@ UserSetProcessWindowStation(HWINSTA hWindowStation)
{
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;
}