mirror of
https://github.com/reactos/reactos.git
synced 2024-09-28 13:34:53 +00:00
[ntoskrnl]
- Implement calling OkayToCloseProcedure callouts to win32k for desktop and window station objects - Fix a bug that caused ObpCloseHandle to return success even when OkayToCloseProcedure failed [win32k] - Rewrite SetProcessWindowStation to actually set the current window station and close the previous one - Implement OkayToCloseProcedure callouts from the kernel to prevent closing the current desktop or window station svn path=/trunk/; revision=51115
This commit is contained in:
parent
eb3ddf59b3
commit
8cf95d1319
|
@ -37,10 +37,46 @@ GENERIC_MAPPING ExpDesktopMapping =
|
|||
|
||||
PKWIN32_PARSEMETHOD_CALLOUT ExpWindowStationObjectParse = NULL;
|
||||
PKWIN32_DELETEMETHOD_CALLOUT ExpWindowStationObjectDelete = NULL;
|
||||
PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExpWindowStationObjectOkToClose = NULL;
|
||||
PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExpDesktopObjectOkToClose = NULL;
|
||||
PKWIN32_DELETEMETHOD_CALLOUT ExpDesktopObjectDelete = NULL;
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ExpDesktopOkToClose( IN PEPROCESS Process OPTIONAL,
|
||||
IN PVOID Object,
|
||||
IN HANDLE Handle,
|
||||
IN KPROCESSOR_MODE AccessMode)
|
||||
{
|
||||
WIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters;
|
||||
|
||||
Parameters.Process = Process;
|
||||
Parameters.Object = Object;
|
||||
Parameters.Handle = Handle;
|
||||
Parameters.PreviousMode = AccessMode;
|
||||
|
||||
return ExpDesktopObjectOkToClose(&Parameters);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ExpWindowStationOkToClose( IN PEPROCESS Process OPTIONAL,
|
||||
IN PVOID Object,
|
||||
IN HANDLE Handle,
|
||||
IN KPROCESSOR_MODE AccessMode)
|
||||
{
|
||||
WIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters;
|
||||
|
||||
Parameters.Process = Process;
|
||||
Parameters.Object = Object;
|
||||
Parameters.Handle = Handle;
|
||||
Parameters.PreviousMode = AccessMode;
|
||||
|
||||
return ExpWindowStationObjectOkToClose(&Parameters);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
ExpWinStaObjectDelete(PVOID DeletedObject)
|
||||
|
@ -114,6 +150,7 @@ ExpWin32kInit(VOID)
|
|||
ObjectTypeInitializer.PoolType = NonPagedPool;
|
||||
ObjectTypeInitializer.DeleteProcedure = ExpWinStaObjectDelete;
|
||||
ObjectTypeInitializer.ParseProcedure = ExpWinStaObjectParse;
|
||||
ObjectTypeInitializer.OkayToCloseProcedure = ExpWindowStationOkToClose;
|
||||
ObCreateObjectType(&Name,
|
||||
&ObjectTypeInitializer,
|
||||
NULL,
|
||||
|
@ -124,6 +161,7 @@ ExpWin32kInit(VOID)
|
|||
ObjectTypeInitializer.GenericMapping = ExpDesktopMapping;
|
||||
ObjectTypeInitializer.DeleteProcedure = ExpDesktopDelete;
|
||||
ObjectTypeInitializer.ParseProcedure = NULL;
|
||||
ObjectTypeInitializer.OkayToCloseProcedure = ExpDesktopOkToClose;
|
||||
ObCreateObjectType(&Name,
|
||||
&ObjectTypeInitializer,
|
||||
NULL,
|
||||
|
|
|
@ -1752,7 +1752,6 @@ ObpCloseHandle(IN HANDLE Handle,
|
|||
|
||||
/* Detach and return success */
|
||||
if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -20,6 +20,8 @@ PKWIN32_THREAD_CALLOUT PspW32ThreadCallout = NULL;
|
|||
PGDI_BATCHFLUSH_ROUTINE KeGdiFlushUserBatch = NULL;
|
||||
extern PKWIN32_PARSEMETHOD_CALLOUT ExpWindowStationObjectParse;
|
||||
extern PKWIN32_DELETEMETHOD_CALLOUT ExpWindowStationObjectDelete;
|
||||
extern PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExpWindowStationObjectOkToClose;
|
||||
extern PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExpDesktopObjectOkToClose;
|
||||
extern PKWIN32_DELETEMETHOD_CALLOUT ExpDesktopObjectDelete;
|
||||
extern PKWIN32_POWEREVENT_CALLOUT PopEventCallout;
|
||||
|
||||
|
@ -116,6 +118,8 @@ PsEstablishWin32Callouts(IN PWIN32_CALLOUTS_FPNS CalloutData)
|
|||
PspW32ThreadCallout = CalloutData->ThreadCallout;
|
||||
ExpWindowStationObjectParse = CalloutData->WindowStationParseProcedure;
|
||||
ExpWindowStationObjectDelete = CalloutData->WindowStationDeleteProcedure;
|
||||
ExpWindowStationObjectOkToClose = CalloutData->WindowStationOkToCloseProcedure;
|
||||
ExpDesktopObjectOkToClose = CalloutData->DesktopOkToCloseProcedure;
|
||||
ExpDesktopObjectDelete = CalloutData->DesktopDeleteProcedure;
|
||||
PopEventCallout = CalloutData->PowerEventCallout;
|
||||
KeGdiFlushUserBatch = CalloutData->BatchFlushRoutine;
|
||||
|
|
|
@ -69,6 +69,9 @@ IntDesktopObjectParse(IN PVOID ParseObject,
|
|||
VOID APIENTRY
|
||||
IntDesktopObjectDelete(PWIN32_DELETEMETHOD_PARAMETERS Parameters);
|
||||
|
||||
NTSTATUS NTAPI
|
||||
IntDesktopOkToClose(PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters);
|
||||
|
||||
LRESULT CALLBACK
|
||||
IntDesktopWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
|
|
|
@ -166,6 +166,7 @@ typedef struct _PROCESSINFO
|
|||
PCLS pclsPrivateList;
|
||||
PCLS pclsPublicList;
|
||||
INT cThreads;
|
||||
HDESK hdeskStartup;
|
||||
DWORD dwhmodLibLoadedMask;
|
||||
HANDLE ahmodLibLoaded[CLIBS];
|
||||
struct _WINSTATION_OBJECT *prpwinsta;
|
||||
|
|
|
@ -82,6 +82,9 @@ NTSTATUS
|
|||
APIENTRY
|
||||
IntWinStaObjectParse(PWIN32_PARSEMETHOD_PARAMETERS Parameters);
|
||||
|
||||
NTSTATUS NTAPI
|
||||
IntWinstaOkToClose(PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters);
|
||||
|
||||
NTSTATUS FASTCALL
|
||||
IntValidateWindowStationHandle(
|
||||
HWINSTA WindowStation,
|
||||
|
@ -106,4 +109,7 @@ IntGetFullWindowStationName(
|
|||
|
||||
PWINSTATION_OBJECT FASTCALL IntGetWinStaObj(VOID);
|
||||
|
||||
BOOL FASTCALL
|
||||
UserSetProcessWindowStation(HWINSTA hWindowStation);
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -119,6 +119,7 @@ Win32kProcessCallback(struct _EPROCESS *Process,
|
|||
{
|
||||
DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql());
|
||||
Win32Process->W32PF_flags |= W32PF_TERMINATED;
|
||||
|
||||
if (Win32Process->InputIdleEvent)
|
||||
{
|
||||
EngFreeMem((PVOID)Win32Process->InputIdleEvent);
|
||||
|
@ -144,6 +145,9 @@ Win32kProcessCallback(struct _EPROCESS *Process,
|
|||
{
|
||||
LogonProcess = NULL;
|
||||
}
|
||||
|
||||
UserSetProcessWindowStation(NULL);
|
||||
|
||||
}
|
||||
|
||||
RETURN( STATUS_SUCCESS);
|
||||
|
@ -220,25 +224,14 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
|
|||
{
|
||||
if(hWinSta != NULL)
|
||||
{
|
||||
if(Process != CsrProcess)
|
||||
if(!UserSetProcessWindowStation(hWinSta))
|
||||
{
|
||||
HWINSTA hProcessWinSta = (HWINSTA)InterlockedCompareExchangePointer((PVOID)&Process->Win32WindowStation, (PVOID)hWinSta, NULL);
|
||||
if(hProcessWinSta != NULL)
|
||||
{
|
||||
/* our process is already assigned to a different window station, we don't need the handle anymore */
|
||||
NtClose(hWinSta);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NtClose(hWinSta);
|
||||
DPRINT1("Failed to set process window station\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (hDesk != NULL)
|
||||
{
|
||||
Win32Thread->rpdesk = NULL;
|
||||
Win32Thread->hdesk = NULL;
|
||||
if (!IntSetThreadDesktop(hDesk, FALSE))
|
||||
{
|
||||
DPRINT1("Unable to set thread desktop\n");
|
||||
|
@ -441,6 +434,8 @@ DriverEntry(
|
|||
CalloutData.ProcessCallout = Win32kProcessCallback;
|
||||
CalloutData.ThreadCallout = Win32kThreadCallback;
|
||||
CalloutData.BatchFlushRoutine = NtGdiFlushUserBatch;
|
||||
CalloutData.DesktopOkToCloseProcedure = IntDesktopOkToClose;
|
||||
CalloutData.WindowStationOkToCloseProcedure = IntWinstaOkToClose;
|
||||
|
||||
/* Register our per-process and per-thread structures. */
|
||||
PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS)&CalloutData);
|
||||
|
|
|
@ -168,6 +168,29 @@ IntDesktopObjectDelete(PWIN32_DELETEMETHOD_PARAMETERS Parameters)
|
|||
IntFreeDesktopHeap(Desktop);
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
IntDesktopOkToClose(PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters)
|
||||
{
|
||||
PTHREADINFO pti;
|
||||
|
||||
pti = PsGetCurrentThreadWin32Thread();
|
||||
|
||||
if( pti == NULL)
|
||||
{
|
||||
/* This happens when we leak desktop handles */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Do not allow the current desktop or the initial desktop to be closed */
|
||||
if( Parameters->Handle == pti->ppi->hdeskStartup ||
|
||||
Parameters->Handle == pti->hdesk)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
INIT_FUNCTION
|
||||
|
|
|
@ -187,6 +187,21 @@ IntWinStaObjectParse(PWIN32_PARSEMETHOD_PARAMETERS Parameters)
|
|||
return STATUS_OBJECT_TYPE_MISMATCH;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
IntWinstaOkToClose(PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters)
|
||||
{
|
||||
PPROCESSINFO ppi;
|
||||
|
||||
ppi = PsGetCurrentProcessWin32Process();
|
||||
|
||||
if(Parameters->Handle == ppi->hwinsta)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
/*
|
||||
|
@ -915,6 +930,57 @@ IntGetWinStaObj(VOID)
|
|||
return WinStaObj;
|
||||
}
|
||||
|
||||
BOOL FASTCALL
|
||||
UserSetProcessWindowStation(HWINSTA hWindowStation)
|
||||
{
|
||||
PPROCESSINFO ppi;
|
||||
NTSTATUS Status;
|
||||
HWINSTA hwinstaOld;
|
||||
PWINSTATION_OBJECT NewWinSta = NULL, OldWinSta;
|
||||
|
||||
ppi = PsGetCurrentProcessWin32Process();
|
||||
|
||||
if(hWindowStation !=NULL)
|
||||
{
|
||||
Status = IntValidateWindowStationHandle( hWindowStation,
|
||||
KernelMode,
|
||||
0,
|
||||
&NewWinSta);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Validation of window station handle (0x%X) failed\n",
|
||||
hWindowStation);
|
||||
SetLastNtError(Status);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
OldWinSta = ppi->prpwinsta;
|
||||
hwinstaOld = ppi->hwinsta;
|
||||
|
||||
/*
|
||||
* FIXME - don't allow changing the window station if there are threads that are attached to desktops and own gui objects
|
||||
*/
|
||||
|
||||
InterlockedExchangePointer(&PsGetCurrentProcess()->Win32WindowStation, hWindowStation);
|
||||
|
||||
ppi->prpwinsta = NewWinSta;
|
||||
ppi->hwinsta = hWindowStation;
|
||||
|
||||
|
||||
if(OldWinSta != NULL)
|
||||
{
|
||||
ObDereferenceObject(OldWinSta);
|
||||
}
|
||||
|
||||
if(hwinstaOld != NULL)
|
||||
{
|
||||
ZwClose(hwinstaOld);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* NtUserSetProcessWindowStation
|
||||
*
|
||||
|
@ -934,44 +1000,15 @@ IntGetWinStaObj(VOID)
|
|||
BOOL APIENTRY
|
||||
NtUserSetProcessWindowStation(HWINSTA hWindowStation)
|
||||
{
|
||||
PWINSTATION_OBJECT NewWinSta;
|
||||
NTSTATUS Status;
|
||||
BOOL ret;
|
||||
|
||||
DPRINT("About to set process window station with handle (0x%X)\n",
|
||||
hWindowStation);
|
||||
UserEnterExclusive();
|
||||
|
||||
if(PsGetCurrentProcess() == CsrProcess)
|
||||
{
|
||||
DPRINT1("CSRSS is not allowed to change it's window station!!!\n");
|
||||
EngSetLastError(ERROR_ACCESS_DENIED);
|
||||
return FALSE;
|
||||
}
|
||||
ret = UserSetProcessWindowStation(hWindowStation);
|
||||
|
||||
Status = IntValidateWindowStationHandle(
|
||||
hWindowStation,
|
||||
KernelMode,
|
||||
0,
|
||||
&NewWinSta);
|
||||
UserLeave();
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Validation of window station handle (0x%X) failed\n",
|
||||
hWindowStation);
|
||||
SetLastNtError(Status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME - don't allow changing the window station if there are threads that are attached to desktops and own gui objects
|
||||
*/
|
||||
|
||||
/* FIXME - dereference the old window station, etc... */
|
||||
InterlockedExchangePointer(&PsGetCurrentProcess()->Win32WindowStation, hWindowStation);
|
||||
|
||||
DPRINT("PsGetCurrentProcess()->Win32WindowStation 0x%X\n",
|
||||
PsGetCurrentProcess()->Win32WindowStation);
|
||||
|
||||
return TRUE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue