534 lines
14 KiB
C
534 lines
14 KiB
C
|
/*++
|
|||
|
|
|||
|
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;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|