www.pudn.com > IpFilter.rar > IpHookGlobal.cpp


/////////////////////////////////////////////////////////////////////////////// 
// 
//	(C) Copyright 1999 - 2000 Mark Roddy 
//	All Rights Reserved 
// 
//	Hollis Technology Solutions 
//	94 Dow Road 
//	Hollis, NH 03049 
//	info@hollistech.com 
// 
//	Synopsis:  
//  
// 
//	Version Information: 
// 
//	$Header: /iphook/sys/driver/IpHookGlobal.cpp 4     1/27/00 10:35p Markr $  
// 
/////////////////////////////////////////////////////////////////////////////// 
#include "IpHookKrnl.h" 
 
HTS_DEBUG_THIS_FILE 
 
void IP_HOOK_GLOBAL_DATA::queueRequest(PIRP Irp) 
{ 
	PVOID context; 
 
	lock(context); 
	IoSetCancelRoutine(Irp, GlobalCancel); 
	InsertTailList(&queue, &Irp->Tail.Overlay.ListEntry); 
	unlock(context); 
} 
 
PIRP IP_HOOK_GLOBAL_DATA::popQueue(BOOLEAN locked) 
{ 
	PIRP Irp = NULL; 
 
	PVOID context; 
 
	if (!locked) { 
	 
		lock(context); 
	} 
 
	if (!IsListEmpty(&queue)) { 
 
		PLIST_ENTRY el = RemoveHeadList(&queue); 
		Irp = CONTAINING_RECORD(el, IRP, Tail.Overlay.ListEntry); 
		PDRIVER_CANCEL state = IoSetCancelRoutine(Irp, NULL); 
 
		if (state == NULL) { 
			// 
			// we have hit the race condition where our 
			// cancel routine is runnning just before it acquires 
			// the lock and dequeues the irp 
			// 
			InsertHeadList(&cancelQueue, &Irp->Tail.Overlay.ListEntry); 
			 
			Irp = NULL; 
		} 
 
    } 
	 
	if (!locked) { 
 
		unlock(context); 
 
	} 
 
	return Irp; 
} 
 
PIPHOOK_DATA IP_HOOK_GLOBAL_DATA::getBuffer() 
{ 
	PIPHOOK_DATA data = NULL; 
 
	HtsDebugPrint(HTS_DEBUG_LOW, "getBuffer()\n"); 
 
	PVOID context; 
 
	lock(context); 
 
	bool keepTrying = true; 
 
	do { 
 
		if (currentBuffer == NULL) { 
 
			HtsAssert(currentIrp == NULL); 
 
			currentIrp = popQueue(TRUE); 
			 
			if (currentIrp) { 
 
				currentBuffer =  
					(PIPHOOK_BUFFER) MmGetSystemAddressForMdl(currentIrp->MdlAddress); 
			} 
 
			if (currentBuffer) { 
 
				currentBuffer->valid = 0; 
 
			}  else { 
 
				keepTrying =false; 
 
			} 
		} 
 
		if (currentBuffer) { 
 
			HtsDebugPrint(HTS_DEBUG_LOW, "currentBuffer %x valid %x entries %x\n", 
					currentBuffer, 
					currentBuffer->valid, currentBuffer->entries); 
 
			if (currentBuffer->valid < currentBuffer->entries) { 
 
				data = ¤tBuffer->buffer[currentBuffer->valid]; 
 
				currentBuffer->valid++; 
 
			} else { 
 
				flushBuffer(TRUE); 
 
				HtsAssert(currentBuffer == NULL); 
				// 
				// Im tempted to recurse here 
				// 
				HtsDebugPrint(HTS_DEBUG_LOW, "getBuffer continue\n"); 
 
			} 
		} 
 
	} while ((!currentBuffer) && keepTrying); 
 
	unlock(context); 
 
	HtsDebugPrint(HTS_DEBUG_LOW, "returning data %x\n", data); 
 
	return data; 
} 
 
IP_HOOK_GLOBAL_DATA::IP_HOOK_GLOBAL_DATA()  
{ 
	owningContext = NULL; 
	IpfDeviceObject = NULL; 
	IpfFileObject = NULL; 
	IpHookSequence = 0; 
	InitializeListHead(&queue); 
	InitializeListHead(&cancelQueue); 
	currentIrp = NULL; 
	currentBuffer = NULL; 
	KeInitializeEvent(&stopEvent, NotificationEvent, FALSE); 
 
} 
 
NTSTATUS IP_HOOK_GLOBAL_DATA::initDevice() 
{ 
	UNICODE_STRING nameString; 
 
	RtlInitUnicodeString(&nameString, DD_IPFLTRDRVR_DEVICE_NAME); 
 
	NTSTATUS Status = IoGetDeviceObjectPointer(&nameString, 
									  STANDARD_RIGHTS_ALL, 
									  &IpfFileObject, 
									  &IpfDeviceObject); 
	if (!NT_SUCCESS(Status)) { 
 
		HtsDebugPrint(HTS_DEBUG_HIGH, "Can't open IpFilter (%S) Status %x\n", 
					  DD_IPFLTRDRVR_DEVICE_NAME, Status); 
 
	} else { 
 
		HtsAssert( IpfFileObject ); 
 
		HtsAssert( IpfDeviceObject ); 
	} 
 
	return Status; 
} 
 
 
IP_HOOK_GLOBAL_DATA::~IP_HOOK_GLOBAL_DATA() 
{ 
	HtsDebugPrint(HTS_DEBUG_LOW,  
		"~IP_HOOK_GLOBAL_DATA IpfFileObject %x\n", IpfFileObject); 
 
	if (workerThreadObject != NULL) { 
		 
		KeSetEvent(&stopEvent, 0, TRUE); 
 
		(void) KeWaitForSingleObject(workerThreadObject, Executive, KernelMode, FALSE, NULL); 
 
		ObDereferenceObject(workerThreadObject); 
         
	} 
 
 
	if (IpfFileObject) { 
 
		HtsAssert(IpfDeviceObject); 
 
		ObDereferenceObject(IpfFileObject); 
		IpfFileObject = NULL; 
		IpfDeviceObject = NULL; 
 
	} else { 
 
		HtsAssert(ipGlobal.IpfDeviceObject == NULL); 
 
	} 
 
	 
} 
 
void IP_HOOK_GLOBAL_DATA::flushBufferIfData() 
{ 
	PVOID context; 
 
	lock(context); 
 
	if (currentIrp) { 
 
		HtsAssert(currentBuffer); 
 
		if (currentBuffer->valid) { 
 
			flushBuffer(TRUE); 
		} 
	} 
 
	unlock(context); 
} 
 
void IP_HOOK_GLOBAL_DATA::flushBuffer(BOOLEAN locked) 
{ 
	// 
	// complete the current buffer/irp 
	// 
	PIRP Irp = NULL; 
	ULONG Information = 0; 
	PVOID context; 
 
	HtsDebugPrint(HTS_DEBUG_LOW, "flushBuffer(%x)\n", locked); 
 
	if (!locked) { 
	 
		lock(context); 
	} 
 
	if (currentIrp) { 
 
		HtsAssert(currentBuffer); 
 
		Irp = currentIrp; 
 
		currentIrp = NULL; 
 
		ULONG valid = currentBuffer->valid; 
 
		Information = sizeof(IPHOOK_BUFFER) - sizeof(IPHOOK_DATA) 
			+ (valid * sizeof(IPHOOK_DATA)); 
		 
		currentBuffer = NULL; 
 
		HtsDebugPrint(HTS_DEBUG_LOW, "Flushing Irp %x valid %x size %x\n", Irp, valid, Information); 
 
	} 
 
	if (!locked) { 
 
		unlock(context); 
 
	} 
 
	if (Irp) { 
 
		HtsIrpReturn(Irp, STATUS_SUCCESS, Information); 
	} 
} 
 
void IP_HOOK_GLOBAL_DATA::releaseAllBuffers(BOOLEAN locked) 
{ 
	flushBuffer(locked); 
 
	PIRP Irp = popQueue(locked); 
 
	HtsDebugPrint(HTS_DEBUG_LOW, "releaseAllBuffers(%d)\n", locked); 
 
	while (Irp) { 
 
		HtsDebugPrint(HTS_DEBUG_LOW, "releasing Irp %x\n", Irp); 
 
		HtsIrpReturn(Irp, STATUS_CANCELLED, 0); 
 
		Irp = popQueue(locked); 
	} 
} 
 
void workerThreadStart(PVOID context) 
{ 
	// 
	// this routine runs forever until it is signalled to die. 
	// It waits on an event - the stopevent, the wait is timed. 
	// If the timer expires then the function flushes the current buffer -  
	// delivering the contents to user space. Otherwise the routine terminates 
	// its host thread by returning out of this function. 
	// 
	PRKEVENT stopEvent = (PRKEVENT) context; 
	LARGE_INTEGER  Timeout; 
 
	do { 
		Timeout.QuadPart = -10000000L; 
 
		NTSTATUS Status = KeWaitForSingleObject(stopEvent, 
							  Executive, 
							  KernelMode, 
							  FALSE, 
							  &Timeout); 
 
		switch (Status) { 
 
		case STATUS_TIMEOUT: 
			// 
			// flush the buffer 
			// 
			HtsDebugPrint(HTS_DEBUG_LOW, "workerThreadStart STATUS_TIMEOUT\n"); 
			ipGlobal.flushBufferIfData(); 
 
			break; 
		 
		default: 
 
			HtsDebugPrint(HTS_DEBUG_HIGH, 
				"workerThreadStart wait returned %x\n", Status); 
 
		case STATUS_SUCCESS: 
			// 
			// for any value other than STATUS_TIMEOUT we bail! 
			// 
			HtsDebugPrint(HTS_DEBUG_LOW, 
				"workerThreadStart exit\n"); 
 
			return; 
		} 
 
	} while(1); 
 
} 
 
NTSTATUS IP_HOOK_GLOBAL_DATA::createThread() 
{ 
 
	NTSTATUS Status = PsCreateSystemThread(&workerThread, 
								  THREAD_ALL_ACCESS, 
								  NULL, 
								  NULL, 
								  NULL, 
								  workerThreadStart, 
								  (PVOID)&stopEvent); 
 
	if (!NT_SUCCESS(Status)) { 
 
		HtsDebugPrint(HTS_DEBUG_HIGH, "PsCreateSystemThread failed\n"); 
 
		workerThread = NULL; 
 
	} 
	 
	Status = ObReferenceObjectByHandle(workerThread, THREAD_ALL_ACCESS, NULL, KernelMode, 
		  &workerThreadObject, NULL ); 
 
	if (!NT_SUCCESS(Status)) { 
 
		HtsDebugPrint(HTS_DEBUG_HIGH, "ObReferenceObjectByHandle failed\n"); 
 
		KeSetEvent(&stopEvent, 0, FALSE); 
 
		workerThread = NULL; 
 
		workerThreadObject = NULL; 
 
	} 
	 
	return Status; 
 
} 
/////////////////////////////////////////////////////////////////////////////// 
//  
// Change History Log 
// 
// $Log: /iphook/sys/driver/IpHookGlobal.cpp $ 
//  
// 4     1/27/00 10:35p Markr 
// Prepare to release! 
// 
///////////////////////////////////////////////////////////////////////////////