📄 ksutil.c
字号:
{
PDEVICE_OBJECT pDeviceObject;
pKS_Endpoint->m_pKS_Address = NULL;
pKS_Endpoint->m_nAssociateStatus = STATUS_UNSUCCESSFUL;
pDeviceObject = IoGetRelatedDeviceObject( pKS_Address->m_pFileObject );
//
// Associate the local endpoint with the address object.
//
TdiBuildAssociateAddress(
pKS_Address->m_pAtomicIrp,
pDeviceObject,
pKS_Endpoint->m_pFileObject,
NULL,
NULL,
pKS_Address->m_hAddress
);
//
// Submit The Request To The Transport
//
pKS_Endpoint->m_nAssociateStatus = KS_MakeSimpleTdiRequest(
pDeviceObject,
pKS_Address->m_pAtomicIrp
);
if( NT_SUCCESS( pKS_Endpoint->m_nAssociateStatus ) )
{
pKS_Endpoint->m_pKS_Address = pKS_Address;
_I_KS_RefTransportAddress( pKS_Endpoint->m_pKS_Address );
}
return( pKS_Endpoint->m_nAssociateStatus );
}
/////////////////////////////////////////////////////////////////////////////
//// _I_KS_DisassociateAddress (INTERNAL/PRIVATE)
//
// Purpose
//
// Parameters
//
// Return Value
// Status
//
// Remarks
//
NTSTATUS
_I_KS_DisassociateAddress(
PKS_ENDPOINT pKS_Endpoint
)
{
NTSTATUS Status = STATUS_SUCCESS;
PDEVICE_OBJECT pDeviceObject;
pDeviceObject = IoGetRelatedDeviceObject( pKS_Endpoint->m_pFileObject );
// Disassociate the local endpoint with the address object.
if( pKS_Endpoint->m_pKS_Address )
{
TdiBuildDisassociateAddress(
(pKS_Endpoint->m_pKS_Address)->m_pAtomicIrp,
pDeviceObject,
pKS_Endpoint->m_pFileObject,
NULL,
NULL
);
//
// Submit The Request To The Transport
//
Status = KS_MakeSimpleTdiRequest(
pDeviceObject,
(pKS_Endpoint->m_pKS_Address)->m_pAtomicIrp
);
}
if( NT_SUCCESS( Status ) )
{
if( pKS_Endpoint->m_pKS_Address )
{
_I_KS_DerefTransportAddress( pKS_Endpoint->m_pKS_Address );
}
}
return( Status );
}
/////////////////////////////////////////////////////////////////////////////
//// KS_OpenConnectionEndpoint
//
// Purpose
// Open a new TDI connection endpoint and associate it with a specified
// transport address object.
//
// Parameters
// TransportDeviceNameW
// Pointer to a zero-terminated wide character string that specifies
// the transport device. An example would be: L"\\Device\\Tcp"
//
// pKS_Address
// Pointer to the KS_ADDRESS structure previously opened using the
// LS_OpenTransportAddress function. The KS_ADDRESS pointer specifies
// the transport address object to be used with the new connection
// endpoint.
//
// pKS_Endpoint
// Pointer to a caller-provided KS_ENDPOINT structure that will be
// initialized as the connection endpoint is opened.
//
// pContext
// This is actually an arbitrary value provided by the caller. The value
// passed as pContext here will simply be returned as TdiEventContex when
// TDI event handlers are called. Typically pContext is actually a pointer
// to a structure of interest to the caller.
//
// Return Value
// Status
//
// Remarks
// This function combines several of the steps involved in opening a connection
// endpoint into one convenient function.
//
// Before calling this function the caller must have already opened a transport
// address object using KS_OpenTransportAddress.
//
// This function performs most of the mechanics of opening a TDI connection endpoint
// object. It builds the extended attributes (EA) buffer, calls ZwCreateFile and
// obtains a pointer to the connection endpoint object file pointer by calling
// ObReferenceObjectByHandle. If these operations are successful, the function calls
// an internal function called _I_KS_AssociateAddress to associate the new connection
// endpoint with the specified transport address.
//
// The connection endpoint object handle and its file pointer are stored in the
// KS_ENDPOINT structure. A pointer to a KS_ENDPOINT structure that has been successfully
// initialized by KS_OpenConnectionEndpoint is used by subsequent calls that operate
// on a connection endpoint.
//
// It is important to note that KS_OpenConnectionEndpoint will call ZwCreateFile in the
// process of opening a connection endpoint. 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 handle can be performed
// in arbitrary context unless there are other restrictions.
//
// The client process dependency of the connection endpoint handle does affect the design
// of a TDI Client to some extent. In particular, the client process that was used to
// create an connection endpoint object must continue to exist until the connection endpoint
// object is eventually closed.
//
// There are several ways to insure that the client process continues to exist while
// the connection endpoint 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 endpoint object handle will remain valid.
//
// See the NT DDK documentation topic "5.2 Opening a Connection Endpoint" for more
// information.
//
// Callers of KS_OpenConnectionEndpoint must be running at IRQL PASSIVE_LEVEL.
//
NTSTATUS
KS_OpenConnectionEndpoint(
IN PWSTR TransportDeviceNameW,// Zero-terminated String
PKS_ADDRESS pKS_Address,
PKS_ENDPOINT pKS_Endpoint,
PVOID pContext
)
{
NTSTATUS Status;
KdPrint(("KS_OpenConnectionEndpoint: Entry...\n") );
ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
//
// Initialize KS_CONTEXT Structure
//
NdisZeroMemory( pKS_Endpoint, sizeof( KS_ENDPOINT ) );
pKS_Endpoint->m_ReferenceCount = 1;
pKS_Endpoint->m_pKS_Address = NULL;
//
// Open Connection Context
//
Status = _I_KS_OpenConnectionContext(
TransportDeviceNameW,
pKS_Endpoint,
pContext
);
if( !NT_SUCCESS( Status ) )
{
return( pKS_Endpoint->m_nOpenStatus );
}
KdPrint(("KS_OpenConnectionEndpoint: Opened Connection Context\n") );
//
// Associate Address
//
Status = _I_KS_AssociateAddress( pKS_Address, pKS_Endpoint );
if( NT_SUCCESS( Status ) )
{
KdPrint(("KS_OpenConnectionEndpoint: Associated Address\n") );
//
// Add The Connection To The Address Object's Connection List
//
InsertTailList(
&pKS_Address->m_ConnectionList,
&pKS_Endpoint->m_ListElement
);
}
return( pKS_Endpoint->m_nAssociateStatus );
}
/////////////////////////////////////////////////////////////////////////////
//// _I_KS_RefConnectionEndpoint (INTERNAL/PRIVATE)
//
// Purpose
// This routine increments the reference count on the connection endpoint.
//
// Parameters
//
// Return Value
// None.
//
// Remarks
//
VOID
_I_KS_RefConnectionEndpoint(
PKS_ENDPOINT pKS_Endpoint
)
{
InterlockedIncrement( &pKS_Endpoint->m_ReferenceCount );
}
/////////////////////////////////////////////////////////////////////////////
//// _I_KS_DestroyConnection (INTERNAL/PRIVATE)
//
// Purpose
//
// Parameters
//
// Return Value
// Status
//
// Remarks
//
NTSTATUS
_I_KS_DestroyConnection(
PKS_ENDPOINT pKS_Endpoint
)
{
NTSTATUS Status;
//
// About Disassociate Address
// --------------------------
// Logically one would think it appropriate to call _I_KS_DisassociateAddress
// at this point. However, the NT DDK TDI documentation states that when
// closing a connection endpoint it is unnecessary "to disassociate
// the connection endpoint from from its associated transport address
// before making a close-connection-endpoint request".
//
// Further, on TCP it appears that a call to _I_KS_DisassociateAddress
// will often fail with STATUS_CONNECTION_ACTIVE (0xC000023B).
//
// So, instead of calling _I_KS_DisassociateAddress we just remove
// the reference counts to the transport address and connection context
// objects that was created by _I_KS_AssociateAddress.
//
_I_KS_DerefTransportAddress( pKS_Endpoint->m_pKS_Address );
//
// Remove The Connection To The Address Object's Connection List
//
RemoveEntryList( &pKS_Endpoint->m_ListElement );
//
// Close Connection Context
//
Status = _I_KS_CloseConnectionContext( pKS_Endpoint );
#ifdef DBG
if( NT_SUCCESS( Status ) )
{
KdPrint(("KS_DestroyConnection: Closed Connection Context\n") );
}
#endif // DBG
return( Status );
}
/////////////////////////////////////////////////////////////////////////////
//// _I_KS_DerefConnectionEndpoint (INTERNAL/PRIVATE)
//
// Purpose
// This routine decrements the reference count on the connection endpoint.
//
// Parameters
//
// Return Value
// None.
//
// Remarks
//
VOID
_I_KS_DerefConnectionEndpoint(
PKS_ENDPOINT pKS_Endpoint
)
{
LONG Result;
Result = InterlockedDecrement( &pKS_Endpoint->m_ReferenceCount );
if( !Result )
{
//
// Destroy The Connection
//
_I_KS_DestroyConnection( pKS_Endpoint );
}
}
/////////////////////////////////////////////////////////////////////////////
//// KS_CloseConnectionEndpoint
//
// Purpose
// KS_CloseConnectionEndpoint closes the connection endpoint specified by
// pKS_ENDPOINT.
//
// Parameters
// pKS_Endpoint
// Pointer to the KS_ENDPOINT structure that specifies the connection endpoint
// object pointer and handle to be closed.
//
// Return Value
// Status
//
// Remarks
// This function calls the internal function _I_KS_DerefConnectionEndpoint to
// decrement the reference count for the KS_ENDPOINT structure. If the reference
// count is decremented to zero by this call, the connection endpoint object
// specified by pKS_ENDPOINT will actually be closed.
//
// Callers of KS_CloseConnectionEndpoint must be running at IRQL PASSIVE_LEVEL.
//
NTSTATUS
KS_CloseConnectionEndpoint(
PKS_ENDPOINT pKS_Endpoint
)
{
KdPrint(("KS_CloseConnectionEndpoint: Entry...\n"));
_I_KS_DerefConnectionEndpoint( pKS_Endpoint );
return( STATUS_SUCCESS );
}
/////////////////////////////////////////////////////////////////////////////
//// KS_Connect
//
// Purpose
// This routine establishes a connection between a local connection endpoint
// and a remote transport address.
//
// Parameters
// pKS_Endpoint
// Pointer to the KS_ENDPOINT structure that specifies the local connection
// endpoint object pointer to be used.
// pTransportAddress
// Pointer to a TRANSPORT_ADDRESS structure that specifies the remote
// connection address for the connection.
//
// Return Value
//
// Remarks
// For a local-node client to establish an endpoint-to-endpoint connection
// with a remote-node peer process, it must first associate an idle local
// connection endpoint with a local-node address. A client cannot initiate a
// connection attempt to a remote-node peer until it has made a successful
// TDI_ASSOCIATE_ADDRESS request, which it set up with TdiBuildAsociateAddress,
// to its underlying transport.
//
// It terms of the KS library functions, this means that the KS_ENDPOINT
// structure pointed to by pKS_Endpoint must have been successfully initialized
// by calling KS_OpenConntectionEndpoint.
//
// See the NT DDK documentation topic "5.5 Making an Endpoint-to-Endpoint
// Connection" for more information.
//
// As currently written, callers of KS_Connect must be running at
// IRQL PASSIVE_LEVEL.
//
NTSTATUS
KS_Connect(
PKS_ENDPOINT pKS_Endpoint,
IN PTRANSPORT_ADDRESS pTransportAddress // Remote Transport Address
)
{
NTSTATUS Status = STATUS_SUCCESS;
TDI_CONNECTION_INFORMATION RequestConnectionInfo;
// TDI_CONNECTION_INFORMATION ReturnConnectionInfo;
LARGE_INTEGER ConnectionTimeOut = {0,0};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -