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.
 
 
 
 
 
 

702 lines
18 KiB

/**************************** Module Header ********************************\
* Module Name: ex.c
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* Executive support routines
*
* History:
* 03-04-95 JimA Created.
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
NTSTATUS
OpenEffectiveToken(
PHANDLE phToken)
{
NTSTATUS Status;
/*
* Open the client's token.
*/
Status = ZwOpenThreadTokenEx(
NtCurrentThread(),
TOKEN_QUERY,
(BOOLEAN)TRUE, // OpenAsSelf
OBJ_KERNEL_HANDLE,
phToken);
if (Status == STATUS_NO_TOKEN) {
/*
* Client wasn't impersonating anyone. Open its process token.
*/
Status = ZwOpenProcessTokenEx(
NtCurrentProcess(),
TOKEN_QUERY,
OBJ_KERNEL_HANDLE,
phToken);
}
if (!NT_SUCCESS(Status)) {
RIPMSG1(RIP_WARNING, "Can't open client's token! - Status = %lx", Status);
}
return Status;
}
NTSTATUS
GetProcessLuid(
PETHREAD Thread,
PLUID LuidProcess
)
{
PACCESS_TOKEN UserToken = NULL;
BOOLEAN fCopyOnOpen;
BOOLEAN fEffectiveOnly;
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
NTSTATUS Status;
if (Thread == NULL)
Thread = PsGetCurrentThread();
//
// Check for a thread token first
//
UserToken = PsReferenceImpersonationToken(Thread,
&fCopyOnOpen, &fEffectiveOnly, &ImpersonationLevel);
if (UserToken == NULL) {
//
// No thread token, go to the process
//
UserToken = PsReferencePrimaryToken(PsGetThreadProcess(Thread));
if (UserToken == NULL)
return STATUS_NO_TOKEN;
}
Status = SeQueryAuthenticationIdToken(UserToken, LuidProcess);
//
// We're finished with the token
//
ObDereferenceObject(UserToken);
return Status;
}
BOOLEAN IsRestricted(
PETHREAD Thread)
{
PACCESS_TOKEN UserToken;
BOOLEAN fCopyOnOpen;
BOOLEAN fEffectiveOnly;
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
BOOLEAN fRestricted = FALSE;
/*
* Check for a thread token first.
*/
UserToken = PsReferenceImpersonationToken(Thread,
&fCopyOnOpen, &fEffectiveOnly, &ImpersonationLevel);
/*
* If no thread token, go to the process.
*/
if (UserToken == NULL) {
UserToken = PsReferencePrimaryToken(PsGetThreadProcess(Thread));
}
/*
* If we got a token, is it restricted?
*/
if (UserToken != NULL) {
fRestricted = SeTokenIsRestricted(UserToken);
ObDereferenceObject(UserToken);
}
return fRestricted;
}
NTSTATUS InitSystemThread(
PUNICODE_STRING pstrThreadName)
{
PETHREAD pEThread;
PEPROCESS Process;
PTHREADINFO pti;
NTSTATUS Status = STATUS_SUCCESS;
CheckCritOut();
pEThread = PsGetCurrentThread();
Process = PsGetThreadProcess(pEThread);
ValidateThreadSessionId(pEThread);
/*
* check to see if process is already set, if not, we
* need to set it up as well
*/
UserAssert(PsGetProcessWin32Process(Process));
EnterCrit();
/*
* Flag this as a system thread
*/
pti = PtiCurrentShared();
/*
* This is a CSRSS thread and we want to just convert it to a system thread,
* Then changes the TIF flags and allocate a kernel side pClientInfo.
*/
UserAssert((pti->TIF_flags & TIF_CSRSSTHREAD) && !(pti->TIF_flags & TIF_SYSTEMTHREAD));
#if DBG
try {
UserAssert(pti->pClientInfo == ((PCLIENTINFO)((NtCurrentTeb())->Win32ClientInfo)));
} except (W32ExceptionHandler(FALSE, RIP_WARNING)) {
}
#endif
pti->pClientInfo = UserAllocPoolWithQuota(sizeof(CLIENTINFO),
TAG_CLIENTTHREADINFO);
if (pti->pClientInfo == NULL) {
LeaveCrit();
return STATUS_NO_MEMORY;
}
pti->TIF_flags &= ~TIF_CSRSSTHREAD;
pti->TIF_flags |= TIF_SYSTEMTHREAD;
INITCLIENTINFO(pti);
if (pstrThreadName) {
if (pti->pstrAppName != NULL)
UserFreePool(pti->pstrAppName);
pti->pstrAppName = UserAllocPoolWithQuota(sizeof(UNICODE_STRING) +
pstrThreadName->Length + sizeof(WCHAR), TAG_TEXT);
if (pti->pstrAppName != NULL) {
pti->pstrAppName->Buffer = (PWCHAR)(pti->pstrAppName + 1);
RtlCopyMemory(pti->pstrAppName->Buffer, pstrThreadName->Buffer,
pstrThreadName->Length);
pti->pstrAppName->Buffer[pstrThreadName->Length / sizeof(WCHAR)] = 0;
pti->pstrAppName->MaximumLength = pstrThreadName->Length + sizeof(WCHAR);
pti->pstrAppName->Length = pstrThreadName->Length;
}
}
/*
* Need to clear the W32PF_APPSTARTING bit so that windows created by
* the RIT don't cause the cursor to change to the app starting cursor.
*/
if (pti->ppi != NULL && (pti->ppi->W32PF_Flags & W32PF_APPSTARTING)) {
ClearAppStarting(pti->ppi);
}
Error:
LeaveCrit();
return Status;
}
NTSTATUS CommitReadOnlyMemory(
HANDLE hSection,
PSIZE_T pCommitSize,
DWORD dwCommitOffset,
int* pdCommit)
{
SIZE_T ulViewSize;
LARGE_INTEGER liOffset;
PEPROCESS Process;
PVOID pUserBase, pvt;
NTSTATUS Status;
ulViewSize = 0;
pUserBase = NULL;
liOffset.QuadPart = 0;
Process = PsGetCurrentProcess();
Status = MmMapViewOfSection(
hSection,
Process,
&pUserBase,
0,
PAGE_SIZE,
&liOffset,
&ulViewSize,
ViewUnmap,
SEC_NO_CHANGE,
PAGE_EXECUTE_READ);
if (NT_SUCCESS(Status)) {
/*
* Commit the memory
*/
pUserBase = pvt = (PVOID)((PBYTE)pUserBase + dwCommitOffset);
Status = ZwAllocateVirtualMemory(
NtCurrentProcess(),
&pUserBase,
0,
pCommitSize,
MEM_COMMIT,
PAGE_EXECUTE_READ);
if (pdCommit) {
*pdCommit = (int)((PBYTE)pUserBase - (PBYTE)pvt);
} else {
UserAssert(pvt == pUserBase);
}
MmUnmapViewOfSection(Process, pUserBase);
}
return Status;
}
/***************************************************************************\
* CreateKernelEvent
*
* Creates a kernel event. This is used when reference counted events
* created by ZwCreateEvent are not needed.
*
* History:
* 06-26-95 JimA Created.
\***************************************************************************/
PKEVENT CreateKernelEvent(
IN EVENT_TYPE Type,
IN BOOLEAN State)
{
PKEVENT pEvent;
pEvent = UserAllocPoolNonPagedNS(sizeof(KEVENT), TAG_SYSTEM);
if (pEvent != NULL) {
KeInitializeEvent(pEvent, Type, State);
}
return pEvent;
}
/***************************************************************************\
* LockObjectAssignment
*
* References an object into a data structure
*
* History:
* 06-26-95 JimA Created.
\***************************************************************************/
VOID LockObjectAssignment(
PVOID *pplock,
PVOID pobject
#ifdef LOGDESKTOPLOCKS
,DWORD tag,
ULONG_PTR extra
#endif
)
{
PVOID pobjectOld;
/*
* Save old object to dereference AFTER the new object is referenced.
* This will avoid problems with relocking the same object.
*/
pobjectOld = *pplock;
/*
* Reference the new object.
*/
if (pobject != NULL) {
ObReferenceObject(pobject);
#ifdef LOGDESKTOPLOCKS
if (OBJECT_TO_OBJECT_HEADER(pobject)->Type == *ExDesktopObjectType) {
LogDesktop(pobject, tag, TRUE, extra);
}
#endif
}
*pplock = pobject;
/*
* Dereference the old object.
*/
if (pobjectOld != NULL) {
#ifdef LOGDESKTOPLOCKS
if (OBJECT_TO_OBJECT_HEADER(pobjectOld)->Type == *ExDesktopObjectType) {
LogDesktop(pobjectOld, tag, FALSE, extra);
}
#endif
ObDereferenceObject(pobjectOld);
}
}
/***************************************************************************\
* UnlockObjectAssignment
*
* Dereferences an object locked into a data structure
*
* History:
* 06-26-95 JimA Created.
\***************************************************************************/
VOID UnlockObjectAssignment(
PVOID *pplock
#ifdef LOGDESKTOPLOCKS
,DWORD tag,
ULONG_PTR extra
#endif
)
{
if (*pplock != NULL) {
PVOID plock = *pplock;
#ifdef LOGDESKTOPLOCKS
if (OBJECT_TO_OBJECT_HEADER(*pplock)->Type == *ExDesktopObjectType) {
LogDesktop(*pplock, tag, FALSE, extra);
}
#endif
*pplock = NULL;
ObDereferenceObject(plock);
}
}
/***************************************************************************\
* UserDereferenceObject
*
* We need this for thread locking stuff since ObDereferenceObject is a macro.
*
* 09-21-98 JerrySh Created.
\***************************************************************************/
VOID UserDereferenceObject(
PVOID pobj)
{
ObDereferenceObject(pobj);
}
/***************************************************************************\
* ProtectHandle
*
* This api is used set and clear close protection on handles used
* by the kernel.
*
* 08-18-95 JimA Created.
\***************************************************************************/
NTSTATUS ProtectHandle(
IN HANDLE Handle,
IN POBJECT_TYPE pObjectType,
IN BOOLEAN Protect)
{
OBJECT_HANDLE_INFORMATION HandleInfo;
OBJECT_HANDLE_FLAG_INFORMATION HandleFlagInfo;
NTSTATUS Status;
PVOID pObject = NULL;
Status = ObReferenceObjectByHandle(
Handle,
EVENT_ALL_ACCESS,
pObjectType,
UserMode,
&pObject,
&HandleInfo);
if (NT_SUCCESS(Status)) {
HandleFlagInfo.Inherit = (HandleInfo.HandleAttributes & OBJ_INHERIT) ? TRUE : FALSE;
HandleFlagInfo.ProtectFromClose = Protect;
Status = ObSetHandleAttributes(
Handle,
&HandleFlagInfo,
UserMode);
}
if (pObject) {
ObDereferenceObject(pObject);
}
return Status;
}
#ifdef LOGDESKTOPLOCKS
#define LOG_DELTA 8
PLogD GrowLogIfNecessary(
PDESKTOP pdesk)
{
if (pdesk->nLogCrt < pdesk->nLogMax) {
UserAssert(pdesk->pLog != NULL);
return pdesk->pLog;
}
/*
* Grow the buffer
*/
if (pdesk->pLog == NULL) {
UserAssert(pdesk->nLogMax == 0 && pdesk->nLogCrt == 0);
pdesk->pLog = (PLogD)UserAllocPool(LOG_DELTA * sizeof(LogD), TAG_LOGDESKTOP);
} else {
pdesk->pLog = (PLogD)UserReAllocPool(pdesk->pLog,
pdesk->nLogCrt * sizeof(LogD),
(pdesk->nLogCrt + LOG_DELTA) * sizeof(LogD),
TAG_LOGDESKTOP);
}
UserAssert(pdesk->pLog != NULL);
pdesk->nLogMax += LOG_DELTA;
return pdesk->pLog;
}
/***************************************************************************\
* LogDesktop
*
* Log the lock/unlock calls for desktop objects
*
* Dec-2-97 clupu Created.
\***************************************************************************/
VOID LogDesktop(
PDESKTOP pdesk,
DWORD tag,
BOOL bLock,
ULONG_PTR extra)
{
DWORD tag1 = 0, tag2 = 0;
PLogD pLog;
if (pdesk == NULL) {
return;
}
/*
* The tag stored in LogD structure is actually a WORD.
*/
UserAssert(HIWORD(tag) == 0);
if (bLock) {
(pdesk->nLockCount)++;
growAndAdd:
/*
* grow the table if necessary and add the new
* lock/unlock information to it
*/
pLog = GrowLogIfNecessary(pdesk);
pLog += pdesk->nLogCrt;
pLog->tag = (WORD)tag;
pLog->type = (WORD)bLock;
pLog->extra = extra;
RtlZeroMemory(pLog->trace, 6 * sizeof(PVOID));
RtlWalkFrameChain(pLog->trace, 6, 0);
(pdesk->nLogCrt)++;
return;
}
/*
* It's an unlock.
* First search for a matching lock
*/
UserAssert(pdesk->nLockCount > 0);
switch (tag) {
case LDU_CLS_DESKPARENT1:
tag1 = LDL_CLS_DESKPARENT1;
break;
case LDU_CLS_DESKPARENT2:
tag1 = LDL_CLS_DESKPARENT1;
tag2 = LDL_CLS_DESKPARENT2;
break;
case LDU_FN_DESTROYCLASS:
tag1 = LDL_FN_DESTROYCLASS;
break;
case LDU_FN_DESTROYMENU:
tag1 = LDL_FN_DESTROYMENU;
break;
case LDU_FN_DESTROYTHREADINFO:
tag1 = LDL_FN_DESTROYTHREADINFO;
break;
case LDU_FN_DESTROYWINDOWSTATION:
tag1 = LDL_FN_DESTROYWINDOWSTATION;
break;
case LDU_DESKDISCONNECT:
tag1 = LDL_DESKDISCONNECT;
break;
case LDU_DESK_DESKNEXT:
tag1 = LDL_DESK_DESKNEXT1;
break;
case LDU_OBJ_DESK:
tag1 = LDL_OBJ_DESK;
tag2 = LDL_MOTHERDESK_DESK1;
break;
case LDL_PTI_DESK:
tag1 = LDL_PTI_DESK;
tag2 = LDL_DT_DESK;
break;
case LDU_PTI_DESK:
tag1 = LDL_PTI_DESK;
break;
case LDU_PPI_DESKSTARTUP1:
case LDU_PPI_DESKSTARTUP2:
case LDU_PPI_DESKSTARTUP3:
tag1 = LDL_PPI_DESKSTARTUP1;
tag2 = LDL_PPI_DESKSTARTUP2;
break;
case LDU_DESKLOGON:
tag1 = LDL_DESKLOGON;
break;
case LDUT_FN_FREEWINDOW:
tag1 = LDLT_FN_FREEWINDOW;
break;
case LDUT_FN_DESKTOPTHREAD_DESK:
tag1 = LDLT_FN_DESKTOPTHREAD_DESK;
break;
case LDUT_FN_DESKTOPTHREAD_DESKTEMP:
tag1 = LDLT_FN_DESKTOPTHREAD_DESKTEMP;
break;
case LDUT_FN_SETDESKTOP:
tag1 = LDLT_FN_SETDESKTOP;
break;
case LDUT_FN_NTUSERSWITCHDESKTOP:
tag1 = LDLT_FN_NTUSERSWITCHDESKTOP;
break;
case LDUT_FN_SENDMESSAGEBSM1:
case LDUT_FN_SENDMESSAGEBSM2:
tag1 = LDLT_FN_SENDMESSAGEBSM;
break;
case LDUT_FN_SYSTEMBROADCASTMESSAGE:
tag1 = LDLT_FN_SYSTEMBROADCASTMESSAGE;
break;
case LDUT_FN_CTXREDRAWSCREEN:
tag1 = LDLT_FN_CTXREDRAWSCREEN;
break;
case LDUT_FN_CTXDISABLESCREEN:
tag1 = LDLT_FN_CTXDISABLESCREEN;
break;
case LD_DEREF_FN_CREATEDESKTOP1:
case LD_DEREF_FN_CREATEDESKTOP2:
case LD_DEREF_FN_CREATEDESKTOP3:
tag1 = LD_REF_FN_CREATEDESKTOP;
break;
case LD_DEREF_FN_OPENDESKTOP:
tag1 = LD_REF_FN_OPENDESKTOP;
break;
case LD_DEREF_FN_SETDESKTOP:
tag1 = LD_REF_FN_SETDESKTOP;
break;
case LD_DEREF_FN_GETTHREADDESKTOP:
tag1 = LD_REF_FN_GETTHREADDESKTOP;
break;
case LD_DEREF_FN_CLOSEDESKTOP1:
case LD_DEREF_FN_CLOSEDESKTOP2:
tag1 = LD_REF_FN_CLOSEDESKTOP;
break;
case LD_DEREF_FN_RESOLVEDESKTOP:
tag1 = LD_REF_FN_RESOLVEDESKTOP;
break;
case LD_DEREF_VALIDATE_HDESK1:
case LD_DEREF_VALIDATE_HDESK2:
case LD_DEREF_VALIDATE_HDESK3:
case LD_DEREF_VALIDATE_HDESK4:
tag1 = LDL_VALIDATE_HDESK;
break;
case LDUT_FN_CREATETHREADINFO1:
case LDUT_FN_CREATETHREADINFO2:
tag1 = LDLT_FN_CREATETHREADINFO;
break;
case LD_DEREF_FN_SETCSRSSTHREADDESKTOP1:
case LD_DEREF_FN_SETCSRSSTHREADDESKTOP2:
tag1 = LD_REF_FN_SETCSRSSTHREADDESKTOP;
break;
case LD_DEREF_FN_CONSOLECONTROL1:
tag1 = LD_REF_FN_CONSOLECONTROL1;
break;
case LD_DEREF_FN_CONSOLECONTROL2:
tag1 = LD_REF_FN_CONSOLECONTROL2;
break;
case LD_DEREF_FN_GETUSEROBJECTINFORMATION:
tag1 = LD_REF_FN_GETUSEROBJECTINFORMATION;
break;
case LD_DEREF_FN_SETUSEROBJECTINFORMATION:
tag1 = LD_REF_FN_SETUSEROBJECTINFORMATION;
break;
case LD_DEREF_FN_CREATEWINDOWSTATION:
tag1 = LD_REF_FN_CREATEWINDOWSTATION;
break;
case LDL_TERM_DESKDESTROY1:
tag1 = LDL_TERM_DESKDESTROY2;
break;
case LDL_MOTHERDESK_DESK1:
tag1 = LDL_MOTHERDESK_DESK1;
tag2 = LDL_MOTHERDESK_DESK2;
break;
case LDL_WINSTA_DESKLIST2:
tag1 = LDL_WINSTA_DESKLIST1;
break;
case LDL_DESKRITINPUT:
case LDU_DESKRITINPUT:
tag1 = LDL_DESKRITINPUT;
break;
}
if (tag1 != 0) {
int ind;
/*
* this is an unlock we know about. Let's find the
* matching lock in the table. We start searching
* the table backwords.
*/
for (ind = pdesk->nLogCrt - 1; ind >= 0; ind--) {
pLog = pdesk->pLog + ind;
if (pLog->type == 1 &&
(pLog->tag == tag1 || pLog->tag == tag2) &&
pLog->extra == extra) {
/*
* match found. remove the lock
*/
RtlMoveMemory(pdesk->pLog + ind,
pdesk->pLog + ind + 1,
(pdesk->nLogCrt - ind - 1) * sizeof(LogD));
(pdesk->nLogCrt)--;
(pdesk->nLockCount)--;
if (pdesk->nLockCount == 0) {
RIPMSG1(RIP_VERBOSE, "Lock count 0 for pdesk %#p\n", pdesk);
}
return;
}
}
/*
* We didn't find the matching lock and we were supposed to.
* Just add it to the table and we'll look at it.
*/
RIPMSG3(RIP_WARNING, "Didn't find matching lock for pdesk %#p tag %d extra %lx\n",
pdesk, tag, extra);
}
(pdesk->nLockCount)--;
goto growAndAdd;
}
#endif