📄 ksutil.c
字号:
/////////////////////////////////////////////////////////////////////////////
//// INCLUDE FILES
#include "NDIS.H"
#include "TDI.H"
#include "TDIKRNL.H"
#include "KSUtil.h"
// Copyright And Configuration Management ----------------------------------
//
// TDI Test TCP (TTCP) Utilities - KSUTIL.c
//
// PCAUSA TDI Client Samples For Windows NT
//
// Copyright (c) 1999-2000 Printing Communications Associates, Inc.
// - PCAUSA -
//
// Thomas F. Divine
// 4201 Brunswick Court
// Smyrna, Georgia 30080 USA
// (770) 432-4580
// tdivine@pcausa.com
//
// End ---------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//// NOTES
//
// The KS_xxx utilities are general purpose, and are intended to be used
// and incorporated into your own TDI client driver.
//
NDIS_PHYSICAL_ADDRESS HighestAcceptableMax =
NDIS_PHYSICAL_ADDRESS_CONST(-1,-1);
static NTSTATUS
_I_KS_SimpleTdiRequestComplete(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
);
VOID
_I_KS_RefTransportAddress(
PKS_ADDRESS pKS_Address
);
VOID
_I_KS_DerefTransportAddress(
PKS_ADDRESS pKS_Address
);
NTSTATUS
_I_KS_OpenConnectionContext(
PWSTR TransportDeviceNameW,// Zero-terminated String
PKS_ENDPOINT pKS_Endpoint,
PVOID pContext
);
NTSTATUS
_I_KS_CloseConnectionContext(
PKS_ENDPOINT pKS_Endpoint
);
VOID
_I_KS_RefConnectionEndpoint(
PKS_ENDPOINT pKS_Endpoint
);
VOID
_I_KS_DerefConnectionEndpoint(
PKS_ENDPOINT pKS_Endpoint
);
NTSTATUS
_I_KS_AssociateAddress(
PKS_ADDRESS pKS_Address,
PKS_ENDPOINT pKS_Endpoint
);
NTSTATUS
_I_KS_DisassociateAddress(
PKS_ENDPOINT pKS_Endpoint
);
/////////////////////////////////////////////////////////////////////////////
//// STRUCTURES
typedef
struct _KS_ADDRESS_REQUEST_CONTEXT
{
PKS_ADDRESS m_pKS_Address;
HANDLE m_CompletionEvent;
PKS_REQUEST_COMPLETION_ROUTINE m_CompletionRoutine;
PVOID m_CompletionContext;
PIO_STATUS_BLOCK m_pIoStatusBlock;
IO_STATUS_BLOCK m_SafeIoStatusBlock;
ULONG m_Reserved;
}
KS_ADDRESS_REQUEST_CONTEXT, *PKS_ADDRESS_REQUEST_CONTEXT;
typedef
struct _KS_ENDPOINT_REQUEST_CONTEXT
{
PKS_ENDPOINT m_pKS_Endpoint;
HANDLE m_CompletionEvent;
PKS_REQUEST_COMPLETION_ROUTINE m_CompletionRoutine;
PVOID m_CompletionContext;
PIO_STATUS_BLOCK m_pIoStatusBlock;
IO_STATUS_BLOCK m_SafeIoStatusBlock;
BOOLEAN m_bSynchronous;
ULONG m_Reserved;
}
KS_ENDPOINT_REQUEST_CONTEXT, *PKS_ENDPOINT_REQUEST_CONTEXT;
/////////////////////////////////////////////////////////////////////////////
// A D D R E S S F U N C T I O N S //
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//// KS_OpenTransportAddress
//
// Purpose
// Open a TDI address object on the specified transport device for the
// specified transport address.
//
// Parameters
// TransportDeviceNameW
// Pointer to a zero-terminated wide character string that specifies
// the transport device. An example would be: L"\\Device\\Tcp"
//
// pTransportAddress
// Pointer to a TRANSPORT_ADDRESS structure (typically a TA_IP_ADDRESS
// structure) that specifies the local address to open.
//
// pKS_Address
// Pointer to a caller-provided KS_ADDRESS structure that will be
// initialized as the transport address object is opened.
//
// Return Value
// Status
//
// Remarks
// See the NT DDK documentation topic "5.1 Opening a Transport Address"
// for more information.
//
// The KS_BuildEaBuffer function is used to build the extended attributes
// buffer.
//
// It is important to note that the call to ZwCreateFile creates a
// client-process-specific file object that represents the transport's
// address object. This means that the m_hAddress handle is only valid
// in the same client process that the ZwCreateFile call was made in.
//
// Fortunately, most TDI operations actually reference the file object
// pointer - not the handle. Operations that do not reference the address
// handle can be performed in arbitrary context unless there are other
// restrictions.
//
// The client process dependency of the address handle does effect
// the design of a TDI Client to some extent. In particular, the
// client process that was used to create an address object must
// continue to exist until the address object is eventually closed.
//
// There are several ways to insure that the client process continues
// to exist while the address object is in use. The most common is to
// create a thread that is attached to the system process. As long as
// the system process continues to exist, the address object handle
// will remain valid.
//
// Callers of KS_OpenTransportAddress must be running at IRQL PASSIVE_LEVEL.
//
NTSTATUS
KS_OpenTransportAddress(
IN PWSTR TransportDeviceNameW,// Zero-terminated String
IN PTRANSPORT_ADDRESS pTransportAddress, // Local Transport Address
PKS_ADDRESS pKS_Address
)
{
NTSTATUS Status = STATUS_SUCCESS;
UNICODE_STRING TransportDeviceName;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
ULONG TransportAddressLength;
ULONG TransportEaBufferLength;
PFILE_FULL_EA_INFORMATION pTransportAddressEa;
PDEVICE_OBJECT pDeviceObject;
ASSERT( pKS_Address );
//
// Initialize KS_ADDRESS Structure
//
pKS_Address->m_nStatus = STATUS_UNSUCCESSFUL;
pKS_Address->m_pFileObject = NULL;
pKS_Address->m_pAtomicIrp = NULL;
pKS_Address->m_ReferenceCount = 1;
InitializeListHead( &pKS_Address->m_ConnectionList );
TransportAddressLength = KS_TransportAddressLength( pTransportAddress );
//
// Setup Transport Device Name
//
NdisInitUnicodeString( &TransportDeviceName, TransportDeviceNameW );
//
// Build an EA buffer for the specified transport address
//
Status = KS_BuildEaBuffer(
TDI_TRANSPORT_ADDRESS_LENGTH, // EaName Length
TdiTransportAddress, // EaName
TransportAddressLength, // EaValue Length
pTransportAddress, // EaValue
&pTransportAddressEa,
&TransportEaBufferLength
);
if( !NT_SUCCESS(Status) )
{
return( pKS_Address->m_nStatus = Status );
}
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
InitializeObjectAttributes(
&ObjectAttributes, // OBJECT_ATTRIBUTES instance
&TransportDeviceName, // Transport Device Name
OBJ_CASE_INSENSITIVE, // Attributes
NULL, // RootDirectory
NULL // SecurityDescriptor
);
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
//
// Call Transport To Create Transport Address Object
//
Status = ZwCreateFile(
&pKS_Address->m_hAddress, // Handle
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, // Desired Access
&ObjectAttributes, // Object Attributes
&IoStatusBlock, // Final I/O status block
0, // Allocation Size
FILE_ATTRIBUTE_NORMAL, // Normal attributes
FILE_SHARE_READ, // Sharing attributes
FILE_OPEN_IF, // Create disposition
0, // CreateOptions
pTransportAddressEa, // EA Buffer
TransportEaBufferLength // EA length
);
//
// Free up the EA buffer allocated.
//
ExFreePool( (PVOID )pTransportAddressEa );
if (NT_SUCCESS(Status))
{
//
// Obtain a referenced pointer to the file object.
//
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
Status = ObReferenceObjectByHandle(
pKS_Address->m_hAddress, // Object Handle
FILE_ANY_ACCESS, // Desired Access
NULL, // Object Type
KernelMode, // Processor mode
(PVOID *)&pKS_Address->m_pFileObject, // File Object pointer
NULL // Object Handle information
);
pDeviceObject = IoGetRelatedDeviceObject( pKS_Address->m_pFileObject );
//
// Allocate IRP For General Purpose Use
//
pKS_Address->m_pAtomicIrp = IoAllocateIrp(
pDeviceObject->StackSize,
FALSE
);
if( !pKS_Address->m_pAtomicIrp )
{
KS_CloseTransportAddress( pKS_Address );
return( pKS_Address->m_nStatus = STATUS_INSUFFICIENT_RESOURCES );
}
}
if (NT_SUCCESS(Status))
{
}
else
{
}
return( pKS_Address->m_nStatus = Status );
}
/////////////////////////////////////////////////////////////////////////////
//// _I_KS_RefTransportAddress (INTERNAL/PRIVATE)
//
// Purpose
// This routine increments the reference count on the transport address.
//
// Parameters
// pKS_Address
// Pointer to the KS_ADDRESS structure whose reference count should
// be incremented.
//
// Return Value
// None.
//
// Remarks
//
VOID
_I_KS_RefTransportAddress(
PKS_ADDRESS pKS_Address
)
{
ASSERT( pKS_Address );
ASSERT( pKS_Address->m_ReferenceCount > 0 );
if( pKS_Address )
{
InterlockedIncrement( &pKS_Address->m_ReferenceCount );
}
}
/////////////////////////////////////////////////////////////////////////////
//// _I_KS_DestroyTransportAddress (INTERNAL/PRIVATE)
//
// Purpose
// This routine destroys the transport address object.
//
// Parameters
// pKS_Address
// Pointer to the KS_ADDRESS structure that specifies the transport
// address object pointer and handle to be destroyed.
//
// Return Value
// Status
//
// Remarks
// This function will free resources allocated in KS_OpenTransportAddress,
// dereference the transport address file object pointer anc actually
// close the transport address file handle.
//
// Callers of _I_KS_DestroyTransportAddress must be running at IRQL
// PASSIVE_LEVEL.
//
NTSTATUS
_I_KS_DestroyTransportAddress(
PKS_ADDRESS pKS_Address
)
{
NTSTATUS Status = STATUS_SUCCESS;
KdPrint(("KS_DestroyTransportAddress: Entry...\n"));
ASSERT( pKS_Address );
ASSERT( pKS_Address->m_ReferenceCount == 0 );
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
ASSERT( IsListEmpty( &pKS_Address->m_ConnectionList ) );
if( !pKS_Address )
{
return( STATUS_SUCCESS );
}
//
// Free IRP Allocated For Receiveing
//
if( pKS_Address->m_pAtomicIrp )
{
IoFreeIrp( pKS_Address->m_pAtomicIrp );
}
pKS_Address->m_pAtomicIrp = NULL;
//
// Free IRP Allocated For Sending
//
//
// Dereference The File Object
//
if( pKS_Address->m_pFileObject != NULL )
{
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
ObDereferenceObject( pKS_Address->m_pFileObject );
}
pKS_Address->m_pFileObject = NULL;
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
ZwClose( pKS_Address->m_hAddress );
return Status;
}
/////////////////////////////////////////////////////////////////////////////
//// _I_KS_DerefTransportAddress (INTERNAL/PRIVATE)
//
// Purpose
// This routine decrements the reference count on the transport address.
//
// Parameters
// pKS_Address
// Pointer to the KS_ADDRESS structure whose reference count should be
// decremented.
//
// Return Value
// None.
//
// Remarks
// The KS_ADDRESS structure will continue to exist until the reference count
// is deceremented to zero. When ther reference count is decremented to zero
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -