mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
534 lines
14 KiB
534 lines
14 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
rxce.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the RXCE routines related to binding/unbinding, dynamic
|
|
enabling/disabling of transports.
|
|
|
|
Revision History:
|
|
|
|
Balan Sethu Raman [SethuR] 15-Feb-1995
|
|
|
|
Notes:
|
|
|
|
The number of transport bindings are in all probability very few ( mostly one or two).
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, RxCeBuildTransport)
|
|
#pragma alloc_text(PAGE, RxCeTearDownTransport)
|
|
#pragma alloc_text(PAGE, RxCeQueryAdapterStatus)
|
|
#pragma alloc_text(PAGE, RxCeQueryTransportInformation)
|
|
#pragma alloc_text(PAGE, DuplicateTransportAddress)
|
|
#pragma alloc_text(PAGE, RxCeBuildAddress)
|
|
#pragma alloc_text(PAGE, RxCeTearDownAddress)
|
|
#endif
|
|
|
|
//
|
|
// The debug trace level
|
|
//
|
|
|
|
#define Dbg (DEBUG_TRACE_RXCEBINDING)
|
|
|
|
|
|
NTSTATUS
|
|
RxCeBuildTransport(
|
|
IN OUT PRXCE_TRANSPORT pTransport,
|
|
IN PUNICODE_STRING pTransportName,
|
|
IN ULONG QualityOfService)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine binds to the transport specified.
|
|
|
|
Arguments:
|
|
|
|
|
|
pTransportName - the binding string for the desired transport
|
|
|
|
QualityOfService - the quality of service desired from the transport.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - if the call was successfull.
|
|
|
|
Notes:
|
|
|
|
The RDBSS or RXCE do not paticipate in the computation of quality
|
|
of service. They essentially use it as a magic number that needs
|
|
to be passed to the underlying transport provider.
|
|
|
|
At present we ignore the QualityOfService parameter. How should a request for
|
|
binding to a transport that has been currently bound to with a lower quality of
|
|
service be handled?
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
PAGED_CODE();
|
|
|
|
// Update profiling info.
|
|
RxProfile(RxCeBinding,RxCeBindToTransport);
|
|
|
|
try {
|
|
pTransport->Signature = RXCE_TRANSPORT_SIGNATURE;
|
|
|
|
pTransport->ConnectionCount = 0;
|
|
pTransport->VirtualCircuitCount = 0;
|
|
pTransport->pDeviceObject = NULL;
|
|
pTransport->ControlChannel = INVALID_HANDLE_VALUE;
|
|
pTransport->pControlChannelFileObject = NULL;
|
|
|
|
pTransport->Name.MaximumLength = pTransportName->Length;
|
|
pTransport->Name.Length = pTransportName->Length;
|
|
|
|
pTransport->pProviderInfo
|
|
= RxAllocatePoolWithTag(
|
|
PagedPool,
|
|
sizeof(RXCE_TRANSPORT_PROVIDER_INFO),
|
|
RXCE_TRANSPORT_POOLTAG);
|
|
|
|
|
|
pTransport->Name.Buffer = RxAllocatePoolWithTag(
|
|
NonPagedPool,
|
|
pTransport->Name.Length,
|
|
RXCE_TRANSPORT_POOLTAG);
|
|
|
|
if ((pTransport->pProviderInfo != NULL) &&
|
|
(pTransport->Name.Buffer != NULL)) {
|
|
RtlCopyMemory(
|
|
pTransport->Name.Buffer,
|
|
pTransportName->Buffer,
|
|
pTransport->Name.Length);
|
|
|
|
// Initialize the transport information.
|
|
Status = RxTdiBindToTransport(
|
|
pTransport);
|
|
|
|
// Ensure that the quality of service criterion is met.
|
|
|
|
// Cleanup if the operation was not successfull.
|
|
if (!NT_SUCCESS(Status)) {
|
|
RxDbgTrace(0, Dbg, ("RxTdiBindToTransport returned %lx\n",Status));
|
|
RxCeTearDownTransport(pTransport);
|
|
} else {
|
|
pTransport->QualityOfService = QualityOfService;
|
|
}
|
|
} else {
|
|
RxCeTearDownTransport(pTransport);
|
|
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
} finally {
|
|
if (AbnormalTermination()) {
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
RxLog(("RxCeBindToTransport T: %lx\n",pTransport));
|
|
RxWmiLog(LOG,
|
|
RxCeBuildTransport,
|
|
LOGPTR(pTransport));
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
RxCeTearDownTransport(
|
|
IN PRXCE_TRANSPORT pTransport)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine unbinds from the transport specified.
|
|
|
|
Arguments:
|
|
|
|
pTransport - the transport instance
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - if the call was successfull.
|
|
|
|
Notes:
|
|
|
|
if a transport that has not been bound to is specified no error is
|
|
returned. The operation trivially succeeds.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
PAGED_CODE();
|
|
|
|
// Update profiling info.
|
|
RxProfile(RxCeBinding,RxCeUnbindFromTransport);
|
|
|
|
try {
|
|
if (RxCeIsTransportValid(pTransport)) {
|
|
if (pTransport->pDeviceObject != NULL) {
|
|
Status = RxTdiUnbindFromTransport(pTransport);
|
|
}
|
|
|
|
RxDbgTrace(0, Dbg,("RxTdiUnbindFromTransport returned %lx\n",Status));
|
|
|
|
if (pTransport->Name.Buffer != NULL) {
|
|
RxFreePool(pTransport->Name.Buffer);
|
|
}
|
|
|
|
if (pTransport->pProviderInfo != NULL ) {
|
|
RxFreePool(pTransport->pProviderInfo);
|
|
}
|
|
|
|
pTransport->ConnectionCount = 0;
|
|
pTransport->VirtualCircuitCount = 0;
|
|
pTransport->pProviderInfo = NULL;
|
|
pTransport->pDeviceObject = NULL;
|
|
pTransport->ControlChannel = INVALID_HANDLE_VALUE;
|
|
pTransport->pControlChannelFileObject = NULL;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
} finally {
|
|
if (AbnormalTermination()) {
|
|
RxLog(("RxCeTdT: T: %lx\n",pTransport));
|
|
RxWmiLog(LOG,
|
|
RxCeTearDownTransport,
|
|
LOGPTR(pTransport));
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
RxCeQueryAdapterStatus(
|
|
PRXCE_TRANSPORT pTransport,
|
|
PADAPTER_STATUS pAdapterStatus)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns the name of a given transport in a caller allocated buffer
|
|
|
|
Arguments:
|
|
|
|
pTransport - the RXCE_TRANSPORT instance
|
|
|
|
pAdapterStatus - the adapter status of the transport
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - if the call was successfull.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_INVALID_PARAMETER;
|
|
|
|
PAGED_CODE();
|
|
|
|
try {
|
|
if (RxCeIsTransportValid(pTransport)) {
|
|
Status = RxTdiQueryAdapterStatus(pTransport,pAdapterStatus);
|
|
}
|
|
} finally {
|
|
if (AbnormalTermination()) {
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
RxLog(("RXCeQAS: T: %lx\n",pTransport));
|
|
RxWmiLog(LOG,
|
|
RxCeQueryAdapterStatus,
|
|
LOGPTR(pTransport));
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
RxCeQueryTransportInformation(
|
|
PRXCE_TRANSPORT pTransport,
|
|
PRXCE_TRANSPORT_INFORMATION pTransportInformation)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns the transport information for a given transport
|
|
|
|
Arguments:
|
|
|
|
pTransport - the RXCE_TRANSPORT
|
|
|
|
pTransportInformation - the information for the transport
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS - if the call was successfull.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_INVALID_PARAMETER;
|
|
|
|
PRXCE_TRANSPORT_PROVIDER_INFO pProviderInfo;
|
|
|
|
PAGED_CODE();
|
|
|
|
try {
|
|
if (RxCeIsTransportValid(pTransport)) {
|
|
pProviderInfo = (PRXCE_TRANSPORT_PROVIDER_INFO)pTransportInformation;
|
|
|
|
*pProviderInfo = *(pTransport->pProviderInfo);
|
|
pTransportInformation->ConnectionCount = pTransport->ConnectionCount;
|
|
pTransportInformation->QualityOfService = pTransport->QualityOfService;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
} finally {
|
|
if (AbnormalTermination()) {
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
RxLog(("RXCeQTI: T: %lx\n",pTransport));
|
|
RxWmiLog(LOG,
|
|
RxCeQueryTransportInformation,
|
|
LOGPTR(pTransport));
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
DuplicateTransportAddress(
|
|
PTRANSPORT_ADDRESS *pCopy,
|
|
PTRANSPORT_ADDRESS pOriginal,
|
|
POOL_TYPE PoolType)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine duplicates a transport addresses.
|
|
|
|
Arguments:
|
|
|
|
pCopy - the pointer to the new copy
|
|
|
|
pOriginal - the original.
|
|
|
|
PoolType - type of pool for memory allocation
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS if successful.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
ULONG Size = ComputeTransportAddressLength(pOriginal);
|
|
|
|
PAGED_CODE();
|
|
|
|
*pCopy = (PTRANSPORT_ADDRESS)
|
|
RxAllocatePoolWithTag(
|
|
PoolType,
|
|
Size,
|
|
RXCE_TRANSPORT_POOLTAG);
|
|
|
|
if (*pCopy != NULL) {
|
|
|
|
RtlCopyMemory(*pCopy,pOriginal,Size);
|
|
|
|
return STATUS_SUCCESS;
|
|
} else
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
NTSTATUS
|
|
RxCeBuildAddress(
|
|
IN OUT PRXCE_ADDRESS pAddress,
|
|
IN PRXCE_TRANSPORT pTransport,
|
|
IN PTRANSPORT_ADDRESS pTransportAddress,
|
|
IN PRXCE_ADDRESS_EVENT_HANDLER pHandler,
|
|
IN PVOID pEventContext)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine associated a transport address with a transport binding.
|
|
|
|
Arguments:
|
|
|
|
pAddress - the address instance
|
|
|
|
pTransport - the transport with whihc this address is to be associated
|
|
|
|
pTransportAddress - the transport address to be associated with the binding
|
|
|
|
pHandler - the event handler associated with the registration.
|
|
|
|
pEventContext - the context parameter to be passed back to the event handler
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS if successfull.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_INVALID_PARAMETER;
|
|
|
|
PAGED_CODE();
|
|
|
|
// Update profiling info.
|
|
RxProfile(RxCeManagement,RxCeRegisterClientAddress);
|
|
|
|
try {
|
|
if (RxCeIsTransportValid(pTransport)) {
|
|
pAddress->Signature = RXCE_ADDRESS_SIGNATURE;
|
|
|
|
pAddress->pTransport = pTransport;
|
|
pAddress->hAddress = INVALID_HANDLE_VALUE;
|
|
pAddress->pFileObject = NULL;
|
|
pAddress->pHandler = NULL;
|
|
pAddress->pTransportAddress = NULL;
|
|
pAddress->pReceiveMdl = NULL;
|
|
|
|
// Allocate the mmeory for the event handling dispatch vector
|
|
pAddress->pHandler = (PRXCE_ADDRESS_EVENT_HANDLER)
|
|
RxAllocatePoolWithTag(
|
|
NonPagedPool,
|
|
sizeof(RXCE_ADDRESS_EVENT_HANDLER),
|
|
RXCE_ADDRESS_POOLTAG);
|
|
|
|
if (pAddress->pHandler != NULL) {
|
|
RtlZeroMemory(
|
|
pAddress->pHandler,
|
|
sizeof(RXCE_ADDRESS_EVENT_HANDLER));
|
|
|
|
// Duplicate the transport address for future searches
|
|
Status = DuplicateTransportAddress(
|
|
&pAddress->pTransportAddress,
|
|
pTransportAddress,
|
|
PagedPool);
|
|
} else {
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
// Open the address w.r.t a transport provider
|
|
Status = RxTdiOpenAddress(
|
|
pTransport,
|
|
pTransportAddress,
|
|
pAddress);
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
// Initialize the handler and the associated context
|
|
if (pHandler != NULL) {
|
|
*(pAddress->pHandler) = *pHandler;
|
|
pAddress->pContext = pEventContext;
|
|
}
|
|
} else {
|
|
RxCeTearDownAddress(pAddress);
|
|
RxDbgTrace(0, Dbg,("RxTdiOpenAddress returned %lx\n",Status));
|
|
}
|
|
} else {
|
|
RxDbgTrace(0, Dbg,("RxCeOpenAddress returned %lx\n",Status));
|
|
}
|
|
}
|
|
} finally {
|
|
if (AbnormalTermination()) {
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
RxLog(("RxCeBA: T: %lx A: %lx\n",pTransport,pAddress));
|
|
RxWmiLog(LOG,
|
|
RxCeBuildAddress,
|
|
LOGPTR(pTransport)
|
|
LOGPTR(pAddress));
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
RxCeTearDownAddress(
|
|
IN PRXCE_ADDRESS pAddress)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine deregisters a transport address from a transport binding
|
|
|
|
Arguments:
|
|
|
|
pAddress - the RxCe address denoting the transport binding/Transport address
|
|
tuple.
|
|
|
|
Return Value:
|
|
|
|
STATUS_SUCCESS if successful.
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS Status = STATUS_INVALID_PARAMETER;
|
|
PRXCE_TRANSPORT pTransport;
|
|
|
|
PAGED_CODE();
|
|
|
|
// Update profiling info.
|
|
RxProfile(RxCeManagement,RxCeDeregisterClientAddress);
|
|
|
|
try {
|
|
pTransport = pAddress->pTransport;
|
|
|
|
if (RxCeIsAddressValid(pAddress) &&
|
|
RxCeIsTransportValid(pTransport)) {
|
|
// close the address object.
|
|
|
|
if (pAddress->hAddress != INVALID_HANDLE_VALUE) {
|
|
Status = RxTdiCloseAddress(pAddress);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
RxDbgTrace(0, Dbg,("RxTdiCloseAddress returned %lx\n",Status));
|
|
}
|
|
}
|
|
|
|
if (pAddress->pHandler != NULL) {
|
|
RxFreePool(pAddress->pHandler);
|
|
}
|
|
|
|
if (pAddress->pTransportAddress != NULL) {
|
|
RxFreePool(pAddress->pTransportAddress);
|
|
}
|
|
|
|
pAddress->pTransport = pTransport;
|
|
pAddress->hAddress = INVALID_HANDLE_VALUE;
|
|
pAddress->pFileObject = NULL;
|
|
pAddress->pHandler = NULL;
|
|
pAddress->pTransportAddress = NULL;
|
|
pAddress->pReceiveMdl = NULL;
|
|
}
|
|
} finally {
|
|
if (AbnormalTermination()) {
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|