WindowsXP-SP1/termsrv/drivers/termdd/misc.c
2020-09-30 16:53:49 +02:00

322 lines
8.7 KiB
C

/****************************************************************************/
// misc.c
//
// Miscellaneous TermDD routines.
//
// Copyright (C) 1998-2000 Microsoft Corporation
/****************************************************************************/
#include <precomp.h>
#pragma hdrstop
#if DBG
LIST_ENTRY IcaGlobalPoolListHead;
ULONG IcaTotalAllocations = 0;
ULONG IcaTotalFrees = 0;
ULONG IcaTotalBytesAllocated = 0;
KSPIN_LOCK IcaDebugSpinLock;
typedef struct _ICA_POOL_HEADER {
LIST_ENTRY GlobalPoolListEntry;
PCHAR FileName;
ULONG LineNumber;
ULONG Size;
ULONG InUse;
} ICA_POOL_HEADER, *PICA_POOL_HEADER;
typedef struct _ICA_POOL_TRAILER {
ULONG Size;
ULONG_PTR CheckSum;
} ICA_POOL_TRAILER, *PICA_POOL_TRAILER;
void IcaInitializeDebugData(void)
{
KeInitializeSpinLock(&IcaDebugSpinLock);
InitializeListHead(&IcaGlobalPoolListHead);
}
BOOLEAN IcaLockConnection(PICA_CONNECTION pConnect)
{
PERESOURCE pResource = &pConnect->Resource;
PLIST_ENTRY Head, Next;
PICA_STACK pStack;
KIRQL oldIrql;
ULONG i;
BOOLEAN Result;
TRACE((pConnect, TC_ICADD, TT_SEM,
"TermDD: IcaLockConnection: 0x%x\n", pResource));
/*
* Ensure we don't already have the connection locked
*/
ASSERT( !ExIsResourceAcquiredExclusiveLite( pResource ) );
/*
* Reference and lock the connection object
*/
IcaReferenceConnection( pConnect );
KeEnterCriticalRegion(); // Disable APC calls when holding a resource.
Result = ExAcquireResourceExclusive( pResource, TRUE );
/*
* Ensure we don't own any stack locks
*/
Head = &pConnect->StackHead;
for ( Next = Head->Flink; Next != Head; Next = Next->Flink ) {
pStack = CONTAINING_RECORD( Next, ICA_STACK, StackEntry );
ASSERT( !ExIsResourceAcquiredExclusiveLite( &pStack->Resource ) );
}
/*
* Ensure we don't own any channel locks
*/
IcaLockChannelTable(&pConnect->ChannelTableLock);
for ( i = 0; i < sizeof(pConnect->pChannel) / sizeof(*pConnect->pChannel); i++ ) {
if (pConnect->pChannel[i]) {
ASSERT(!ExIsResourceAcquiredExclusiveLite(&pConnect->pChannel[i]->Resource));
}
}
IcaUnlockChannelTable(&pConnect->ChannelTableLock);
return Result;
}
void IcaUnlockConnection(PICA_CONNECTION pConnect)
{
PERESOURCE pResource = &pConnect->Resource;
TRACE((pConnect, TC_ICADD, TT_SEM,
"TermDD: IcaUnlockConnection: 0x%x\n", pResource));
/*
* Ensure we already have the connection locked
*/
ASSERT(ExIsResourceAcquiredExclusiveLite(pResource));
ExReleaseResource(pResource);
KeLeaveCriticalRegion(); // Resume APC calls after releasing resource.
IcaDereferenceConnection(pConnect);
}
BOOLEAN IcaLockStack(PICA_STACK pStack)
{
PERESOURCE pResource = &pStack->Resource;
PICA_CONNECTION pConnect;
PLIST_ENTRY Head, Next;
PICA_STACK pNextStack;
KIRQL oldIrql;
ULONG i;
BOOLEAN Result;
/*
* Ensure we don't already have the stack locked
*/
ASSERT( !ExIsResourceAcquiredExclusiveLite( pResource ) );
/*
* Reference and lock the stack object
*/
IcaReferenceStack( pStack );
KeEnterCriticalRegion(); // Disable APC calls when holding a resource.
Result = ExAcquireResourceExclusive( pResource, TRUE );
TRACESTACK((pStack, TC_ICADD, TT_SEM,
"TermDD: IcaLockStack: 0x%x\n", pStack));
/*
* Ensure we don't own any other stack locks
*/
pConnect = IcaGetConnectionForStack( pStack );
Head = &pConnect->StackHead;
for ( Next = Head->Flink; Next != Head; Next = Next->Flink ) {
pNextStack = CONTAINING_RECORD( Next, ICA_STACK, StackEntry );
if ( pNextStack != pStack ) {
ASSERT( !ExIsResourceAcquiredExclusiveLite( &pNextStack->Resource ) );
}
}
/*
* Ensure we don't own any channel locks
*/
IcaLockChannelTable(&pConnect->ChannelTableLock);
for ( i = 0; i < sizeof(pConnect->pChannel) / sizeof(*pConnect->pChannel); i++ ) {
if ( pConnect->pChannel[i] ) {
ASSERT( !ExIsResourceAcquiredExclusiveLite( &pConnect->pChannel[i]->Resource ) );
}
}
IcaUnlockChannelTable(&pConnect->ChannelTableLock);
return Result;
}
void IcaUnlockStack(PICA_STACK pStack)
{
PERESOURCE pResource = &pStack->Resource;
TRACESTACK((pStack, TC_ICADD, TT_SEM,
"TermDD: IcaUnlockStack: 0x%x\n", pStack));
/*
* Ensure we already have the stack locked
*/
ASSERT(ExIsResourceAcquiredExclusiveLite(pResource));
ExReleaseResource(pResource);
KeLeaveCriticalRegion(); // Resume APC calls after releasing resource.
IcaDereferenceStack(pStack);
}
BOOLEAN IcaLockChannel(PICA_CHANNEL pChannel)
{
PERESOURCE pResource = &pChannel->Resource;
TRACECHANNEL((pChannel, TC_ICADD, TT_SEM,
"TermDD: IcaLockChannel: cc %u, vc %d\n",
pChannel->ChannelClass, pChannel->VirtualClass));
IcaReferenceChannel(pChannel);
// Need to disable APC calls when holding a resource.
KeEnterCriticalRegion();
return ExAcquireResourceExclusive(pResource, TRUE);
}
void IcaUnlockChannel(IN PICA_CHANNEL pChannel)
{
PERESOURCE pResource = &pChannel->Resource;
TRACECHANNEL((pChannel, TC_ICADD, TT_SEM,
"TermDD: IcaUnlockChannel: cc %u, vc %d\n",
pChannel->ChannelClass, pChannel->VirtualClass));
/*
* Ensure we already have the channel locked
*/
ASSERT(ExIsResourceAcquiredExclusiveLite(pResource));
ExReleaseResource(pResource);
KeLeaveCriticalRegion(); // Resume APC calls after releasing resource.
IcaDereferenceChannel(pChannel);
}
PVOID IcaAllocatePool(
IN POOL_TYPE PoolType,
IN ULONG NumberOfBytes,
IN PCHAR FileName,
IN ULONG LineNumber,
IN BOOLEAN WithQuota)
{
PICA_POOL_HEADER header;
PICA_POOL_TRAILER trailer;
KIRQL oldIrql;
ASSERT( PoolType == NonPagedPool || PoolType == NonPagedPoolMustSucceed );
// make sure number of bytes are 64bit aligned
NumberOfBytes = (NumberOfBytes + 7) & ~7;
if (WithQuota) {
try {
header = ExAllocatePoolWithQuotaTag(
PoolType,
NumberOfBytes + sizeof(*header) + sizeof(*trailer),
ICA_POOL_TAG
);
} except( EXCEPTION_EXECUTE_HANDLER ) {
return NULL;
}
} else {
header = ExAllocatePoolWithTag(
PoolType,
NumberOfBytes + sizeof(*header) + sizeof(*trailer),
ICA_POOL_TAG
);
}
if (header == NULL) {
return NULL;
}
header->FileName = FileName;
header->LineNumber = LineNumber;
header->Size = NumberOfBytes;
header->InUse = 1;
trailer = (PICA_POOL_TRAILER)((PCHAR)(header + 1) + NumberOfBytes);
trailer->Size = NumberOfBytes;
trailer->CheckSum = (ULONG_PTR)header + (ULONG_PTR)FileName + LineNumber +
NumberOfBytes;
InterlockedIncrement(
&IcaTotalAllocations
);
ExInterlockedAddUlong(
&IcaTotalBytesAllocated,
header->Size,
&IcaDebugSpinLock
);
ExInterlockedInsertTailList( &IcaGlobalPoolListHead,
&header->GlobalPoolListEntry,
&IcaDebugSpinLock );
return (PVOID)(header + 1);
}
void IcaFreePool(IN PVOID Pointer)
{
KIRQL oldIrql;
PICA_POOL_HEADER header = (PICA_POOL_HEADER)Pointer - 1;
PICA_POOL_TRAILER trailer;
trailer = (PICA_POOL_TRAILER)((PCHAR)(header + 1) + header->Size);
ASSERT( header->Size == trailer->Size );
ASSERT( trailer->CheckSum = (ULONG_PTR)header + (ULONG_PTR)header->FileName +
header->LineNumber + header->Size );
InterlockedIncrement(
&IcaTotalFrees
);
ExInterlockedAddUlong(
&IcaTotalBytesAllocated,
-1*header->Size,
&IcaDebugSpinLock
);
KeAcquireSpinLock( &IcaDebugSpinLock, &oldIrql );
RemoveEntryList( &header->GlobalPoolListEntry );
KeReleaseSpinLock( &IcaDebugSpinLock, oldIrql );
header->GlobalPoolListEntry.Flink = (PLIST_ENTRY)(-1);
header->GlobalPoolListEntry.Blink = (PLIST_ENTRY)(-1);
header->InUse = 0;
if (header->Size == trailer->Size)
RtlFillMemory(Pointer, header->Size, 0xff);
ExFreePool((PVOID)header);
}
#endif