|
|
/*************************************************************************
* * khandle.c * * Manage kernel mode handles for transport drivers. * * Copyright 1998, Microsoft. * *************************************************************************/
/*
* Includes */ #include <precomp.h>
#pragma hdrstop
ULONG gHandleTableSize;
#ifdef TERMDD_NO_USE_TABLE_PACKAGE
typedef struct _TDHANDLE_ENTRY { LIST_ENTRY Link; PVOID Context; ULONG ContextSize; } TDHANDLE_ENTRY, *PTDHANDLE_ENTRY;
/*
* Global Data */ LIST_ENTRY IcaTdHandleList;
/*
* These set of routines allows TD's to create a handle that will survive * across them being unloaded and re-loaded. This allows a handle to be * passed back to ICASRV in a secure manner. * * NOTE: We do not deal with ICASRV leaking these handles. It never exits. * If it does, we will need to have ICADD return a real NT handle, or * destroy all handles for a TD when it unloads. */
/*****************************************************************************
* * IcaCreateHandle * * Create a handle entry for the context and length. * * ENTRY: * Param1 (input/output) * Comments * * EXIT: * STATUS_SUCCESS - no error * ****************************************************************************/
NTSTATUS IcaCreateHandle( PVOID Context, ULONG ContextSize, PVOID *ppHandle ) { KIRQL OldIrql; PTDHANDLE_ENTRY p;
p = ICA_ALLOCATE_POOL( NonPagedPool, sizeof(TDHANDLE_ENTRY) ); if( p == NULL ) { return( STATUS_NO_MEMORY ); }
RtlZeroMemory( p, sizeof(TDHANDLE_ENTRY) ); p->Context = Context; p->ContextSize = ContextSize;
*ppHandle = (PVOID)p;
IcaAcquireSpinLock( &IcaSpinLock, &OldIrql ); InsertHeadList( &IcaTdHandleList, &p->Link ); IcaReleaseSpinLock( &IcaSpinLock, OldIrql ); InterlockedIncrement(&gHandleTableSize);
return( STATUS_SUCCESS ); }
/*****************************************************************************
* * IcaReturnHandle * * Return the context and length for the handle. * * ENTRY: * Param1 (input/output) * Comments * * EXIT: * STATUS_SUCCESS - no error * ****************************************************************************/
NTSTATUS IcaReturnHandle( PVOID Handle, PVOID *ppContext, PULONG pContextSize ) { KIRQL OldIrql; PLIST_ENTRY pEntry; PTDHANDLE_ENTRY p;
IcaAcquireSpinLock( &IcaSpinLock, &OldIrql );
pEntry = IcaTdHandleList.Flink;
while( pEntry != &IcaTdHandleList ) {
p = CONTAINING_RECORD( pEntry, TDHANDLE_ENTRY, Link );
if( (PVOID)p == Handle ) { *ppContext = p->Context; *pContextSize = p->ContextSize; IcaReleaseSpinLock( &IcaSpinLock, OldIrql ); return( STATUS_SUCCESS ); }
pEntry = pEntry->Flink; }
IcaReleaseSpinLock( &IcaSpinLock, OldIrql );
return( STATUS_INVALID_HANDLE ); }
/*****************************************************************************
* * IcaCloseHandle * * Return the context and length for the handle. Delete the * handle entry. * * ENTRY: * Param1 (input/output) * Comments * * EXIT: * STATUS_SUCCESS - no error * ****************************************************************************/
NTSTATUS IcaCloseHandle( PVOID Handle, PVOID *ppContext, PULONG pContextSize ) { KIRQL OldIrql; PLIST_ENTRY pEntry; PTDHANDLE_ENTRY p;
IcaAcquireSpinLock( &IcaSpinLock, &OldIrql );
pEntry = IcaTdHandleList.Flink;
while( pEntry != &IcaTdHandleList ) {
p = CONTAINING_RECORD( pEntry, TDHANDLE_ENTRY, Link );
if( (PVOID)p == Handle ) { RemoveEntryList( &p->Link ); IcaReleaseSpinLock( &IcaSpinLock, OldIrql ); InterlockedDecrement(&gHandleTableSize); *ppContext = p->Context; *pContextSize = p->ContextSize; ICA_FREE_POOL( p ); return( STATUS_SUCCESS ); }
pEntry = pEntry->Flink; }
IcaReleaseSpinLock( &IcaSpinLock, OldIrql );
return( STATUS_INVALID_HANDLE ); }
/*****************************************************************************
* * IcaInitializeHandleTable * * Initializes handle table at driver load. * * ENTRY: * None * Comments * * EXIT: * None * ****************************************************************************/ void IcaInitializeHandleTable( void ) { InitializeListHead( &IcaTdHandleList ); } /*****************************************************************************
* * IcaCleanupHandleTable * * Cleans up handle table at driver unload. * * ENTRY: * None * Comments * * EXIT: * None * ****************************************************************************/
void IcaCleanupHandleTable( void ) { KIRQL OldIrql; PLIST_ENTRY pEntry; PTDHANDLE_ENTRY p;
KdPrint(("TermDD: IcaCleanupHandleTable table size is %d\n",gHandleTableSize));
for (pEntry = IcaTdHandleList.Flink; pEntry != &IcaTdHandleList; pEntry = IcaTdHandleList.Flink) { p = CONTAINING_RECORD( pEntry, TDHANDLE_ENTRY, Link ); RemoveEntryList(&p->Links); ICA_FREE_POOL( p->Context ); ICA_FREE_POOL( p ); } }
#else
typedef struct _TDHANDLE_ENTRY { PVOID Context; ULONG ContextSize; } TDHANDLE_ENTRY, *PTDHANDLE_ENTRY;
RTL_GENERIC_TABLE IcaHandleReferenceTable;
RTL_GENERIC_COMPARE_RESULTS NTAPI IcaCompareHandleTableEntry ( IN struct _RTL_GENERIC_TABLE *Table, IN PVOID FirstInstance, IN PVOID SecondInstance );
PVOID IcaAllocateHandleTableEntry ( IN struct _RTL_GENERIC_TABLE *Table, IN CLONG ByteSize );
VOID IcaFreeHandleTableEntry ( IN struct _RTL_GENERIC_TABLE *Table, IN PVOID Buffer );
/*****************************************************************************
* * IcaInitializeHandleTable * * Initializes handle table at driver load. * * ENTRY: * None * Comments * * EXIT: * None * ****************************************************************************/ void IcaInitializeHandleTable( void ) { RtlInitializeGenericTable( &IcaHandleReferenceTable, IcaCompareHandleTableEntry, IcaAllocateHandleTableEntry, IcaFreeHandleTableEntry, NULL); }
/*****************************************************************************
* * IcaCleanupHandleTable * * Cleanup handle table at driver unload. * * ENTRY: * None * Comments * * EXIT: * None * ****************************************************************************/
void IcaCleanupHandleTable( void ) { KIRQL OldIrql; PLIST_ENTRY pEntry; PTDHANDLE_ENTRY p; PVOID pContext; TDHANDLE_ENTRY key;
KdPrint(("TermDD: IcaCleanupHandleTable table size is %d\n",gHandleTableSize));
while (p = RtlEnumerateGenericTable(&IcaHandleReferenceTable,TRUE)) { key.Context = p->Context; RtlDeleteElementGenericTable(&IcaHandleReferenceTable, &key); ICA_FREE_POOL(key.Context); }
}
/*****************************************************************************
* * IcaCreateHandle * * Create a handle entry for the context and length. * * ENTRY: * Param1 (input/output) * Comments * * EXIT: * STATUS_SUCCESS - no error * ****************************************************************************/
NTSTATUS IcaCreateHandle( PVOID Context, ULONG ContextSize, PVOID *ppHandle ) { KIRQL OldIrql; TDHANDLE_ENTRY key; BOOLEAN bNewElement;
key.Context = Context; key.ContextSize = ContextSize; IcaAcquireSpinLock( &IcaSpinLock, &OldIrql ); if (!RtlInsertElementGenericTable(&IcaHandleReferenceTable,(PVOID) &key, sizeof(TDHANDLE_ENTRY), &bNewElement )) { IcaReleaseSpinLock( &IcaSpinLock, OldIrql ); return STATUS_NO_MEMORY; } IcaReleaseSpinLock( &IcaSpinLock, OldIrql ); ASSERT(bNewElement); if (!bNewElement) { return STATUS_INVALID_PARAMETER; }
InterlockedIncrement(&gHandleTableSize);
*ppHandle = Context;
return( STATUS_SUCCESS ); }
/*****************************************************************************
* * IcaReturnHandle * * Return the context and length for the handle. * * ENTRY: * Param1 (input/output) * Comments * * EXIT: * STATUS_SUCCESS - no error * ****************************************************************************/
NTSTATUS IcaReturnHandle( PVOID Handle, PVOID *ppContext, PULONG pContextSize ) { KIRQL OldIrql; PTDHANDLE_ENTRY p; TDHANDLE_ENTRY key;
key.Context = Handle; IcaAcquireSpinLock( &IcaSpinLock, &OldIrql );
p = RtlLookupElementGenericTable(&IcaHandleReferenceTable, &key); if (p != NULL) { *ppContext = p->Context; *pContextSize = p->ContextSize; IcaReleaseSpinLock( &IcaSpinLock, OldIrql ); return STATUS_SUCCESS; } else { IcaReleaseSpinLock( &IcaSpinLock, OldIrql ); return STATUS_INVALID_HANDLE; }
}
/*****************************************************************************
* * IcaCloseHandle * * Return the context and length for the handle. Delete the * handle entry. * * ENTRY: * Param1 (input/output) * Comments * * EXIT: * STATUS_SUCCESS - no error * ****************************************************************************/
NTSTATUS IcaCloseHandle( PVOID Handle, PVOID *ppContext, PULONG pContextSize ) { KIRQL OldIrql; PTDHANDLE_ENTRY p; TDHANDLE_ENTRY key;
key.Context = Handle; IcaAcquireSpinLock( &IcaSpinLock, &OldIrql );
p = RtlLookupElementGenericTable(&IcaHandleReferenceTable, &key); if (p != NULL) { *ppContext = p->Context; *pContextSize = p->ContextSize; RtlDeleteElementGenericTable(&IcaHandleReferenceTable, &key); IcaReleaseSpinLock( &IcaSpinLock, OldIrql ); InterlockedDecrement(&gHandleTableSize); return STATUS_SUCCESS; } else { IcaReleaseSpinLock( &IcaSpinLock, OldIrql ); return STATUS_INVALID_HANDLE; }
}
/*****************************************************************************
* * IcaCompareHandleTableEntry * * Generic table support.Compare two handles table entry instances * * ****************************************************************************/
RTL_GENERIC_COMPARE_RESULTS NTAPI IcaCompareHandleTableEntry ( IN struct _RTL_GENERIC_TABLE *Table, IN PVOID FirstInstance, IN PVOID SecondInstance ) { ULONG_PTR FirstHandle = (ULONG_PTR)((PTDHANDLE_ENTRY)FirstInstance)->Context; ULONG_PTR SecondHandle = (ULONG_PTR)((PTDHANDLE_ENTRY)SecondInstance)->Context;
if (FirstHandle < SecondHandle ) { return GenericLessThan; }
if (FirstHandle > SecondHandle ) { return GenericGreaterThan; } return GenericEqual; }
/*****************************************************************************
* * IcaAllocateHandleTableEntry * * Generic table support. Allocates a new table entry * * ****************************************************************************/
PVOID IcaAllocateHandleTableEntry ( IN struct _RTL_GENERIC_TABLE *Table, IN CLONG ByteSize ) {
return ICA_ALLOCATE_POOL( NonPagedPool, ByteSize ); }
/*****************************************************************************
* * IcaFreeHandleTableEntry * * Generic table support. frees a new table entry * * ****************************************************************************/
VOID IcaFreeHandleTableEntry ( IN struct _RTL_GENERIC_TABLE *Table, IN PVOID Buffer ) {
ICA_FREE_POOL(Buffer); }
#endif
|