windows-nt/Source/XPSP1/NT/base/ntos/ex/win32.c

664 lines
17 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
win32.c
Abstract:
This module implements the definition of the executive Win32 objects.
Functions to manage these objects are implemented in win32k.sys.
Author:
James I. Anderson (jima) 14-June-1995
Environment:
Kernel mode only.
Revision History:
--*/
#include "exp.h"
//
// Address of windowstation and desktop object type descriptors.
//
POBJECT_TYPE ExWindowStationObjectType;
POBJECT_TYPE ExDesktopObjectType;
PKWIN32_CLOSEMETHOD_CALLOUT ExDesktopCloseProcedureCallout;
PKWIN32_CLOSEMETHOD_CALLOUT ExWindowStationCloseProcedureCallout;
PKWIN32_OPENMETHOD_CALLOUT ExDesktopOpenProcedureCallout;
PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExDesktopOkToCloseProcedureCallout;
PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExWindowStationOkToCloseProcedureCallout;
PKWIN32_DELETEMETHOD_CALLOUT ExDesktopDeleteProcedureCallout;
PKWIN32_DELETEMETHOD_CALLOUT ExWindowStationDeleteProcedureCallout;
PKWIN32_PARSEMETHOD_CALLOUT ExWindowStationParseProcedureCallout;
PKWIN32_OPENMETHOD_CALLOUT ExWindowStationOpenProcedureCallout;
//
// common types for above win32 callouts and parameters
//
typedef PVOID PKWIN32_CALLOUT_PARAMETERS;
typedef
NTSTATUS
(*PKWIN32_CALLOUT) (
IN PKWIN32_CALLOUT_PARAMETERS
);
NTSTATUS
ExpWin32SessionCallout(
IN PKWIN32_CALLOUT CalloutRoutine,
IN PKWIN32_CALLOUT_PARAMETERS Parameters,
IN ULONG SessionId,
OUT PNTSTATUS CalloutStatus OPTIONAL
);
VOID
ExpWin32CloseProcedure(
IN PEPROCESS Process OPTIONAL,
IN PVOID Object,
IN ACCESS_MASK GrantedAccess,
IN ULONG ProcessHandleCount,
IN ULONG SystemHandleCount );
BOOLEAN
ExpWin32OkayToCloseProcedure(
IN PEPROCESS Process OPTIONAL,
IN PVOID Object,
IN HANDLE Handle,
IN KPROCESSOR_MODE PreviousMode
);
VOID
ExpWin32DeleteProcedure(
IN PVOID Object
);
NTSTATUS
ExpWin32ParseProcedure (
IN PVOID ParseObject,
IN PVOID ObjectType,
IN OUT PACCESS_STATE AccessState,
IN KPROCESSOR_MODE AccessMode,
IN ULONG Attributes,
IN OUT PUNICODE_STRING CompleteName,
IN OUT PUNICODE_STRING RemainingName,
IN OUT PVOID Context OPTIONAL,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
OUT PVOID *Object
);
NTSTATUS
ExpWin32OpenProcedure(
IN OB_OPEN_REASON OpenReason,
IN PEPROCESS Process OPTIONAL,
IN PVOID Object,
IN ACCESS_MASK GrantedAccess,
IN ULONG HandleCount
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text (INIT, ExpWin32Initialization)
#pragma alloc_text (PAGE, ExpWin32CloseProcedure)
#pragma alloc_text (PAGE, ExpWin32OkayToCloseProcedure)
#pragma alloc_text (PAGE, ExpWin32DeleteProcedure)
#pragma alloc_text (PAGE, ExpWin32OpenProcedure)
#pragma alloc_text (PAGE, ExpWin32ParseProcedure)
#pragma alloc_text (PAGE, ExpWin32SessionCallout)
#endif
/*
* windowstation generic mapping
*/
#ifdef ALLOC_DATA_PRAGMA
#pragma const_seg("INITCONST")
#endif
const GENERIC_MAPPING ExpWindowStationMapping = {
STANDARD_RIGHTS_READ,
STANDARD_RIGHTS_WRITE,
STANDARD_RIGHTS_EXECUTE,
STANDARD_RIGHTS_REQUIRED
};
/*
* desktop generic mapping
*/
const GENERIC_MAPPING ExpDesktopMapping = {
STANDARD_RIGHTS_READ,
STANDARD_RIGHTS_WRITE,
STANDARD_RIGHTS_EXECUTE,
STANDARD_RIGHTS_REQUIRED
};
#ifdef ALLOC_DATA_PRAGMA
#pragma const_seg()
#endif
/*++
Routine Description:
Close Procedure for Win32k windostation and desktop objects
Arguments:
Defined by OB_CLOSE_METHOD
Return Value:
--*/
VOID ExpWin32CloseProcedure(
IN PEPROCESS Process OPTIONAL,
IN PVOID Object,
IN ACCESS_MASK GrantedAccess,
IN ULONG ProcessHandleCount,
IN ULONG SystemHandleCount )
{
//
// SessionId is the first field in the Win32k Object structure
//
ULONG SessionId = *((PULONG)Object);
WIN32_CLOSEMETHOD_PARAMETERS CloseParams;
NTSTATUS Status;
CloseParams.Process = Process;
CloseParams.Object = Object;
CloseParams.GrantedAccess = GrantedAccess;
CloseParams.ProcessHandleCount = ProcessHandleCount;
CloseParams.SystemHandleCount = SystemHandleCount;
if ((OBJECT_TO_OBJECT_HEADER(Object)->Type) == ExDesktopObjectType) {
Status = ExpWin32SessionCallout((PKWIN32_CALLOUT)ExDesktopCloseProcedureCallout,
(PKWIN32_CALLOUT_PARAMETERS)&CloseParams,
SessionId,
NULL);
ASSERT(NT_SUCCESS(Status));
} else if ((OBJECT_TO_OBJECT_HEADER(Object)->Type) == ExWindowStationObjectType) {
Status = ExpWin32SessionCallout((PKWIN32_CALLOUT)ExWindowStationCloseProcedureCallout,
(PKWIN32_CALLOUT_PARAMETERS)&CloseParams,
SessionId,
NULL);
ASSERT(NT_SUCCESS(Status));
} else {
ASSERT((OBJECT_TO_OBJECT_HEADER(Object)->Type) == ExDesktopObjectType || (OBJECT_TO_OBJECT_HEADER(Object)->Type == ExWindowStationObjectType));
}
}
/*++
Routine Description:
OkayToClose Procedure for Win32k windostation and desktop objects
Arguments:
Defined by OB_OKAYTOCLOSE_METHOD
Return Value:
--*/
BOOLEAN ExpWin32OkayToCloseProcedure(
IN PEPROCESS Process OPTIONAL,
IN PVOID Object,
IN HANDLE Handle,
IN KPROCESSOR_MODE PreviousMode
)
{
//
// SessionId is the first field in the Win32k Object structure
//
ULONG SessionId = *((PULONG)Object);
WIN32_OKAYTOCLOSEMETHOD_PARAMETERS OKToCloseParams;
NTSTATUS Status, CallStatus = STATUS_UNSUCCESSFUL;
OKToCloseParams.Process = Process;
OKToCloseParams.Object = Object;
OKToCloseParams.Handle = Handle;
OKToCloseParams.PreviousMode = PreviousMode;
if (OBJECT_TO_OBJECT_HEADER(Object)->Type == ExDesktopObjectType) {
Status = ExpWin32SessionCallout((PKWIN32_CALLOUT)ExDesktopOkToCloseProcedureCallout,
(PKWIN32_CALLOUT_PARAMETERS)&OKToCloseParams,
SessionId,
&CallStatus);
ASSERT(NT_SUCCESS(Status));
} else if (OBJECT_TO_OBJECT_HEADER(Object)->Type == ExWindowStationObjectType) {
Status = ExpWin32SessionCallout((PKWIN32_CALLOUT)ExWindowStationOkToCloseProcedureCallout,
(PKWIN32_CALLOUT_PARAMETERS)&OKToCloseParams,
SessionId,
&CallStatus);
ASSERT(NT_SUCCESS(Status));
} else {
ASSERT(OBJECT_TO_OBJECT_HEADER(Object)->Type == ExDesktopObjectType ||
OBJECT_TO_OBJECT_HEADER(Object)->Type == ExWindowStationObjectType);
}
return (BOOLEAN)(NT_SUCCESS(CallStatus));
}
/*++
Routine Description:
Delete Procedure for Win32k windostation and desktop objects
Arguments:
Defined by OB_DELETE_METHOD
Return Value:
--*/
VOID ExpWin32DeleteProcedure(
IN PVOID Object
)
{
//
// SessionId is the first field in the Win32k Object structure
//
ULONG SessionId = *((PULONG)Object);
WIN32_DELETEMETHOD_PARAMETERS DeleteParams;
NTSTATUS Status;
DeleteParams.Object = Object;
if (OBJECT_TO_OBJECT_HEADER(Object)->Type == ExDesktopObjectType) {
Status = ExpWin32SessionCallout((PKWIN32_CALLOUT)ExDesktopDeleteProcedureCallout,
(PKWIN32_CALLOUT_PARAMETERS)&DeleteParams,
SessionId,
NULL);
ASSERT(NT_SUCCESS(Status));
} else if (OBJECT_TO_OBJECT_HEADER(Object)->Type == ExWindowStationObjectType) {
Status = ExpWin32SessionCallout((PKWIN32_CALLOUT)ExWindowStationDeleteProcedureCallout,
(PKWIN32_CALLOUT_PARAMETERS)&DeleteParams,
SessionId,
NULL);
ASSERT(NT_SUCCESS(Status));
} else {
ASSERT(OBJECT_TO_OBJECT_HEADER(Object)->Type == ExDesktopObjectType ||
OBJECT_TO_OBJECT_HEADER(Object)->Type == ExWindowStationObjectType);
}
}
/*++
Routine Description:
Open Procedure for Win32k desktop objects
Arguments:
Defined by OB_OPEN_METHOD
Return Value:
--*/
NTSTATUS
ExpWin32OpenProcedure(
IN OB_OPEN_REASON OpenReason,
IN PEPROCESS Process OPTIONAL,
IN PVOID Object,
IN ACCESS_MASK GrantedAccess,
IN ULONG HandleCount
)
{
//
// SessionId is the first field in the Win32k Object structure
//
ULONG SessionId = *((PULONG)Object);
WIN32_OPENMETHOD_PARAMETERS OpenParams;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
OpenParams.OpenReason = OpenReason;
OpenParams.Process = Process;
OpenParams.Object = Object;
OpenParams.GrantedAccess = GrantedAccess;
OpenParams.HandleCount = HandleCount;
if ((OBJECT_TO_OBJECT_HEADER(Object)->Type) == ExDesktopObjectType) {
Status = ExpWin32SessionCallout((PKWIN32_CALLOUT)ExDesktopOpenProcedureCallout,
(PKWIN32_CALLOUT_PARAMETERS)&OpenParams,
SessionId,
NULL);
ASSERT(NT_SUCCESS(Status));
} else if ((OBJECT_TO_OBJECT_HEADER(Object)->Type) == ExWindowStationObjectType) {
Status = ExpWin32SessionCallout((PKWIN32_CALLOUT)ExWindowStationOpenProcedureCallout,
(PKWIN32_CALLOUT_PARAMETERS)&OpenParams,
SessionId,
NULL);
ASSERT(NT_SUCCESS(Status));
} else {
ASSERT((OBJECT_TO_OBJECT_HEADER(Object)->Type) == ExDesktopObjectType || (OBJECT_TO_OBJECT_HEADER(Object)->Type == ExWindowStationObjectType));
}
return Status;
}
/*++
Routine Description:
Parse Procedure for Win32k windostation objects
Arguments:
Defined by OB_PARSE_METHOD
Return Value:
--*/
NTSTATUS ExpWin32ParseProcedure (
IN PVOID ParseObject,
IN PVOID ObjectType,
IN OUT PACCESS_STATE AccessState,
IN KPROCESSOR_MODE AccessMode,
IN ULONG Attributes,
IN OUT PUNICODE_STRING CompleteName,
IN OUT PUNICODE_STRING RemainingName,
IN OUT PVOID Context OPTIONAL,
IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
OUT PVOID *Object
)
{
//
// SessionId is the first field in the Win32k Object structure
//
ULONG SessionId = *((PULONG)ParseObject);
WIN32_PARSEMETHOD_PARAMETERS ParseParams;
NTSTATUS Status, CallStatus = STATUS_UNSUCCESSFUL;
ParseParams.ParseObject = ParseObject;
ParseParams.ObjectType = ObjectType;
ParseParams.AccessState = AccessState;
ParseParams.AccessMode = AccessMode;
ParseParams.Attributes = Attributes;
ParseParams.CompleteName = CompleteName;
ParseParams.RemainingName = RemainingName;
ParseParams.Context = Context;
ParseParams.SecurityQos = SecurityQos;
ParseParams.Object = Object;
//
// Parse Procedure is only provided for WindowStation objects
//
Status = ExpWin32SessionCallout((PKWIN32_CALLOUT)ExWindowStationParseProcedureCallout,
(PKWIN32_CALLOUT_PARAMETERS)&ParseParams,
SessionId,
&CallStatus);
ASSERT(NT_SUCCESS(Status));
return CallStatus;
}
BOOLEAN
ExpWin32Initialization (
)
/*++
Routine Description:
This function creates the Win32 object type descriptors at system
initialization and stores the address of the object type descriptor
in local static storage.
Arguments:
None.
Return Value:
A value of TRUE is returned if the Win32 object type descriptors are
successfully created. Otherwise a value of FALSE is returned.
--*/
{
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
NTSTATUS Status;
UNICODE_STRING TypeName;
//
// Initialize string descriptor.
//
RtlInitUnicodeString(&TypeName, L"WindowStation");
//
// Create windowstation object type descriptor.
//
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
ObjectTypeInitializer.GenericMapping = ExpWindowStationMapping;
ObjectTypeInitializer.SecurityRequired = TRUE;
ObjectTypeInitializer.PoolType = NonPagedPool;
ObjectTypeInitializer.CloseProcedure = ExpWin32CloseProcedure;
ObjectTypeInitializer.DeleteProcedure = ExpWin32DeleteProcedure;
ObjectTypeInitializer.OkayToCloseProcedure = ExpWin32OkayToCloseProcedure;
ObjectTypeInitializer.ParseProcedure = ExpWin32ParseProcedure;
ObjectTypeInitializer.OpenProcedure = ExpWin32OpenProcedure;
ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK |
OBJ_PERMANENT |
OBJ_EXCLUSIVE;
ObjectTypeInitializer.ValidAccessMask = STANDARD_RIGHTS_REQUIRED;
Status = ObCreateObjectType(&TypeName,
&ObjectTypeInitializer,
(PSECURITY_DESCRIPTOR)NULL,
&ExWindowStationObjectType);
//
// If the windowstation object type descriptor was not successfully
// created, then return a value of FALSE.
//
if (!NT_SUCCESS(Status))
return FALSE;
//
// Initialize string descriptor.
//
RtlInitUnicodeString(&TypeName, L"Desktop");
ObjectTypeInitializer.ParseProcedure = NULL; //Desktop has no Parse Procedure
//
// Create windowstation object type descriptor.
//
ObjectTypeInitializer.GenericMapping = ExpDesktopMapping;
Status = ObCreateObjectType(&TypeName,
&ObjectTypeInitializer,
(PSECURITY_DESCRIPTOR)NULL,
&ExDesktopObjectType);
//
// If the desktop object type descriptor was successfully created, then
// return a value of TRUE. Otherwise return a value of FALSE.
//
return (BOOLEAN)(NT_SUCCESS(Status));
}
NTSTATUS
ExpWin32SessionCallout(
IN PKWIN32_CALLOUT CalloutRoutine,
IN PKWIN32_CALLOUT_PARAMETERS Parameters,
IN ULONG SessionId,
OUT PNTSTATUS CalloutStatus OPTIONAL
)
/*++
Routine Description:
This routine calls the specified callout routine in session space, for the
specified session.
Parameters:
CalloutRoutine - Callout routine in session space.
Parameters - Parameters to pass the callout routine.
SessionId - Specifies the ID of the session in which the specified
callout routine is to be called.
CalloutStatus - Optionally, supplies the address of a variable to receive
the NTSTATUS code returned by the callout routine.
Return Value:
Status code that indicates whether or not the function was successful.
Notes:
Returns STATUS_NOT_FOUND if the specified session was not found.
--*/
{
NTSTATUS Status, CallStatus;
PVOID OpaqueSession;
KAPC_STATE ApcState;
PAGED_CODE();
//
// Make sure we have all the information we need to deliver notification.
//
if (CalloutRoutine == NULL) {
return STATUS_INVALID_PARAMETER;
}
//
// Make sure the callout routine in session space.
//
ASSERT(MmIsSessionAddress((PVOID)CalloutRoutine));
if ((PsGetCurrentProcess()->Flags & PS_PROCESS_FLAGS_IN_SESSION) &&
(SessionId == PsGetCurrentProcessSessionId())) {
//
// If the call is from a user mode process, and we are asked to call the
// current session, call directly.
//
CallStatus = (CalloutRoutine)(Parameters);
//
// Return the callout status.
//
if (ARGUMENT_PRESENT(CalloutStatus)) {
*CalloutStatus = CallStatus;
}
Status = STATUS_SUCCESS;
} else {
//
// Reference the session object for the specified session.
//
OpaqueSession = MmGetSessionById(SessionId);
if (OpaqueSession == NULL) {
return STATUS_NOT_FOUND;
}
//
// Attach to the specified session.
//
Status = MmAttachSession(OpaqueSession, &ApcState);
if (!NT_SUCCESS(Status)) {
KdPrintEx((DPFLTR_SYSTEM_ID, DPFLTR_WARNING_LEVEL,
"ExpWin32SessionCallout: "
"could not attach to 0x%p, session %d for registered notification callout @ 0x%p\n",
OpaqueSession,
SessionId,
CalloutRoutine));
MmQuitNextSession(OpaqueSession);
return Status;
}
//
// Dispatch notification to the callout routine.
//
CallStatus = (CalloutRoutine)(Parameters);
//
// Return the callout status.
//
if (ARGUMENT_PRESENT(CalloutStatus)) {
*CalloutStatus = CallStatus;
}
//
// Detach from the session.
//
Status = MmDetachSession(OpaqueSession, &ApcState);
ASSERT(NT_SUCCESS(Status));
//
// Dereference the session object.
//
Status = MmQuitNextSession(OpaqueSession);
ASSERT(NT_SUCCESS(Status));
}
return Status;
}