windows-nt/Source/XPSP1/NT/base/fs/rdr2/rxce/rxce.c

534 lines
14 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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;
}