|
|
/*++
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; }
|