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
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
|