📄 ksutil.c
字号:
pDeviceObject = IoGetRelatedDeviceObject( pKS_Address->m_pFileObject );
//
// Allocate IRP For Receiving
//
pReceiveIrp = IoAllocateIrp( pDeviceObject->StackSize, FALSE );
if( !pReceiveIrp )
{
return( STATUS_INSUFFICIENT_RESOURCES );
}
Length = 0;
pNextMdl = pReceiveMdl;
while( pNextMdl )
{
Length += MmGetMdlByteCount( pNextMdl );
pNextMdl = pNextMdl->Next;
}
TdiBuildReceiveDatagram(
pReceiveIrp,
pDeviceObject,
pKS_Address->m_pFileObject,
_I_KS_AddressRequestComplete, // Completion routine
pKS_RequestContext, // Completion context
pReceiveMdl, // the data buffer
Length, // send buffer length
pReceiveDatagramInfo,
pReturnInfo,
InFlags
);
//
// Reference The Address Object
//
_I_KS_RefTransportAddress( pKS_RequestContext->m_pKS_Address );
//
// Submit the request
//
(pKS_RequestContext->m_pIoStatusBlock)->Status = STATUS_UNSUCCESSFUL;
(pKS_RequestContext->m_pIoStatusBlock)->Information = 0;
Status = IoCallDriver( pDeviceObject, pReceiveIrp );
if( bSynchronous )
{
if( (Status == STATUS_SUCCESS) || (Status == STATUS_PENDING) )
{
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
Status = KeWaitForSingleObject(
&SyncEvent, // Object to wait on.
Executive, // Reason for waiting
KernelMode, // Processor mode
FALSE, // Alertable
NULL // Timeout
);
if( NT_SUCCESS( Status ) )
{
Status = pReceiveIrp->IoStatus.Status;
}
}
}
if( !NT_SUCCESS( Status ) )
{
//
// Handle Case Where Completion Function Will Not Be Called...
//
//
// Dereference The Address Object
//
_I_KS_DerefTransportAddress( pKS_RequestContext->m_pKS_Address );
//
// Free Memory Allocated For Private Completion Context
//
NdisFreeMemory(
pKS_RequestContext,
sizeof( KS_ADDRESS_REQUEST_CONTEXT ),
0
);
IoFreeIrp( pReceiveIrp );
}
return( Status );
}
/////////////////////////////////////////////////////////////////////////////
//// KS_QueryAddressInfo
//
// Purpose
// KS_QueryAddressInfo makes a TDI_QUERY_INFORMATION request for
// TDI_QUERY_ADDRESS_INFO for the transport address or connection endpoint
// specified by its file object pointer.
//
// Parameters
// pFileObject
// Can be either a TDI transport address file object (from KS_ADDRESS)
// or TDI connection endpoint file object (from KS_ENDPOINT).
//
// pInfoBuffer
// Must point to a buffer sufficiently large to hold a TDI_ADDRESS_INFO
// structure for a TDI_ADDRESS_IP.
//
// pInfoBufferSize
// Pointer to a ULONG. On entry, the ULONG pointed to by pInfoBufferSize
// must be initialized with the size of the buffer at pInfoBuffer. On
// return, the ULONG pointed to by pInfoBufferSize will be updated to
// indicate the length of the data written to pInfoBuffer.
//
// Return Value
//
// Remarks
// This function is roughly the TDI equivalent of the Winsock getsockname
// function.
//
// Callers of KS_QueryAddressInfo must be running at IRQL PASSIVE_LEVEL.
//
// The information returned from TDI_QUERY_ADDRESS_INFO depends on the
// type of the file object:
//
// Transport Address File Object:
// in_addr: 0.0.0.0; sin_port: 1042 (0x412)
//
// Connection Endpoint File Object:
// in_addr: 172.16.1.130; sin_port: 1042 (0x412)
//
// On reflection, this makes sense. An address object has a unique port
// number, but can be used on multiple host IP addresses on a multihomed
// host. Hence, the IP address is zero.
//
// However, once a connection is established the network interface is
// also established. Hence, the IP address on a connected connection
// endpoint is non-zero.
//
NTSTATUS
KS_QueryAddressInfo(
PFILE_OBJECT pFileObject,
PVOID pInfoBuffer,
PULONG pInfoBufferSize
)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
IO_STATUS_BLOCK IoStatusBlock;
PIRP pIrp = NULL;
PMDL pMdl = NULL;
PDEVICE_OBJECT pDeviceObject;
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
pDeviceObject = IoGetRelatedDeviceObject( pFileObject );
RtlZeroMemory( pInfoBuffer, *pInfoBufferSize );
//
// Allocate IRP For The Query
//
pIrp = IoAllocateIrp( pDeviceObject->StackSize, FALSE );
if( !pIrp )
{
return( STATUS_INSUFFICIENT_RESOURCES );
}
pMdl = KS_AllocateAndProbeMdl(
pInfoBuffer, // Virtual address for MDL construction
*pInfoBufferSize, // size of the buffer
FALSE,
FALSE,
NULL
);
if( !pMdl )
{
IoFreeIrp( pIrp );
return( STATUS_INSUFFICIENT_RESOURCES );
}
TdiBuildQueryInformation(
pIrp,
pDeviceObject,
pFileObject,
_I_KS_SimpleTdiRequestComplete, // Completion routine
NULL, // Completion context
TDI_QUERY_ADDRESS_INFO,
pMdl
);
//
// Submit The Query To The Transport
//
Status = KS_MakeSimpleTdiRequest(
pDeviceObject,
pIrp
);
//
// Free Allocated Resources
//
KS_UnlockAndFreeMdl(pMdl);
*pInfoBufferSize = pIrp->IoStatus.Information;
IoFreeIrp( pIrp );
return( Status );
}
/////////////////////////////////////////////////////////////////////////////
// E N D P O I N T F U N C T I O N S //
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//// _I_KS_OpenConnectionContext (INTERNAL/PRIVATE)
//
// Purpose
// Open a TDI connection context object on the specified transport
// device.
//
// Parameters
// TransportDeviceNameW
// Pointer to a zero-terminated wide character string that specifies
// the transport device. An example would be: L"\\Device\\Tcp"
//
//
// Return Value
// Status
//
// Remarks
// See the NT DDK documentation topic "5.2 Opening a Connection Endpoint"
// for more information.
//
// It is important to note that the call to ZwCreateFile creates a
// client-process-specific file object that represents the connection
// endpoint object. This means that the m_hContext 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 connection
// context handle can be performed in arbitrary context unless there are
// other restrictions.
//
// The client process dependency of the connection context handle does effect
// the design of a TDI Client to some extent. In particular, the the client
// process that was used to create a connection contect object must
// continue to exist until the connection context object is eventually closed.
//
// There are several ways to insure that the client process continues
// to exist while the connection context 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 connection context object
// handle will remain valid.
//
// Callers of _I_KS_OpenConnectionContext must be running at IRQL PASSIVE_LEVEL.
//
NTSTATUS
_I_KS_OpenConnectionContext(
IN PWSTR TransportDeviceNameW,// Zero-terminated String
PKS_ENDPOINT pKS_Endpoint,
PVOID pContext
)
{
NTSTATUS Status = STATUS_SUCCESS;
UNICODE_STRING TransportDeviceName;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
ULONG TransportEaBufferLength;
PFILE_FULL_EA_INFORMATION pConnectionContextEa;
//
// Initialize Context-Related Fields
//
pKS_Endpoint->m_nOpenStatus = STATUS_UNSUCCESSFUL;
pKS_Endpoint->m_pFileObject = NULL;
//
// Setup Transport Device Name
//
NdisInitUnicodeString( &TransportDeviceName, TransportDeviceNameW );
//
// Build An EA Buffer For The Connection Context
// ---------------------------------------------
// The EaValue will be the ConnectionContext passed to various
// TDI EventHandler routines.
//
Status = KS_BuildEaBuffer(
TDI_CONNECTION_CONTEXT_LENGTH, // EaName Length
TdiConnectionContext, // EaName
sizeof( PVOID ), // EaValue Length
&pContext, // EaValue
&pConnectionContextEa,
&TransportEaBufferLength
);
if( !NT_SUCCESS(Status) )
{
return( pKS_Endpoint->m_nOpenStatus = 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 Connection Endpoint Object
//
Status = ZwCreateFile(
&pKS_Endpoint->m_hContext, // 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
pConnectionContextEa, // EA Buffer
TransportEaBufferLength // EA length
);
if (NT_SUCCESS(Status))
{
//
// Obtain a referenced pointer to the file object.
//
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
Status = ObReferenceObjectByHandle(
pKS_Endpoint->m_hContext,// Object Handle
FILE_ANY_ACCESS, // Desired Access
NULL, // Object Type
KernelMode, // Processor mode
(PVOID *)&pKS_Endpoint->m_pFileObject, // File Object pointer
NULL // Object Handle information
);
}
//
// Free up the EA buffer allocated.
//
ExFreePool( (PVOID )pConnectionContextEa );
return( pKS_Endpoint->m_nOpenStatus = Status );
}
/////////////////////////////////////////////////////////////////////////////
//// _I_KS_CloseConnectionContext (INTERNAL/PRIVATE)
//
// Purpose
// This routine closes the connection context (endpoint) object.
//
// Parameters
//
// Return Value
// Status
//
// Remarks
// Callers of _I_KS_CloseConnectionContext must be running at IRQL PASSIVE_LEVEL.
//
NTSTATUS
_I_KS_CloseConnectionContext(
PKS_ENDPOINT pKS_Endpoint
)
{
NTSTATUS Status = STATUS_SUCCESS;
KdPrint(("_I_KS_CloseConnectionContext: Entry...\n"));
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
//
// Dereference The File Object
//
if( pKS_Endpoint->m_pFileObject != NULL )
{
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
ObDereferenceObject( pKS_Endpoint->m_pFileObject );
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
ZwClose( pKS_Endpoint->m_hContext );
}
pKS_Endpoint->m_pFileObject = NULL;
return Status;
}
/////////////////////////////////////////////////////////////////////////////
//// _I_KS_AssociateAddress (INTERNAL/PRIVATE)
//
// Purpose
//
// Parameters
// pKS_Address
// Pointer to the KS_ADDRESS structure that specifies the transport
// address object to associated with a connection endpoint object.
//
// Return Value
// Status
//
// Remarks
//
NTSTATUS
_I_KS_AssociateAddress(
PKS_ADDRESS pKS_Address,
PKS_ENDPOINT pKS_Endpoint
)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -