Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

908 lines
28 KiB

/**************************** Module Header ********************************\
* Module Name: security.c
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* Securable Object Routines
*
* History:
* 12-31-90 JimA Created.
* 04-14-92 RichardW Changed ACE_HEADER
\***************************************************************************/
#define _SECURITY 1
#include "precomp.h"
#pragma hdrstop
#pragma alloc_text(INIT, InitSecurity)
/*
* General security stuff
*/
PSECURITY_DESCRIPTOR gpsdInitWinSta;
PRIVILEGE_SET psTcb = { 1, PRIVILEGE_SET_ALL_NECESSARY,
{ SE_TCB_PRIVILEGE, 0 }
};
/***************************************************************************\
* AllocAce
*
* Allocates and initializes an ACE list.
*
* History:
* 04-25-91 JimA Created.
\***************************************************************************/
PACCESS_ALLOWED_ACE AllocAce(
PACCESS_ALLOWED_ACE pace,
BYTE bType,
BYTE bFlags,
ACCESS_MASK am,
PSID psid,
LPDWORD lpdwLength)
{
PACCESS_ALLOWED_ACE paceNew;
DWORD iEnd;
DWORD dwLength, dwLengthSid;
/*
* Allocate space for the ACE.
*/
dwLengthSid = RtlLengthSid(psid);
dwLength = dwLengthSid + sizeof(ACE_HEADER) + sizeof(ACCESS_MASK);
if (pace == NULL) {
iEnd = 0;
pace = UserAllocPoolWithQuota(dwLength, TAG_SECURITY);
if (pace == NULL)
return NULL;
} else {
iEnd = *lpdwLength;
paceNew = UserAllocPoolWithQuota(iEnd + dwLength, TAG_SECURITY);
if (paceNew == NULL)
return NULL;
RtlCopyMemory(paceNew, pace, iEnd);
UserFreePool(pace);
pace = paceNew;
}
*lpdwLength = dwLength + iEnd;
/*
* Insert the new ACE.
*/
paceNew = (PACCESS_ALLOWED_ACE)((PBYTE)pace + iEnd);
paceNew->Header.AceType = bType;
paceNew->Header.AceSize = (USHORT)dwLength;
paceNew->Header.AceFlags = bFlags;
paceNew->Mask = am;
RtlCopySid(dwLengthSid, &paceNew->SidStart, psid);
return pace;
}
/***************************************************************************\
* CreateSecurityDescriptor
*
* Allocates and initializes a security descriptor.
*
* History:
* 04-25-91 JimA Created.
\***************************************************************************/
PSECURITY_DESCRIPTOR CreateSecurityDescriptor(
PACCESS_ALLOWED_ACE paceList,
DWORD cbAce,
BOOLEAN fDaclDefaulted)
{
PSECURITY_DESCRIPTOR psd;
PACL pacl;
NTSTATUS Status;
/*
* Allocate the security descriptor
*/
psd = (PSECURITY_DESCRIPTOR)UserAllocPoolWithQuota(
cbAce + sizeof(ACL) + SECURITY_DESCRIPTOR_MIN_LENGTH,
TAG_SECURITY);
if (psd == NULL)
return NULL;
RtlCreateSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION);
/*
* Initialize the ACL
*/
pacl = (PACL)((PBYTE)psd + SECURITY_DESCRIPTOR_MIN_LENGTH);
Status = RtlCreateAcl(pacl, sizeof(ACL) + cbAce, ACL_REVISION);
if (NT_SUCCESS(Status)) {
/*
* Add the ACEs to the ACL.
*/
Status = RtlAddAce(pacl, ACL_REVISION, MAXULONG, paceList, cbAce);
if (NT_SUCCESS(Status)) {
/*
* Initialize the SD
*/
Status = RtlSetDaclSecurityDescriptor(psd, (BOOLEAN)TRUE,
pacl, fDaclDefaulted);
RtlSetSaclSecurityDescriptor(psd, (BOOLEAN)FALSE, NULL,
(BOOLEAN)FALSE);
RtlSetOwnerSecurityDescriptor(psd, NULL, (BOOLEAN)FALSE);
RtlSetGroupSecurityDescriptor(psd, NULL, (BOOLEAN)FALSE);
}
}
if (!NT_SUCCESS(Status)) {
UserFreePool(psd);
return NULL;
}
return psd;
}
/***************************************************************************\
* InitSecurity
*
* Initialize global security information.
*
* History:
* 01-29-91 JimA Created.
\***************************************************************************/
BOOL InitSecurity(
VOID)
{
PACCESS_ALLOWED_ACE paceList = NULL, pace;
DWORD dwLength;
/*
* Create ACE list.
*/
paceList = AllocAce(NULL,
ACCESS_ALLOWED_ACE_TYPE,
CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | NO_PROPAGATE_INHERIT_ACE,
WinStaMapping.GenericAll,
SeExports->SeWorldSid,
&dwLength);
if (paceList == NULL)
return FALSE;
pace = AllocAce(paceList,
ACCESS_ALLOWED_ACE_TYPE,
CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE | NO_PROPAGATE_INHERIT_ACE,
WinStaMapping.GenericAll,
SeExports->SeRestrictedSid,
&dwLength);
if (pace == NULL) {
UserFreePool(paceList);
return FALSE;
}
paceList = pace;
pace = AllocAce(paceList, ACCESS_ALLOWED_ACE_TYPE,
OBJECT_INHERIT_ACE | INHERIT_ONLY_ACE,
GENERIC_ALL, SeExports->SeWorldSid, &dwLength);
if (pace == NULL) {
UserFreePool(paceList);
return FALSE;
}
paceList = pace;
pace = AllocAce(paceList, ACCESS_ALLOWED_ACE_TYPE,
OBJECT_INHERIT_ACE | INHERIT_ONLY_ACE,
GENERIC_ALL, SeExports->SeRestrictedSid, &dwLength);
if (pace == NULL) {
UserFreePool(paceList);
return FALSE;
}
paceList = pace;
pace = AllocAce(paceList, ACCESS_ALLOWED_ACE_TYPE,
0, DIRECTORY_QUERY | DIRECTORY_CREATE_OBJECT,
SeExports->SeAliasAdminsSid, &dwLength);
if (pace == NULL) {
UserFreePool(paceList);
return FALSE;
}
paceList = pace;
pace = AllocAce(paceList, ACCESS_ALLOWED_ACE_TYPE,
0, DIRECTORY_TRAVERSE, SeExports->SeWorldSid, &dwLength);
if (pace == NULL) {
UserFreePool(paceList);
return FALSE;
}
paceList = pace;
pace = AllocAce(paceList, ACCESS_ALLOWED_ACE_TYPE,
0, DIRECTORY_TRAVERSE, SeExports->SeRestrictedSid, &dwLength);
if (pace == NULL) {
UserFreePool(paceList);
return FALSE;
}
paceList = pace;
/*
* Create the SD
*/
gpsdInitWinSta = CreateSecurityDescriptor(paceList, dwLength, FALSE);
UserFreePool(paceList);
if (gpsdInitWinSta == NULL) {
RIPMSG0(RIP_WARNING, "Initial windowstation security was not created!");
}
return (BOOL)(gpsdInitWinSta != NULL);
}
/***************************************************************************\
* TestForInteractiveUser
*
* Returns STATUS_SUCCESS if the LUID passed represents an
* interactiveUser user logged on by winlogon, otherwise FALSE
*
* History:
* 03-08-95 JimA Created.
\***************************************************************************/
NTSTATUS
TestForInteractiveUser(
PLUID pluidCaller
)
{
PWINDOWSTATION pwinsta;
UserAssert(grpWinStaList != NULL);
/*
* !!!
*
* This relies on the fact that there is only ONE interactive
* windowstation and that it is the first one in the list.
* If multiple windowstations are ever supported
* a lookup will have to be done here.
*/
pwinsta = grpWinStaList;
/*
* Compare it with the id of the logged on user.
*/
if (RtlEqualLuid(pluidCaller, &pwinsta->luidUser))
return STATUS_SUCCESS;
else
return STATUS_ACCESS_DENIED;
}
/***************************************************************************\
* _UserTestForWinStaAccess
*
* Returns STATUS_SUCCESS if the current user has GENERIC_EXECUTE access on
* WindowStation pstrWinSta
*
*
* History:
* 06-05-96 Created SalimC
* 01-02-02 Modified Mohamed Changed pstrWinSta to be a kernel mode address
* and later copied to a dynamically allocated
* user mode address.
\***************************************************************************/
NTSTATUS
_UserTestForWinStaAccess(
PUNICODE_STRING pstrWinSta,
BOOL fInherit
)
{
PTOKEN_STATISTICS pStats;
ULONG BytesRequired;
PWINDOWSTATION pwinsta;
HWINSTA hwsta = NULL;
POBJECT_ATTRIBUTES pObjAttr = NULL;
PUNICODE_STRING pstrStatic;
NTSTATUS Status = STATUS_SUCCESS;
SIZE_T cbObjA;
UNICODE_STRING strDefWinSta;
HANDLE htoken;
BOOLEAN fDefWinSta;
CheckCritIn();
/*
* If we are testing against Default WindowStation (WinSta0) retreive
* pwinsta from the top of the grpwinstaList instead of doing an
* _OpenWindowStation.
*
* NOTE: This relies on the fact that there is only ONE interactive
* windowstation and that it is the first one in the list. If multiple
* windowstations are ever supported a lookup will have to be done
* instead.
*/
RtlInitUnicodeString(&strDefWinSta, DEFAULT_WINSTA);
fDefWinSta = RtlEqualUnicodeString(pstrWinSta, &strDefWinSta, TRUE);
if (fDefWinSta) {
if (!NT_SUCCESS(Status = OpenEffectiveToken(&htoken))) {
return Status;
}
Status = ZwQueryInformationToken(htoken,
TokenStatistics,
NULL,
0,
&BytesRequired);
if (Status != STATUS_BUFFER_TOO_SMALL) {
ZwClose(htoken);
return Status;
}
//
// Allocate space for the user info
//
pStats = (PTOKEN_STATISTICS)UserAllocPoolWithQuota(BytesRequired, TAG_SECURITY);
if (pStats == NULL) {
Status = STATUS_NO_MEMORY;
ZwClose(htoken);
return Status;
}
//
// Read in the user info
//
Status = ZwQueryInformationToken(htoken,
TokenStatistics,
pStats,
BytesRequired,
&BytesRequired);
if (!NT_SUCCESS(Status)) {
ZwClose(htoken);
UserFreePool(pStats);
return Status;
}
/*
* Make sure that current process has access to this window station
*/
Status = STATUS_ACCESS_DENIED;
if (grpWinStaList != NULL) {
/*
* !!!
*
* This relies on the fact that there is only ONE interactive
* windowstation and that it is the first one in the list.
* If multiple windowstations are ever supported
* a lookup will have to be done here.
*/
pwinsta = grpWinStaList;
/*
* For now we will just do the user luid test till we figure out
* what fInherit means for a Multi-User system
*/
if (fInherit) {
if ( (RtlEqualLuid(&pStats->AuthenticationId, &pwinsta->luidUser)) ||
(RtlEqualLuid(&pStats->AuthenticationId, &luidSystem)) ||
(AccessCheckObject(pwinsta, GENERIC_EXECUTE, UserMode, &WinStaMapping)) ) {
Status = STATUS_SUCCESS;
}
} else {
/* Bug 42905. Service Controller clears the flag
* ScStartupInfo.dwFlags &= (~STARTF_DESKTOPINHERIT) to make services
* running under the context of system non-interactive. Hence if fInherit
* is false don't do the SystemLuid and AccessCheckObject tests.
*/
if (RtlEqualLuid(&pStats->AuthenticationId, &pwinsta->luidUser)) {
Status = STATUS_SUCCESS;
}
}
}
ZwClose(htoken);
UserFreePool(pStats);
return Status;
}
/*
* Since we don't have a pointer to the WindowStation Object we will do
* a _OpenWindowStation() to make sure we have the desired access.
*/
cbObjA = sizeof(*pObjAttr) + sizeof(*pstrStatic) + STATIC_UNICODE_BUFFER_LENGTH * sizeof(WCHAR);
Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
&pObjAttr, 0, &cbObjA, MEM_COMMIT, PAGE_READWRITE);
pstrStatic = (PUNICODE_STRING)((PBYTE)pObjAttr + sizeof(*pObjAttr));
if (NT_SUCCESS(Status)) {
/*
* Note -- the string must be in client-space or the address
* validation in _OpenWindowStation will fail.
*/
try {
pstrStatic->Length = 0;
pstrStatic->MaximumLength = STATIC_UNICODE_BUFFER_LENGTH * sizeof(WCHAR);
pstrStatic->Buffer = (PWSTR)((PBYTE)pstrStatic + sizeof(*pstrStatic));
RtlCopyUnicodeString(pstrStatic, pstrWinSta);
InitializeObjectAttributes(pObjAttr,
pstrStatic,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
Status = GetExceptionCode();
}
if (NT_SUCCESS(Status)) {
/*
* In order to be able to verify access rights, we will pass
* UserMode for KPROCESSOR_MODE. Passing KernelMode would bypass
* all security checks. As a side-effect, hwsta is created
* as a UserMode handle and is not a trusted/protected handle.
*/
hwsta = _OpenWindowStation(pObjAttr, GENERIC_EXECUTE, UserMode);
}
} else {
return Status;
}
if (pObjAttr != NULL) {
ZwFreeVirtualMemory(NtCurrentProcess(), &pObjAttr, &cbObjA, MEM_RELEASE);
}
if (!hwsta) {
return STATUS_ACCESS_DENIED;
}
Status = ObCloseHandle(hwsta, UserMode);
UserAssert(NT_SUCCESS(Status));
return Status;
}
/***************************************************************************\
* CheckGrantedAccess
*
* Confirms all requested accesses are granted and sets error status.
*
* History:
* 06-26-95 JimA Created.
\***************************************************************************/
BOOL CheckGrantedAccess(
ACCESS_MASK amGranted,
ACCESS_MASK amRequest)
{
/*
* Check the granted access.
*/
if (!RtlAreAllAccessesGranted(amGranted, amRequest)) {
RIPERR0(ERROR_ACCESS_DENIED, RIP_VERBOSE, "");
return FALSE;
}
return TRUE;
}
/***************************************************************************\
* CheckWinstaWriteAttributesAccess
*
* Checks if the current process has WINSTA_WRITEATTRIBUTES access
* to its windowstation, and whether that windowstation is an
* interactive windowstation.
*
* History:
* 06-Jun-1996 adams Created.
\***************************************************************************/
BOOL CheckWinstaWriteAttributesAccess(
VOID)
{
PPROCESSINFO ppiCurrent = PpiCurrent();
/*
* winlogon has rights to all windowstations.
*/
if (PsGetCurrentProcessId() == gpidLogon)
return TRUE;
if (!(ppiCurrent->W32PF_Flags & W32PF_IOWINSTA)) {
RIPERR0(ERROR_REQUIRES_INTERACTIVE_WINDOWSTATION,
RIP_WARNING,
"Operation invalid on a non-interactive WindowStation.");
return FALSE;
}
if (!RtlAreAllAccessesGranted(ppiCurrent->amwinsta, WINSTA_WRITEATTRIBUTES)) {
RIPERR0(ERROR_ACCESS_DENIED,
RIP_WARNING,
"WINSTA_WRITEATTRIBUTES access to WindowStation denied.");
return FALSE;
}
return TRUE;
}
/***************************************************************************\
* AccessCheckObject
*
* Performs an access check on an object
*
* History:
* 12-31-90 JimA Created.
\***************************************************************************/
BOOL AccessCheckObject(
PVOID pobj,
ACCESS_MASK amRequest,
KPROCESSOR_MODE AccessMode,
CONST GENERIC_MAPPING *pGenericMapping)
{
NTSTATUS Status;
ACCESS_STATE AccessState;
BOOLEAN fAccessGranted;
AUX_ACCESS_DATA AuxData;
BOOLEAN bMutexLocked = (pGenericMapping == (&KeyMapping));
/*
* Due to a resource problem in the object manager, we must pass in a TRUE
* when checking access for registry keys, even if we do not explicitly have
* the object type mutex. If we do not, we can get into a deadlock situation with this mutex
* and the CmpRegistry lock.
*/
SeCreateAccessState(&AccessState, &AuxData, amRequest, (PGENERIC_MAPPING)pGenericMapping);
fAccessGranted = ObCheckObjectAccess(
pobj,
&AccessState,
bMutexLocked,
AccessMode,
&Status);
SeDeleteAccessState(&AccessState);
return (BOOL)(fAccessGranted == TRUE);
}
/***************************************************************************\
* IsPrivileged
*
* Check to see if the client has the specified privileges
*
* History:
* 01-02-91 JimA Created.
\***************************************************************************/
BOOL IsPrivileged(
PPRIVILEGE_SET ppSet)
{
SECURITY_SUBJECT_CONTEXT Context;
BOOLEAN bHeld;
SeCaptureSubjectContext(&Context);
SeLockSubjectContext(&Context);
bHeld = SePrivilegeCheck(ppSet, &Context, UserMode);
SePrivilegeObjectAuditAlarm(NULL, &Context, 0, ppSet, bHeld, UserMode);
SeUnlockSubjectContext(&Context);
SeReleaseSubjectContext(&Context);
if (!bHeld)
RIPERR0(ERROR_PRIVILEGE_NOT_HELD, RIP_VERBOSE, "");
/*
* Return result of privilege check
*/
return (BOOL)bHeld;
}
/***************************************************************************\
* _GetUserObjectInformation (API)
*
* Gets information about a secure USER object
*
* History:
* 04-25-94 JimA Created.
\***************************************************************************/
BOOL _GetUserObjectInformation(
HANDLE h,
int nIndex,
PVOID ccxpvInfo,
DWORD nLength,
LPDWORD lpnLengthNeeded)
{
PUSEROBJECTFLAGS puof;
BOOL fSuccess = TRUE;
PVOID pObject;
POBJECT_HEADER pHead;
DWORD dwLengthNeeded = 0;
OBJECT_HANDLE_INFORMATION ohi;
PUNICODE_STRING pstrInfo;
PWINDOWSTATION pwinsta;
NTSTATUS Status;
ACCESS_MASK amDesiredAccess = 0;
/*
* Validate the object and get a pointer with whatever
* access is granted.
*/
Status = ObReferenceObjectByHandle(
h,
0,
NULL,
UserMode,
&pObject,
NULL);
if (!NT_SUCCESS(Status)) {
RIPNTERR0(Status, RIP_VERBOSE, "ObReferenceObjectByHandle Failed");
return FALSE;
}
/*
* Determine the correct access mask given the object type.
*/
pHead = OBJECT_TO_OBJECT_HEADER(pObject);
if (pHead->Type == *ExWindowStationObjectType) {
amDesiredAccess = WINSTA_READATTRIBUTES;
} else if (pHead->Type == *ExDesktopObjectType) {
amDesiredAccess = DESKTOP_READOBJECTS;
}
ObDereferenceObject(pObject);
if (!amDesiredAccess) {
RIPERR0(ERROR_INVALID_FUNCTION, RIP_WARNING, "Object is not a USER object");
return FALSE;
}
/*
* Re-open the object with the proper access.
*/
Status = ObReferenceObjectByHandle(
h,
amDesiredAccess,
NULL,
UserMode,
&pObject,
&ohi);
if (!NT_SUCCESS(Status)) {
RIPNTERR0(Status, RIP_VERBOSE, "ObReferenceObjectByHandle Failed");
return FALSE;
}
#ifdef LOGDESKTOPLOCKS
if (OBJECT_TO_OBJECT_HEADER(pObject)->Type == *ExDesktopObjectType) {
LogDesktop(pObject, LD_REF_FN_GETUSEROBJECTINFORMATION, TRUE, (ULONG_PTR)PtiCurrentShared());
}
#endif
try {
switch (nIndex) {
case UOI_FLAGS:
dwLengthNeeded = sizeof(USEROBJECTFLAGS);
if (nLength < sizeof(USEROBJECTFLAGS)) {
RIPERR0(ERROR_INSUFFICIENT_BUFFER, RIP_VERBOSE, "");
fSuccess = FALSE;
break;
}
puof = ccxpvInfo;
puof->fInherit = (ohi.HandleAttributes & OBJ_INHERIT) ? TRUE : FALSE;
puof->fReserved = 0;
puof->dwFlags = 0;
if (pHead->Type == *ExDesktopObjectType) {
if (CheckHandleFlag(NULL, ((PDESKTOP)pObject)->dwSessionId, h, HF_DESKTOPHOOK)) {
puof->dwFlags |= DF_ALLOWOTHERACCOUNTHOOK;
}
} else {
if (!(((PWINDOWSTATION)pObject)->dwWSF_Flags & WSF_NOIO))
puof->dwFlags |= WSF_VISIBLE;
}
break;
case UOI_NAME:
pstrInfo = POBJECT_NAME(pObject);
goto docopy;
case UOI_TYPE:
pstrInfo = &pHead->Type->Name;
docopy:
if (pstrInfo) {
dwLengthNeeded = pstrInfo->Length + sizeof(WCHAR);
if (dwLengthNeeded > nLength) {
RIPERR0(ERROR_INSUFFICIENT_BUFFER, RIP_VERBOSE, "");
fSuccess = FALSE;
break;
}
RtlCopyMemory(ccxpvInfo, pstrInfo->Buffer, pstrInfo->Length);
*(PWCHAR)((PBYTE)ccxpvInfo + pstrInfo->Length) = 0;
} else {
dwLengthNeeded = 0;
}
break;
case UOI_USER_SID:
if (pHead->Type == *ExWindowStationObjectType)
pwinsta = pObject;
else
pwinsta = ((PDESKTOP)pObject)->rpwinstaParent;
if (pwinsta->psidUser == NULL) {
dwLengthNeeded = 0;
} else {
dwLengthNeeded = RtlLengthSid(pwinsta->psidUser);
if (dwLengthNeeded > nLength) {
RIPERR0(ERROR_INSUFFICIENT_BUFFER, RIP_VERBOSE, "");
fSuccess = FALSE;
break;
}
RtlCopyMemory(ccxpvInfo, pwinsta->psidUser, dwLengthNeeded);
}
break;
default:
RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, "");
fSuccess = FALSE;
break;
}
} except (W32ExceptionHandler(TRUE, RIP_WARNING)) {
fSuccess = FALSE;
}
*lpnLengthNeeded = dwLengthNeeded;
#ifdef LOGDESKTOPLOCKS
if (OBJECT_TO_OBJECT_HEADER(pObject)->Type == *ExDesktopObjectType) {
LogDesktop(pObject, LD_DEREF_FN_GETUSEROBJECTINFORMATION, FALSE, (ULONG_PTR)PtiCurrentShared());
}
#endif
ObDereferenceObject(pObject);
return fSuccess;
}
/***************************************************************************\
* _SetUserObjectInformation (API)
*
* Sets information about a secure USER object
*
* History:
* 04-25-94 JimA Created.
\***************************************************************************/
BOOL _SetUserObjectInformation(
HANDLE h,
int nIndex,
PVOID ccxpvInfo,
DWORD nLength)
{
PUSEROBJECTFLAGS puof;
BOOL fSuccess = TRUE;
PVOID pObject;
POBJECT_HEADER pHead;
DWORD dwLengthNeeded = 0;
OBJECT_HANDLE_INFORMATION ohi;
OBJECT_HANDLE_FLAG_INFORMATION ofi;
NTSTATUS Status;
ACCESS_MASK amDesiredAccess = 0;
/*
* Validate the object and get a pointer with whatever
* access is granted.
*/
Status = ObReferenceObjectByHandle(
h,
0,
NULL,
UserMode,
&pObject,
NULL);
if (!NT_SUCCESS(Status)) {
RIPNTERR0(Status, RIP_VERBOSE, "ObReferenceObjectByHandle Failed");
return FALSE;
}
/*
* Determine the correct access mask given the object type.
*/
pHead = OBJECT_TO_OBJECT_HEADER(pObject);
if (pHead->Type == *ExWindowStationObjectType) {
amDesiredAccess = WINSTA_WRITEATTRIBUTES;
} else if (pHead->Type == *ExDesktopObjectType) {
amDesiredAccess = DESKTOP_WRITEOBJECTS;
}
ObDereferenceObject(pObject);
if (!amDesiredAccess) {
RIPERR0(ERROR_INVALID_FUNCTION, RIP_WARNING, "Object is not a USER object");
return FALSE;
}
/*
* Re-open the object with the proper access.
*/
Status = ObReferenceObjectByHandle(
h,
amDesiredAccess,
NULL,
UserMode,
&pObject,
&ohi);
if (!NT_SUCCESS(Status)) {
RIPNTERR0(Status, RIP_VERBOSE, "ObReferenceObjectByHandle Failed");
return FALSE;
}
#ifdef LOGDESKTOPLOCKS
if (OBJECT_TO_OBJECT_HEADER(pObject)->Type == *ExDesktopObjectType) {
LogDesktop(pObject, LD_REF_FN_SETUSEROBJECTINFORMATION, TRUE, (ULONG_PTR)PtiCurrent());
}
#endif
try {
switch (nIndex) {
case UOI_FLAGS:
if (nLength < sizeof(USEROBJECTFLAGS)) {
RIPERR0(ERROR_INVALID_DATA, RIP_VERBOSE, "");
fSuccess = FALSE;
break;
}
puof = ccxpvInfo;
ofi.Inherit = (puof->fInherit != FALSE);
ofi.ProtectFromClose = (ohi.HandleAttributes & OBJ_PROTECT_CLOSE) ? TRUE : FALSE;
ObSetHandleAttributes(h, &ofi, UserMode);
if (pHead->Type == *ExDesktopObjectType) {
SetHandleFlag(h, HF_DESKTOPHOOK,
puof->dwFlags & DF_ALLOWOTHERACCOUNTHOOK);
}
break;
default:
RIPERR0(ERROR_INVALID_PARAMETER, RIP_VERBOSE, "");
fSuccess = FALSE;
break;
}
} except (W32ExceptionHandler(TRUE, RIP_WARNING)) {
fSuccess = FALSE;
}
#ifdef LOGDESKTOPLOCKS
if (OBJECT_TO_OBJECT_HEADER(pObject)->Type == *ExDesktopObjectType) {
LogDesktop(pObject, LD_DEREF_FN_SETUSEROBJECTINFORMATION, FALSE, (ULONG_PTR)PtiCurrent());
}
#endif
ObDereferenceObject(pObject);
return fSuccess;
}
/***************************************************************************\
* UserScreenAccessCheck
*
* Called from the engine to determine if the thread's desktop is
* active and the process has WINSTA_READSCREEN access.
*
* Note that we may or may not be in USER's critical section when this
* is called. This is OK as long as we don't reference thing belonging
* to other threads. If we did try to enter the critical section here,
* a deadlock may occur between the engine and user.
*
* History:
* 05-20-1993 JimA Created.
* 11-22-1996 BradG Brought back to life.
* 05-07-2001 JasonSch CSRSS threads aren't always attached to a desktop,
* but they need to draw anyway (for console).
\***************************************************************************/
BOOL FASTCALL UserScreenAccessCheck(VOID)
{
PTHREADINFO ptiCurrent = PtiCurrentShared();
UserAssert(ptiCurrent != NULL);
return (ptiCurrent != NULL &&
(ptiCurrent->rpdesk == grpdeskRitInput || (ptiCurrent->TIF_flags & TIF_CSRSSTHREAD) != 0) &&
(W32GetCurrentProcess()->W32PF_Flags & (W32PF_READSCREENACCESSGRANTED | W32PF_IOWINSTA)) == (W32PF_READSCREENACCESSGRANTED | W32PF_IOWINSTA)
);
}