📄 transprt.c
字号:
/*++
Copyright (c) 1989 - 1999 Microsoft Corporation
Module Name:
transport.c
Abstract:
This module implements all transport related functions in the SMB connection engine
--*/
#include "precomp.h"
#pragma hdrstop
#include "tdikrnl.h"
NTSTATUS
SmbCeIsServerAvailable(
PUNICODE_STRING Name
);
VOID
SmbCeServerIsUnavailable(
PUNICODE_STRING Name,
NTSTATUS Status
);
VOID
SmbCeDiscardUnavailableServerList( );
VOID
MRxSmbpOverrideBindingPriority(
PUNICODE_STRING pTransportName,
PULONG pPriority
);
VOID
MRxSmbPnPBindingHandler(
__in TDI_PNP_OPCODE PnPOpcode,
__in PUNICODE_STRING pTransportName,
__in PWSTR BindingList
);
NTSTATUS
MRxSmbPnPPowerHandler(
IN PUNICODE_STRING DeviceName,
IN PNET_PNP_EVENT PowerEvent,
IN PTDI_PNP_CONTEXT Context1,
IN PTDI_PNP_CONTEXT Context2
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, SmbCeFindTransport)
#pragma alloc_text(PAGE, SmbCepInitializeServerTransport)
#pragma alloc_text(PAGE, SmbCeInitializeExchangeTransport)
#pragma alloc_text(PAGE, SmbCeUninitializeExchangeTransport)
#pragma alloc_text(PAGE, SmbCepDereferenceTransport)
#pragma alloc_text(PAGE, MRxSmbpBindTransportCallback)
#pragma alloc_text(PAGE, MRxSmbpBindTransportWorkerThreadRoutine)
#pragma alloc_text(PAGE, MRxSmbpUnbindTransportCallback)
#pragma alloc_text(PAGE, MRxSmbpOverrideBindingPriority)
#pragma alloc_text(PAGE, MRxSmbPnPBindingHandler)
#pragma alloc_text(PAGE, MRxSmbRegisterForPnpNotifications)
#pragma alloc_text(PAGE, MRxSmbDeregisterForPnpNotifications)
#pragma alloc_text(PAGE, SmbCeDereferenceTransportArray)
#pragma alloc_text(PAGE, SmbCeIsServerAvailable)
#pragma alloc_text(PAGE, SmbCeServerIsUnavailable)
#pragma alloc_text(PAGE, SmbCeDiscardUnavailableServerList)
#endif
SMBCE_TRANSPORTS MRxSmbTransports;
//
// The head of the list of servers that are currently unavailable
//
LIST_ENTRY UnavailableServerList = { &UnavailableServerList, &UnavailableServerList };
//
// Each entry in the UnavailableServerList is one of these:
//
typedef struct {
LIST_ENTRY ListEntry;
UNICODE_STRING Name; // Name of server that is unavailable
NTSTATUS Status; // Status received when we tried to connect to it
LARGE_INTEGER Time; // Time when we last attempted to connect
} *PUNAVAILABLE_SERVER;
//
// Protects UnavailableServerList
//
ERESOURCE UnavailableServerListResource = {0};
//
// Time (seconds) that we keep an entry in the UnavailableServerList.
// We will not retry a connection attempt to a server
// for UNAVAILABLE_SERVER_TIME seconds
//
#define UNAVAILABLE_SERVER_TIME 10
RXDT_DefineCategory(TRANSPRT);
#define Dbg (DEBUG_TRACE_TRANSPRT)
NTSTATUS
MRxSmbInitializeTransport()
/*++
Routine Description:
This routine initializes the transport related data structures
Returns:
STATUS_SUCCESS if the transport data structures was successfully initialized
Notes:
--*/
{
KeInitializeSpinLock(&MRxSmbTransports.Lock);
MRxSmbTransports.pTransportArray = NULL;
ExInitializeResource( &UnavailableServerListResource );
return STATUS_SUCCESS;
}
NTSTATUS
MRxSmbUninitializeTransport()
/*++
Routine Description:
This routine uninitializes the transport related data structures
Notes:
--*/
{
PSMBCE_TRANSPORT pTransport;
KIRQL SavedIrql;
ULONG TransportCount = 0;
PSMBCE_TRANSPORT_ARRAY pTransportArray = NULL;
KeAcquireSpinLock(&MRxSmbTransports.Lock,&SavedIrql);
if (MRxSmbTransports.pTransportArray != NULL) {
pTransportArray = MRxSmbTransports.pTransportArray;
MRxSmbTransports.pTransportArray = NULL;
}
KeReleaseSpinLock(&MRxSmbTransports.Lock,SavedIrql);
if (pTransportArray != NULL) {
SmbCeDereferenceTransportArray(pTransportArray);
}
SmbCeDiscardUnavailableServerList();
ExDeleteResource( &UnavailableServerListResource );
return STATUS_SUCCESS;
}
NTSTATUS
SmbCeAddTransport(
PSMBCE_TRANSPORT pNewTransport)
/*++
Routine Description:
This routine adds a new instance to the known list of transports
Parameters:
pNewTransport -- the transport instance to be added
Notes:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
KIRQL SavedIrql;
LONG Count;
PSMBCE_TRANSPORT_ARRAY pNewTransportArray = NULL;
PSMBCE_TRANSPORT_ARRAY pOldTransportArray;
PSMBCE_TRANSPORT *pTransports = NULL;
PRXCE_ADDRESS *LocalAddresses = NULL;
SmbCeAcquireResource();
pOldTransportArray = SmbCeReferenceTransportArray();
if (pOldTransportArray != NULL) {
__assume_bound( pOldTransportArray->Count );
Count = pOldTransportArray->Count + 1;
}
else {
Count = 1;
}
pNewTransportArray = (PSMBCE_TRANSPORT_ARRAY)RxAllocatePoolWithTag(
NonPagedPool,
sizeof(SMBCE_TRANSPORT_ARRAY),
MRXSMB_TRANSPORT_POOLTAG);
if (pNewTransportArray == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
if (Status == STATUS_SUCCESS) {
pTransports = (PSMBCE_TRANSPORT *)RxAllocatePoolWithTag(
NonPagedPool,
Count * sizeof(PSMBCE_TRANSPORT),
MRXSMB_TRANSPORT_POOLTAG);
if (pTransports == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
if (Status == STATUS_SUCCESS) {
LocalAddresses = (PRXCE_ADDRESS *)RxAllocatePoolWithTag(
NonPagedPool,
Count * sizeof(PRXCE_ADDRESS),
MRXSMB_TRANSPORT_POOLTAG);
if (LocalAddresses == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
if (Status == STATUS_SUCCESS) {
LONG i;
if (Count > 1) {
PSMBCE_TRANSPORT *pOldTransports;
pOldTransports = pOldTransportArray->SmbCeTransports;
for (i=0;i<Count-1;i++) {
if (pNewTransport->Priority < pOldTransports[i]->Priority) { // The lower number, the higher priority
break;
}
pTransports[i] = pOldTransports[i];
LocalAddresses[i] = &pOldTransports[i]->RxCeAddress;
}
pTransports[i] = pNewTransport;
LocalAddresses[i] = &pNewTransport->RxCeAddress;
for (;i<Count-1;i++) {
pTransports[i+1] = pOldTransports[i];
LocalAddresses[i+1] = &pOldTransports[i]->RxCeAddress;
}
} else {
pTransports[0] = pNewTransport;
LocalAddresses[0] = &pNewTransport->RxCeAddress;
}
for(i=0;i<Count;i++)
SmbCeReferenceTransport(pTransports[i]);
pNewTransportArray->ReferenceCount = 1;
pNewTransportArray->Count = Count;
pNewTransportArray->SmbCeTransports = &pTransports[0];
pNewTransportArray->LocalAddresses = &LocalAddresses[0];
KeAcquireSpinLock(&MRxSmbTransports.Lock,&SavedIrql);
MRxSmbTransports.pTransportArray = pNewTransportArray;
KeReleaseSpinLock(&MRxSmbTransports.Lock,SavedIrql);
// Double dereferencing is necessary to ensure that
// the old transport array is destroyed.
SmbCeDereferenceTransportArray(pOldTransportArray);
}
SmbCeDereferenceTransportArray(pOldTransportArray);
SmbCeReleaseResource();
if (Status != STATUS_SUCCESS) {
if (pNewTransportArray != NULL) {
RxFreePool(pNewTransportArray);
}
if (pTransports != NULL) {
RxFreePool(pTransports);
}
if (LocalAddresses != NULL) {
RxFreePool(LocalAddresses);
}
}
SmbCeDiscardUnavailableServerList();
return Status;
}
NTSTATUS
SmbCeRemoveTransport(
PSMBCE_TRANSPORT pTransport)
/*++
Routine Description:
This routine removes a transport from the list of known transports
Parameters:
pTransport - the transport instance to be removed.
Notes:
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
KIRQL SavedIrql;
LONG Count;
PSMBCE_TRANSPORT_ARRAY pTransportArray = NULL;
PSMBCE_TRANSPORT_ARRAY pOldTransportArray = NULL;
PSMBCE_TRANSPORT *pTransports = NULL;
PRXCE_ADDRESS *pLocalAddresses = NULL;
SmbCeAcquireResource();
pOldTransportArray = SmbCeReferenceTransportArray();
if (pOldTransportArray != NULL) {
LONG Index;
BOOLEAN Found = FALSE;
PSMBCE_TRANSPORT *pOldTransports;
// Establish the fact that the given transport is part of the array.
// if it is not then no further action is necessary
pOldTransports = pOldTransportArray->SmbCeTransports;
for (Index = 0; Index < (LONG)pOldTransportArray->Count; Index++) {
if (pTransport == pOldTransports[Index]) {
Found = TRUE;
}
}
if (Found) {
Count = pOldTransportArray->Count - 1;
if (Count > 0) {
pTransportArray = (PSMBCE_TRANSPORT_ARRAY)RxAllocatePoolWithTag(
NonPagedPool,
sizeof(SMBCE_TRANSPORT_ARRAY),
MRXSMB_TRANSPORT_POOLTAG);
if (pTransportArray == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
if (Status == STATUS_SUCCESS) {
pTransports = (PSMBCE_TRANSPORT *)RxAllocatePoolWithTag(
NonPagedPool,
Count * sizeof(PSMBCE_TRANSPORT),
MRXSMB_TRANSPORT_POOLTAG);
if (pTransports == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
if (Status == STATUS_SUCCESS) {
pLocalAddresses = (PRXCE_ADDRESS *)RxAllocatePoolWithTag(
NonPagedPool,
Count * sizeof(PRXCE_ADDRESS),
MRXSMB_TRANSPORT_POOLTAG);
if (pLocalAddresses == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
}
if (Status == STATUS_SUCCESS) {
LONG i, j;
for (i=0, j=0;i<Count+1;i++) {
if (pTransport != pOldTransports[i]) {
pTransports[j] = pOldTransports[i];
pLocalAddresses[j] = &pOldTransports[i]->RxCeAddress;
j++;
}
}
for(i=0;i<Count;i++)
SmbCeReferenceTransport(pTransports[i]);
pTransportArray->ReferenceCount = 1;
pTransportArray->Count = Count;
pTransportArray->SmbCeTransports = &pTransports[0];
pTransportArray->LocalAddresses = &pLocalAddresses[0];
}
}
if (Status == STATUS_SUCCESS) {
KeAcquireSpinLock(&MRxSmbTransports.Lock,&SavedIrql);
MRxSmbTransports.pTransportArray = pTransportArray;
KeReleaseSpinLock(&MRxSmbTransports.Lock,SavedIrql);
// Double dereferencing is necessary to ensure that
// the old transport array is destroyed.
SmbCeDereferenceTransportArray(pOldTransportArray);
} else {
if (pTransportArray != NULL) {
RxFreePool(pTransportArray);
}
if (pTransports != NULL) {
RxFreePool(pTransports);
}
if (pLocalAddresses != NULL) {
RxFreePool(pLocalAddresses);
}
}
}
SmbCeDereferenceTransportArray(pOldTransportArray);
}
SmbCeReleaseResource();
SmbCeDiscardUnavailableServerList();
return Status;
}
PSMBCE_TRANSPORT
SmbCeFindTransport(
PUNICODE_STRING pTransportName)
/*++
Routine Description:
This routine maps a transport name to the appropriate
PSMBCE_TRANSPORT instance
Arguments:
pTransportName - the transport name
Return Value:
a valid PSMBCE_TRANSPORT if one exists otherwise NULL
Notes:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -