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

📄 netbiostransport.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include <winsock2.h>
#include <iptypes.h>
#include <Iphlpapi.h>
#include <CReg.hxx>
#include <notify.h>
#include <ncb.h>
#include <windev.h>

#include "SMB_Globals.h"
#include "NetbiosTransport.h"
#include "Utils.h"
#include "CriticalSection.h"
#include "nb.h"



using namespace ce;
using namespace NETBIOS_TRANSPORT;

//do any explicit inits for globals setup in the NETBIOS_TRANSPORT
//  namespace
//
//
//  Running     Accepting     State
//     X                        During shutdown
//                  X           Error
//     X            X           Normal Use
//                              Stopped
//
//
LONG NETBIOS_TRANSPORT::g_fIsInited = FALSE;
LONG NETBIOS_TRANSPORT::g_fIsRunning = FALSE;
LONG NETBIOS_TRANSPORT::g_fIsAccepting = FALSE;

// Address change notification globals
USHORT AddressChangeNotification::usID = 0xFF;
SOCKET AddressChangeNotification::s = INVALID_SOCKET;
WSAOVERLAPPED AddressChangeNotification::ov = {0};


// Name change notification
HANDLE NameChangeNotification::h = NULL;
USHORT NameChangeNotification::usID = 0xFFFF;


ce::list<NetBIOSAdapter *> NETBIOS_TRANSPORT::NBAdapterDeleteStack;
ce::list<NetBIOSAdapter *> NETBIOS_TRANSPORT::NBAdapterStack;
ce::list<RecvNode, NETBIOS_CONNECTION_ALLOC > NETBIOS_TRANSPORT::ActiveRecvList;


HANDLE NETBIOS_TRANSPORT::g_hHaltNetbiosTransport = NULL;

CRITICAL_SECTION NETBIOS_TRANSPORT::csAdapterStackList;
CRITICAL_SECTION NETBIOS_TRANSPORT::csSendLock;
CRITICAL_SECTION NETBIOS_TRANSPORT::csActiveRecvListLock;
CRITICAL_SECTION NETBIOS_TRANSPORT::csNCBLock;
ce::fixed_block_allocator<10>              NETBIOS_TRANSPORT::g_NCBAllocator; //Use csNCBLock!


extern DWORD SMB_Deinit(DWORD dwClientContext);
extern DWORD SMB_Init(DWORD dwClientContext);
extern VOID SMB_RestartServer();
extern HRESULT StartTCPListenThread(UINT uiIPAddress, BYTE LANA);
extern HRESULT TerminateTCPListenThread(BYTE LANA);

extern HANDLE g_hNetbiosIOCTL;
extern CRITICAL_SECTION g_csDriverLock;

class HostNameWakeUpNode : public WakeUpNode
{
    public:
        HostNameWakeUpNode() {}
        ~HostNameWakeUpNode(){}

        VOID WakeUp() {
            SMB_RestartServer();
        }

        VOID Terminate() {
        }
};


VOID SMBSRVR_IPAddressChanged();
class IpAddressChangedWakeUpNode : public WakeUpNode
{
    public:
        IpAddressChangedWakeUpNode() {}
        ~IpAddressChangedWakeUpNode(){}

        VOID WakeUp() {
            SMBSRVR_IPAddressChanged();
        }

        VOID Terminate() {
        }
};


//
// Globals to the file
HostNameWakeUpNode g_HostNameWakeUpNode;
IpAddressChangedWakeUpNode g_IPAddressChangedWakeUpNode;


//
// Forward declare any functions
HRESULT InitLana(UCHAR ulLANIdx, DWORD dwNTE);
static void NetBIOSNotifyFunc(uchar lananum, DWORD dwNTE, int flags, int unused);


HRESULT NB_TerminateSession(ULONG ulConnectionID)
{
    CCritSection csLock(&csActiveRecvListLock);
    HRESULT hr = E_FAIL;
    ce::list<RecvNode, NETBIOS_CONNECTION_ALLOC >::iterator itARList;

    //
    // See if we can find this connection ID
    csLock.Lock();
    for(itARList=ActiveRecvList.begin(); itARList!=ActiveRecvList.end(); itARList++) {
        ce::list<ULONG>::iterator itConn;

        for(itConn=(*itARList).OutStandingConnectionIDs.begin(); itConn!=(*itARList).OutStandingConnectionIDs.end(); itConn++) {
            if((*itConn) == ulConnectionID) {
                BYTE ret;
                ncb myNCB;
                myNCB.ncb_command = NCBHANGUP;
                myNCB.ncb_lsn = (*itARList).usLSN;
                myNCB.ncb_lana_num = (*itARList).LANA;
                myNCB.ncb_length = 0;
                myNCB.ncb_buffer = NULL;

                TRACEMSG(ZONE_NETBIOS, (L"SMB_SRV: TerminateSession Called on Netbios for connID: %d", ulConnectionID));

                ret = Netbios(&myNCB);
                ASSERT(0 == ret);

                hr = S_OK;
                goto Done;
            }
        }
    }
    Done:
        return hr;
}


NetBIOSAdapter::NetBIOSAdapter(BYTE _bLana) : bLana(_bLana), nameNum(0xFF), fStopped(FALSE), bMark(TRUE)
{
    HRESULT hr = E_FAIL;
    RETAILMSG(1, (TEXT("SMBSRV:InitLana: Starting NetBios at index: %d"), bLana));

    //
    // Init state by zeroing out threads
    hListenThread = NULL;

    //
    //  Spin threads to handle listening and recving
    hListenThread  = CreateThread(NULL, 0, SMBSRVR_NetbiosListenThread, (LPVOID)this, CREATE_SUSPENDED, NULL);
    if(NULL == hListenThread) {
        TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV:InitLana: CreateThread failed starting NB Listen:%d"), GetLastError()));
        goto Done;
    }


    ASSERT(FAILED(hr));
    hr = S_OK;

    Done:
        //
        // If we failed, set the shutdown flag
        if(FAILED(hr)) {
            InterlockedExchange(&fStopped,TRUE);
        }

        //
        // Now crank up all threads (if we error'ed they will all just return quickly)
        if(NULL != hListenThread) {
            if(0xFFFFFFFF == ResumeThread(hListenThread)) {
                    TRACEMSG(ZONE_ERROR, (L"SMBSRV:Resuming  listen thread %d FAILED!"));
                    CloseHandle(hListenThread);
                    hListenThread = NULL; //Createthread returns null, not invalid handle value!
            }
        }
}

NetBIOSAdapter::~NetBIOSAdapter()
{
   //
   // If the adapter is running, kill it off
   if(!fStopped && FAILED(HaltAdapter())) {
      TRACEMSG(ZONE_ERROR, (L"SMBSRV: NetBIOSAdapter halting failed! (idx:%d)", this->bLana));
      ASSERT(FALSE);
   }
}


HRESULT
NetBIOSAdapter::HaltAdapter()
{
    ncb tNcb;
    BYTE *pCName;
    UCHAR retVal;
    HRESULT hr = S_OK;
    ce::list<RecvNode, NETBIOS_CONNECTION_ALLOC >::iterator itARList;
    CCritSection csLock(&csActiveRecvListLock);

    if(TRUE == fStopped) {
        return S_OK;
    }

    //
    // Render the sending thread worthless
    InterlockedExchange(&fStopped, TRUE);

    //
    // Get registered CName
    if(FAILED(hr = this->GetCName(&pCName))) {
        TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV:InitLana: couldnt get CName")));
        goto Done;
    }

    //
    // Hangup anything thats on our LANA;
    csLock.Lock();
    for(itARList=ActiveRecvList.begin(); itARList!=ActiveRecvList.end(); itARList++) {
        //
        // If this is on our LANA, hang it up (this should stop any active connections)
        if((*itARList).LANA == bLana) {
            tNcb.ncb_command = NCBHANGUP;
            tNcb.ncb_lana_num = bLana;
            tNcb.ncb_lsn = (*itARList).usLSN;
            memcpy(tNcb.ncb_name, pCName, 16);
            tNcb.ncb_length = 0;
            tNcb.ncb_buffer = NULL;

            retVal = Netbios(&tNcb);
            if (retVal != 0 || (retVal = tNcb.ncb_retcode) != 0) {
                TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV:InitLana: NCBHANGUPANY returned %s"), NETBIOS_TRANSPORT::NCBError(retVal)));
            }
        }
    }
    csLock.UnLock();

    //
    // Un-register the name
    tNcb.ncb_command = NCBDELNAME;
    tNcb.ncb_lana_num = bLana;
    tNcb.ncb_length = 0;
    tNcb.ncb_buffer = NULL;
    memcpy(tNcb.ncb_name, pCName, 16);
    retVal = Netbios(&tNcb);
    if (retVal != 0 || (retVal = tNcb.ncb_retcode) != 0) {
        TRACEMSG(ZONE_ERROR, (TEXT("SMBSRV:InitLana: NCBDELNAME returned %s"), NETBIOS_TRANSPORT::NCBError(retVal)));
    }

    //
    // Wait for the listening thread to stop
    if(WAIT_FAILED == WaitForSingleObject(hListenThread, INFINITE)) {
        TRACEMSG(ZONE_INIT, (L"SMBSRV:Waiting for LISTEN thread FAILED!"));
        ASSERT(FALSE);
        hr = E_FAIL;
    }
    TRACEMSG(ZONE_INIT, (L"SMBSRV:Listen thread has been stopped!"));

    //
    // Wait for the recving threads to stop
    for(;;) {
        csLock.Lock();
        if(0 == ActiveRecvList.size()) {
            break;
        }
        RecvNode *myNode = &(ActiveRecvList.front());
        HANDLE h = myNode->MyHandle;
        csLock.UnLock();

        if(WAIT_FAILED == WaitForSingleObject(h, INFINITE)) {
            TRACEMSG(ZONE_INIT, (L"SMBSRV:Waiting for RECV thread FAILED!"));
            ASSERT(FALSE);
        }
    }
    TRACEMSG(ZONE_INIT, (L"SMBSRV:Recv threads have been stopped!"));

    Done:
        return hr;
}


BOOL
NetBIOSAdapter::DuringShutDown()
{
    //
    // We are in the process of shutting down when we are running
    //   but not accepting
    return fStopped;
}

CHAR GetLANAFromNTE(DWORD dwNTE)
{
    NCB ncb;
    if(NB_FAILURE == NETbiosThunk(0, NB_CONVERT_NTE_TO_LANA, (PBYTE)&ncb, sizeof(dwNTE), (PBYTE)&dwNTE, 0, NULL)) {
        return (CHAR)0xFF;
    } else {
        return (CHAR)dwNTE;
    }
}


const int MAX_QUERY_ATTEMPTS = 3;
DWORD
GetAdaptersInformation(CHAR** ppAdapterInfo, DWORD dwNeeded, DWORD *pdwAdapterInfo)
{
    DWORD dwRetCode = ERROR_SUCCESS;
    CHAR* pPassedInPtr = *ppAdapterInfo;

    ASSERT(pdwAdapterInfo);
    ASSERT(ppAdapterInfo);
    ASSERT(*ppAdapterInfo);

    //
    // Because we are awake, enum all IP addresses
    for(int i=0; i<MAX_QUERY_ATTEMPTS; i++) {
        if(ERROR_BUFFER_OVERFLOW == (dwRetCode = GetAdaptersInfo((IP_ADAPTER_INFO *)*ppAdapterInfo, &dwNeeded))) {
            if(pPassedInPtr != *ppAdapterInfo) {
                delete [] *ppAdapterInfo;
            }
            if(NULL == (*ppAdapterInfo = new CHAR[dwNeeded])) {
                dwRetCode = ERROR_OUTOFMEMORY;
                goto Done;
            }
            *pdwAdapterInfo = dwNeeded;
        }
        else if(NO_ERROR == dwRetCode || ERROR_NO_DATA == dwRetCode) {
            break;
        }
    }

Done:
    if((dwRetCode != NO_ERROR) && (pPassedInPtr != *ppAdapterInfo)) {
        delete [] *ppAdapterInfo;
        *ppAdapterInfo = NULL;
    }

    return dwRetCode;
}


VOID
SMBSRVR_IPAddressChanged() {
    ASSERT(NULL != g_hHaltNetbiosTransport);

    CHAR AdapterInfo[1024];
    CHAR *pAdapterInfo = AdapterInfo;
    DWORD dwAdapterInfo = sizeof(AdapterInfo);


    DWORD dwRetCode = 0;
    DWORD dwNeeded = 0;
    DWORD dwWaitRet = 0;

    IP_ADAPTER_INFO *pAdaptTemp = NULL;
    CCritSection csLock(&csAdapterStackList);
    ce::list<NetBIOSAdapter *>::iterator itAdapt;

    //
    // Refresh the event
    if(ERROR_SUCCESS != WSAIoctl(AddressChangeNotification::s, SIO_ADDRESS_LIST_CHANGE, NULL, 0, NULL, 0, NULL, &AddressChangeNotification::ov, NULL) &&
       ERROR_IO_PENDING != GetLastError()) {
        TRACEMSG(ZONE_ERROR, (L"SMBSRV:IP Adapter change error -- cant call ioctl with SIO_ADDRESS_LIST_CHANGE"));
        ASSERT(FALSE);
        goto Done;
    }

    //
    // Because we are awake, enum all IP addresses
    dwNeeded = dwAdapterInfo;
    dwRetCode = GetAdaptersInformation(&pAdapterInfo, dwNeeded, &dwAdapterInfo);
    if(NO_ERROR != dwRetCode) {
        TRACEMSG(ZONE_ERROR, (L"SMBSRV:Unable to get adapter information [%d]", dwRetCode));
        goto Done;
    }

    //
    // Using the addresses loop over what we already have and whats there now
    //   deleting/adding as we go
    pAdaptTemp = (IP_ADAPTER_INFO *)pAdapterInfo;
    csLock.Lock();
    // Set everyones mark false (MARK phase)
    for(itAdapt=NBAdapterStack.begin(); itAdapt!=NBAdapterStack.end(); ++itAdapt) {
         (*itAdapt)->SetMark(FALSE);
    }
    while(NULL != pAdaptTemp) {
        BOOL fFound = FALSE;

        // Loop looking for our NTE, if we find it, mark the node
        for(itAdapt=NBAdapterStack.begin(); itAdapt!=NBAdapterStack.end(); ++itAdapt) {
             if((*itAdapt)->GetNTE() == pAdaptTemp->CurrentIpAddress->Context) {
                fFound = TRUE;

                if(0 != strcmp("0.0.0.0", pAdaptTemp->CurrentIpAddress->IpAddress.String)) {
                    (*itAdapt)->SetMark(TRUE);
                }
                break;
             }
        }
        // if we didnt find the node its NEW, call our notify funct with the proper lana
        if(!fFound) {
            DWORD dwLANA = GetLANAFromNTE(pAdaptTemp->CurrentIpAddress->Context);
            if(0xFFFFFFFF == dwLANA) {
                TRACEMSG(ZONE_ERROR, (L"SMBSRV: invalid LANA on context %d, maybe the IP isnt valid? ", pAdaptTemp->CurrentIpAddress->Context));
            } else {
                NetBIOSNotifyFunc((CHAR)dwLANA, pAdaptTemp->CurrentIpAddress->Context, LANA_UP_FL, 0);
            }
        }
        pAdaptTemp = pAdaptTemp->Next;
    }

    // Delete all nodes that are not marked (SWEEP phase)
    BOOL fNeedPurge = FALSE;
    for(itAdapt=NBAdapterStack.begin(); itAdapt!=NBAdapterStack.end();) {
         if(FALSE == (*itAdapt)->GetMark()) {
            if(!NBAdapterDeleteStack.push_front((*itAdapt))) {
                goto Done;
            }
            NBAdapterStack.erase(itAdapt++);
            fNeedPurge = TRUE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -