📄 addr.c
字号:
/////////////////////////////////////////////////////////////////////////////
//// INCLUDE FILES
#include "ndis.h"
#include "TDI.H"
#include "TDIKRNL.H"
#include "PCATDIH.h"
#include "KSUtil.h"
#include "addr.h"
#include "tcpconn.h"
#include "tcprcv.h"
#include "udprcv.h"
#include "inetinc.h"
// Copyright And Configuration Management ----------------------------------
//
// TDI Address Function Filters - Addr.c
// Transport Data Interface (TDI) Filter For Windows NT
//
// Copyright (c) 2000 Printing Communications Associates, Inc.
// - PCAUSA -
//
// Thomas F. Divine
// 4201 Brunswick Court
// Smyrna, Georgia 30080 USA
// (770) 432-4580
// tdivine@pcausa.com
//
// End ---------------------------------------------------------------------
//
// The Address Object Lists
//
LIST_ENTRY FreeAddrObjList;
LIST_ENTRY OpenAddrObjList;
LIST_ENTRY AddrObjExInfoList;
PAddrObjExInfo
TDIH_GetAddrObjExInfo( PIRP Irp )
{
PAddrObjExInfo pAddrObjExInfo;
//
// Walk The Special Create List
//
pAddrObjExInfo = (PAddrObjExInfo )AddrObjExInfoList.Flink;
while( !IsListEmpty( &AddrObjExInfoList )
&& pAddrObjExInfo != (PAddrObjExInfo )&AddrObjExInfoList
)
{
//
// Match On Address Handle
//
if( pAddrObjExInfo->aox_thread == Irp->Tail.Overlay.Thread )
{
return( pAddrObjExInfo );
}
//
// Move To The Next Address Object Record
//
pAddrObjExInfo = (PAddrObjExInfo )pAddrObjExInfo->aox_q.Flink;
}
return( (PAddrObjExInfo )NULL );
}
AddrObj *
TDIH_GetAddrObjFromFileObject(
PFILE_OBJECT FileObject
)
{
AddrObj *pAddrObj;
//
// Walk The List Of Open Address Objects
//
pAddrObj = (AddrObj * )OpenAddrObjList.Flink;
while( !IsListEmpty( &OpenAddrObjList )
&& pAddrObj != (AddrObj * )&OpenAddrObjList
)
{
//
// Match On Address Handle
//
if( pAddrObj->ao_FileObject == FileObject )
{
return( pAddrObj );
}
//
// Move To The Next Address Object Record
//
pAddrObj = (AddrObj * )pAddrObj->ao_q.Flink;
}
return( (AddrObj * )NULL );
}
/////////////////////////////////////////////////////////////////////////////
//// TDIH_TdiOpenAddressComplete
//
// Purpose
//
// Parameters
//
// Return Value
//
// Remarks
//
NTSTATUS
TDIH_TdiOpenAddressComplete(
PDEVICE_OBJECT pDeviceObject,
PIRP Irp,
void *Context
)
{
PTDIH_DeviceExtension pTDIH_DeviceExtension;
BOOLEAN CanDetachProceed = FALSE;
PDEVICE_OBJECT pAssociatedDeviceObject = NULL;
NTSTATUS Status = Irp->IoStatus.Status;
KdPrint(( "TDIH_TdiOpenAddressComplete: Status: 0x%8.8X\n", Status ));
pTDIH_DeviceExtension = (PTDIH_DeviceExtension )(Context);
ASSERT( pTDIH_DeviceExtension );
//
// Propogate The IRP Pending Flag
//
if (Irp->PendingReturned)
{
IoMarkIrpPending(Irp);
}
// Ensure that this is a valid device object pointer, else return
// immediately.
pAssociatedDeviceObject = pTDIH_DeviceExtension->pFilterDeviceObject;
if (pAssociatedDeviceObject != pDeviceObject)
{
KdPrint(( "TDIH_TdiOpenAddressComplete: Invalid Device Object Pointer\n" ));
return(STATUS_SUCCESS);
}
// Note that you could do all sorts of processing at this point
// depending upon the results of the operation. Be careful though
// about what you chose to do, about the fact that this completion
// routine is being invoked in an arbitrary thread context and probably
// at high IRQL.
//
// Create A New Address Object Record, If Successful
//
if( NT_SUCCESS( Status ) )
{
AddrObj *pAddrObj = NULL;
PIO_STACK_LOCATION IrpSp = NULL;
// Get the current I/O stack location.
IrpSp = IoGetCurrentIrpStackLocation(Irp);
ASSERT(IrpSp);
pAddrObj = TDIH_GetAddrObjFromFileObject( IrpSp->FileObject );
if( pAddrObj )
{
KdPrint((" AddrObj ALREADY EXISTS!!!\n"));
}
//
// Allocate A New Address Object Record
// ------------------------------------
// First attempt to recycle a previously allocated AddrObj structure.
// If none available, allocate a new one.
//
pAddrObj = (AddrObj * )ExAllocatePool(NonPagedPool, sizeof(AddrObj) );
if( !IsListEmpty( &FreeAddrObjList ) )
{
pAddrObj = (AddrObj * )RemoveHeadList( &FreeAddrObjList );
}
if( !pAddrObj || (PLIST_ENTRY )pAddrObj == &FreeAddrObjList )
{
pAddrObj = (AddrObj * )ExAllocatePool(NonPagedPool, sizeof(AddrObj) );
}
//
// Initialize The New Address Object Record
//
if( pAddrObj )
{
PAddrObjExInfo pAddrObjExInfo;
//
// Initialize The New Address Object
//
NdisZeroMemory( pAddrObj, sizeof(AddrObj) );
KS_GetCurrentProcessName( pAddrObj->ao_ProcessName );
pAddrObjExInfo = TDIH_GetAddrObjExInfo( Irp );
if( pAddrObjExInfo )
{
KdPrint((" Marking Internally Initiated Address Object\n" ));
//
// Special Handling For Address Objects Created In The TDI Filter
// --------------------------------------------------------------
// See extensive comments for the W32API_TestOpenAddress function
// in W32Api.c.
//
pAddrObj->aox_valid = TRUE;
pAddrObj->aox_data1 = pAddrObjExInfo->aox_data1;
pAddrObj->aox_data2 = pAddrObjExInfo->aox_data2;
//
// Return The AddrObj Pointer
// --------------------------
// Hopefully you will find a use for it...
//
pAddrObjExInfo->aox_ao = pAddrObj;
}
InitializeListHead( &pAddrObj->ao_tc_q );
InitializeListHead( &pAddrObj->ao_senddg_q );
InitializeListHead( &pAddrObj->ao_rcvdg_q );
pAddrObj->ao_DeviceExtension = pTDIH_DeviceExtension;
if( pTDIH_DeviceExtension->NodeIdentifier.NodeType == TDIH_NODE_TYPE_TCP_FILTER_DEVICE )
{
pAddrObj->ao_prot = IPPROTO_TCP;
}
else if( pTDIH_DeviceExtension->NodeIdentifier.NodeType == TDIH_NODE_TYPE_UDP_FILTER_DEVICE )
{
pAddrObj->ao_prot = IPPROTO_UDP;
}
else if( pTDIH_DeviceExtension->NodeIdentifier.NodeType == TDIH_NODE_TYPE_RAW_IP_FILTER_DEVICE )
{
// ATTENTION!!! Must Extract Protocol From EA
pAddrObj->ao_prot = 0;
}
pAddrObj->ao_FileObject = IrpSp->FileObject;
//
// Add To The Open Address Object List
//
InsertTailList(
&OpenAddrObjList,
&pAddrObj->ao_q
);
}
}
UTIL_DecrementLargeInteger(
pTDIH_DeviceExtension->OutstandingIoRequests,
(unsigned long)1,
&(pTDIH_DeviceExtension->IoRequestsSpinLock)
);
// If the outstanding count is 0, signal the appropriate event which will
// allow any pending detach to proceed.
UTIL_IsLargeIntegerZero(
CanDetachProceed,
pTDIH_DeviceExtension->OutstandingIoRequests,
&(pTDIH_DeviceExtension->IoRequestsSpinLock)
);
if (CanDetachProceed)
{
// signal the event object. Note that this is simply an
// advisory check we do here (to wake up a sleeping thread).
// It is the responsibility of the thread performing the detach to
// ensure that no operations are truly in progress.
KeSetEvent(&(pTDIH_DeviceExtension->IoInProgressEvent), IO_NO_INCREMENT, FALSE);
}
// Although the success return value is hard-coded here, you can
// return an appropriate value (either success or more-processing-reqd)
// based upon what it is that you wish to do in your completion routine.
return(STATUS_SUCCESS);
}
/////////////////////////////////////////////////////////////////////////////
//// TDIH_TdiOpenAddress
//
// Purpose
// This is the hook for TdiOpenAddress
//
// Parameters
//
// Return Value
//
// Remarks
//
NTSTATUS
TDIH_TdiOpenAddress(
PTDIH_DeviceExtension pTDIH_DeviceExtension,
PIRP Irp,
PIO_STACK_LOCATION IrpSp
)
{
NTSTATUS RC;
char ProcessName[ NT_PROCNAMELEN ];
if( KS_GetCurrentProcessName( ProcessName ) )
{
KdPrint(( "TDIH_TdiOpenAddress: Process: \042%s\042\n", ProcessName ));
}
else
{
KdPrint(( "TDIH_TdiOpenAddress: Process: UNKNOWN\n" ));
}
//
// Pass The Request To A TCP/IP Device
//
try
{
PDEVICE_OBJECT pLowerDeviceObject = NULL;
pLowerDeviceObject = pTDIH_DeviceExtension->LowerDeviceObject;
// Be careful about not screwing up badly. This is actually not recommended by the I/O Manager.
if (Irp->CurrentLocation == 1)
{
ULONG ReturnedInformation = 0;
// Bad!! Fudge the error code. Break if we can ...
KdPrint(("TDIH_TdiOpenAddress encountered bogus current location\n"));
// UTIL_BreakPoint();
RC = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Status = RC;
Irp->IoStatus.Information = ReturnedInformation;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return( RC );
}
IoCopyCurrentIrpStackLocationToNext( Irp );
IoSetCompletionRoutine(
Irp,
TDIH_TdiOpenAddressComplete,
pTDIH_DeviceExtension,
TRUE,
TRUE,
TRUE
);
UTIL_IncrementLargeInteger(
pTDIH_DeviceExtension->OutstandingIoRequests,
(unsigned long)1,
&(pTDIH_DeviceExtension->IoRequestsSpinLock)
);
// Clear the fast-IO notification event protected by the resource
// we have acquired.
KeClearEvent(&(pTDIH_DeviceExtension->IoInProgressEvent));
ASSERT( KeGetCurrentIrql() <= DISPATCH_LEVEL );
RC = IoCallDriver(pLowerDeviceObject, Irp);
try_return(RC);
try_exit: NOTHING;
}
finally
{
}
return(RC);
}
/////////////////////////////////////////////////////////////////////////////
//// TDIH_TdiCloseAddressComplete
//
// Purpose
//
// Parameters
//
// Return Value
//
// Remarks
//
NTSTATUS
TDIH_TdiCloseAddressComplete(
PDEVICE_OBJECT pDeviceObject,
PIRP Irp,
void *Context
)
{
PTDIH_DeviceExtension pTDIH_DeviceExtension = NULL;
BOOLEAN CanDetachProceed = FALSE;
PDEVICE_OBJECT pAssociatedDeviceObject = NULL;
NTSTATUS Status = Irp->IoStatus.Status;
AddrObj *pAddrObj;
PIO_STACK_LOCATION IrpSp = NULL;
KdPrint(( "TDIH_TdiCloseAddressComplete: Status: 0x%8.8X\n", Status ));
ASSERT( Context );
pTDIH_DeviceExtension = (PTDIH_DeviceExtension )(Context);
//
// Propogate The IRP Pending Flag
//
if (Irp->PendingReturned)
{
IoMarkIrpPending(Irp);
}
// Ensure that this is a valid device object pointer, else return
// immediately.
pAssociatedDeviceObject = pTDIH_DeviceExtension->pFilterDeviceObject;
ASSERT( pAssociatedDeviceObject == pDeviceObject );
if( pAssociatedDeviceObject != pDeviceObject )
{
KdPrint(( "TDIH_TdiCloseAddressComplete: Invalid Device Object Pointer\n" ));
return(STATUS_SUCCESS);
}
// Note that you could do all sorts of processing at this point
// depending upon the results of the operation. Be careful though
// about what you chose to do, about the fact that this completion
// routine is being invoked in an arbitrary thread context and probably
// at high IRQL.
// Get the current I/O stack location.
IrpSp = IoGetCurrentIrpStackLocation(Irp);
ASSERT(IrpSp);
//
// Locate The Address Object Record
//
pAddrObj = TDIH_GetAddrObjFromFileObject( IrpSp->FileObject );
if( pAddrObj )
{
KdPrint((" Found AddrObject For Close\n" ));
ASSERT( IsListEmpty(&pAddrObj->ao_senddg_q) );
ASSERT( IsListEmpty(&pAddrObj->ao_rcvdg_q) );
//
// Remove From The Open Address List
//
RemoveEntryList( &pAddrObj->ao_q );
//
// Add To The Free Address Object List
// -----------------------------------
// Don't free AddrObj structures. Instead, queue them in
// the Free Address Object List for re-use. This should
// reduce memory fragmentation since AddrObj are likely
// to be needed again.
//
InsertTailList(
&FreeAddrObjList,
&pAddrObj->ao_q
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -