⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transprt.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 5 页
字号:
/*++

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 + -