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

📄 netbios.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 2 页
字号:
        NetBIOSSession *newSessions;

        if (adapter->sessions)
            newSessions = HeapReAlloc(GetProcessHeap(),
             HEAP_ZERO_MEMORY, adapter->sessions, sessionsLen *
             sizeof(NetBIOSSession));
        else
            newSessions = HeapAlloc(GetProcessHeap(),
             HEAP_ZERO_MEMORY, sessionsLen * sizeof(NetBIOSSession));
        if (newSessions)
        {
            adapter->sessions = newSessions;
            adapter->sessionsLen = sessionsLen;
        }
        else
            ret = NRC_OSRESNOTAV;
    }
    return ret;
}

static UCHAR nbReset(NetBIOSAdapter *adapter, PNCB ncb)
{
    UCHAR ret;

    TRACE(": adapter %p, ncb %p\n", adapter, ncb);

    if (!adapter) return NRC_BRIDGE;
    if (!ncb) return NRC_INVADDRESS;

    if (InterlockedIncrement(&adapter->resetting) == 1)
    {
        UCHAR i, resizeTo;

        NBCmdQueueCancelAll(adapter->cmdQueue);

        EnterCriticalSection(&adapter->cs);
        for (i = 0; i < adapter->sessionsLen; i++)
            if (adapter->sessions[i].inUse)
                nbInternalHangup(adapter, &adapter->sessions[i]);
        if (!ncb->ncb_lsn)
            resizeTo = ncb->ncb_callname[0] == 0 ? DEFAULT_NUM_SESSIONS :
             ncb->ncb_callname[0];
        else if (adapter->sessionsLen == 0)
            resizeTo = DEFAULT_NUM_SESSIONS;
        else
            resizeTo = 0;
        if (resizeTo > 0)
            ret = nbResizeAdapter(adapter, resizeTo);
        else
            ret = NRC_GOODRET;
        LeaveCriticalSection(&adapter->cs);
    }
    else
        ret = NRC_TOOMANY;
    InterlockedDecrement(&adapter->resetting);
    TRACE("returning 0x%02x\n", ret);
    return ret;
}

static UCHAR nbSStat(NetBIOSAdapter *adapter, PNCB ncb)
{
    UCHAR ret, i, spaceFor;
    PSESSION_HEADER sstat;

    TRACE(": adapter %p, NCB %p\n", adapter, ncb);

    if (!adapter) return NRC_BADDR;
    if (adapter->sessionsLen == 0) return NRC_ENVNOTDEF;
    if (!ncb) return NRC_INVADDRESS;
    if (!ncb->ncb_buffer) return NRC_BADDR;
    if (ncb->ncb_length < sizeof(SESSION_HEADER)) return NRC_BUFLEN;

    sstat = (PSESSION_HEADER)ncb->ncb_buffer;
    ret = NRC_GOODRET;
    memset(sstat, 0, sizeof(SESSION_HEADER));
    spaceFor = (ncb->ncb_length - sizeof(SESSION_HEADER)) /
     sizeof(SESSION_BUFFER);
    EnterCriticalSection(&adapter->cs);
    for (i = 0; ret == NRC_GOODRET && i < adapter->sessionsLen; i++)
    {
        if (adapter->sessions[i].inUse && (ncb->ncb_name[0] == '*' ||
         !memcmp(ncb->ncb_name, adapter->sessions[i].local_name, NCBNAMSZ)))
        {
            if (sstat->num_sess < spaceFor)
            {
                PSESSION_BUFFER buf;
               
                buf = (PSESSION_BUFFER)((PUCHAR)sstat + sizeof(SESSION_HEADER)
                 + sstat->num_sess * sizeof(SESSION_BUFFER));
                buf->lsn = i;
                buf->state = adapter->sessions[i].state;
                memcpy(buf->local_name, adapter->sessions[i].local_name,
                 NCBNAMSZ);
                memcpy(buf->remote_name, adapter->sessions[i].remote_name,
                 NCBNAMSZ);
                buf->rcvs_outstanding = buf->sends_outstanding = 0;
                sstat->num_sess++;
            }
            else
                ret = NRC_BUFLEN;
        }
    }
    LeaveCriticalSection(&adapter->cs);

    TRACE("returning 0x%02x\n", ret);
    return ret;
}

static UCHAR nbCall(NetBIOSAdapter *adapter, PNCB ncb)
{
    UCHAR ret, i;

    TRACE(": adapter %p, NCB %p\n", adapter, ncb);

    if (!adapter) return NRC_BRIDGE;
    if (adapter->sessionsLen == 0) return NRC_ENVNOTDEF;
    if (!adapter->transport->call) return NRC_ILLCMD;
    if (!ncb) return NRC_INVADDRESS;

    EnterCriticalSection(&adapter->cs);
    for (i = 0; i < adapter->sessionsLen && adapter->sessions[i].inUse; i++)
        ;
    if (i < adapter->sessionsLen)
    {
        adapter->sessions[i].inUse = TRUE;
        adapter->sessions[i].state = CALL_PENDING;
        memcpy(adapter->sessions[i].local_name, ncb->ncb_name, NCBNAMSZ);
        memcpy(adapter->sessions[i].remote_name, ncb->ncb_callname, NCBNAMSZ);
        ret = NRC_GOODRET;
    }
    else
        ret = NRC_LOCTFUL;
    LeaveCriticalSection(&adapter->cs);

    if (ret == NRC_GOODRET)
    {
        ret = adapter->transport->call(adapter->impl.data, ncb,
         &adapter->sessions[i].data);
        if (ret == NRC_GOODRET)
        {
            ncb->ncb_lsn = i;
            adapter->sessions[i].state = SESSION_ESTABLISHED;
        }
        else
        {
            adapter->sessions[i].inUse = FALSE;
            adapter->sessions[i].state = 0;
        }
    }
    TRACE("returning 0x%02x\n", ret);
    return ret;
}

static UCHAR nbSend(NetBIOSAdapter *adapter, PNCB ncb)
{
    UCHAR ret;
    NetBIOSSession *session;

    if (!adapter) return NRC_BRIDGE;
    if (!adapter->transport->send) return NRC_ILLCMD;
    if (!ncb) return NRC_INVADDRESS;
    if (ncb->ncb_lsn >= adapter->sessionsLen) return NRC_SNUMOUT;
    if (!adapter->sessions[ncb->ncb_lsn].inUse) return NRC_SNUMOUT;
    if (!ncb->ncb_buffer) return NRC_BADDR;

    session = &adapter->sessions[ncb->ncb_lsn];
    if (session->state != SESSION_ESTABLISHED)
        ret = NRC_SNUMOUT;
    else
        ret = adapter->transport->send(adapter->impl.data, session->data, ncb);
    return ret;
}

static UCHAR nbRecv(NetBIOSAdapter *adapter, PNCB ncb)
{
    UCHAR ret;
    NetBIOSSession *session;

    if (!adapter) return NRC_BRIDGE;
    if (!adapter->transport->recv) return NRC_ILLCMD;
    if (!ncb) return NRC_INVADDRESS;
    if (ncb->ncb_lsn >= adapter->sessionsLen) return NRC_SNUMOUT;
    if (!adapter->sessions[ncb->ncb_lsn].inUse) return NRC_SNUMOUT;
    if (!ncb->ncb_buffer) return NRC_BADDR;

    session = &adapter->sessions[ncb->ncb_lsn];
    if (session->state != SESSION_ESTABLISHED)
        ret = NRC_SNUMOUT;
    else
        ret = adapter->transport->recv(adapter->impl.data, session->data, ncb);
    return ret;
}

static UCHAR nbInternalHangup(NetBIOSAdapter *adapter, NetBIOSSession *session)
{
    UCHAR ret;

    if (!adapter) return NRC_BRIDGE;
    if (!session) return NRC_SNUMOUT;

    if (adapter->transport->hangup)
        ret = adapter->transport->hangup(adapter->impl.data, session->data);
    else
        ret = NRC_ILLCMD;
    EnterCriticalSection(&adapter->cs);
    memset(session, 0, sizeof(NetBIOSSession));
    LeaveCriticalSection(&adapter->cs);
    return NRC_GOODRET;
}

static UCHAR nbHangup(NetBIOSAdapter *adapter, PNCB ncb)
{
    UCHAR ret;
    NetBIOSSession *session;

    if (!adapter) return NRC_BRIDGE;
    if (!ncb) return NRC_INVADDRESS;
    if (ncb->ncb_lsn >= adapter->sessionsLen) return NRC_SNUMOUT;
    if (!adapter->sessions[ncb->ncb_lsn].inUse) return NRC_SNUMOUT;

    session = &adapter->sessions[ncb->ncb_lsn];
    if (session->state != SESSION_ESTABLISHED)
        ret = NRC_SNUMOUT;
    else
    {
        session->state = HANGUP_PENDING;
        ret = nbInternalHangup(adapter, session);
    }
    return ret;
}

void NetBIOSHangupSession(PNCB ncb)
{
    NetBIOSAdapter *adapter;

    if (!ncb) return;

    adapter = nbGetAdapter(ncb->ncb_lana_num);
    if (adapter)
    {
        if (ncb->ncb_lsn < adapter->sessionsLen &&
         adapter->sessions[ncb->ncb_lsn].inUse)
            nbHangup(adapter, ncb);
    }
}

static UCHAR nbAStat(NetBIOSAdapter *adapter, PNCB ncb)
{
    UCHAR ret;

    if (!adapter) return NRC_BRIDGE;
    if (!adapter->transport->astat) return NRC_ILLCMD;
    if (!ncb) return NRC_INVADDRESS;
    if (!ncb->ncb_buffer) return NRC_BADDR;
    if (ncb->ncb_length < sizeof(ADAPTER_STATUS)) return NRC_BUFLEN;

    ret = adapter->transport->astat(adapter->impl.data, ncb);
    if (ncb->ncb_callname[0] == '*')
    {
        PADAPTER_STATUS astat = (PADAPTER_STATUS)ncb->ncb_buffer;

        astat->max_sess = astat->max_cfg_sess = adapter->sessionsLen;
    }
    return ret;
}

static UCHAR nbDispatch(NetBIOSAdapter *adapter, PNCB ncb)
{
    UCHAR ret, cmd;

    TRACE(": adapter %p, ncb %p\n", adapter, ncb);

    if (!adapter) return NRC_BRIDGE;
    if (!ncb) return NRC_INVADDRESS;

    cmd = ncb->ncb_command & 0x7f;
    if (cmd == NCBRESET)
        ret = nbReset(adapter, ncb);
    else
    {
        ret = NBCmdQueueAdd(adapter->cmdQueue, ncb);
        if (ret == NRC_GOODRET)
        {
            switch (cmd)
            {
                case NCBCALL:
                    ret = nbCall(adapter, ncb);
                    break;

                /* WinNT doesn't chain sends, it always sends immediately.
                 * Doubt there's any real significance to the NA variants.
                 */
                case NCBSEND:
                case NCBSENDNA:
                case NCBCHAINSEND:
                case NCBCHAINSENDNA:
                    ret = nbSend(adapter, ncb);
                    break;

                case NCBRECV:
                    ret = nbRecv(adapter, ncb);
                    break;

                case NCBHANGUP:
                    ret = nbHangup(adapter, ncb);
                    break;

                case NCBASTAT:
                    ret = nbAStat(adapter, ncb);
                    break;

                case NCBFINDNAME:
                    if (adapter->transport->findName)
                        ret = adapter->transport->findName(adapter->impl.data,
                         ncb);
                    else
                        ret = NRC_ILLCMD;
                    break;

                default:
                    FIXME("(%p): command code 0x%02x\n", ncb, ncb->ncb_command);
                    ret = NRC_ILLCMD;
            }
            NBCmdQueueComplete(adapter->cmdQueue, ncb, ret);
        }
    }
    TRACE("returning 0x%02x\n", ret);
    return ret;
}

static DWORD WINAPI nbCmdThread(LPVOID lpVoid)
{
    PNCB ncb = (PNCB)lpVoid;

    if (ncb)
    {
        UCHAR ret;
        NetBIOSAdapter *adapter = nbGetAdapter(ncb->ncb_lana_num);

        if (adapter)
            ret = nbDispatch(adapter, ncb);
        else
            ret = NRC_BRIDGE;
        ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret;
        if (ncb->ncb_post)
            ncb->ncb_post(ncb);
        else if (ncb->ncb_event)
            SetEvent(ncb->ncb_event);
    }
    return 0;
}

UCHAR WINAPI Netbios(PNCB ncb)
{
    UCHAR ret, cmd;

    TRACE("ncb = %p\n", ncb);

    if (!ncb) return NRC_INVADDRESS;

    TRACE("ncb_command 0x%02x, ncb_lana_num %d, ncb_buffer %p, ncb_length %d\n",
     ncb->ncb_command, ncb->ncb_lana_num, ncb->ncb_buffer, ncb->ncb_length);
    cmd = ncb->ncb_command & 0x7f;

    if (cmd == NCBENUM)
        ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret = nbEnum(ncb);
    else if (cmd == NCBADDNAME)
    {
        FIXME("NCBADDNAME: stub, returning success");
        ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret = NRC_GOODRET;
    }
    else
    {
        NetBIOSAdapter *adapter;

        /* Apps not specifically written for WinNT won't do an NCBENUM first,
         * so make sure the table has been enumerated at least once
         */
        if (!gNBTable.enumerated)
            nbInternalEnum();
        adapter = nbGetAdapter(ncb->ncb_lana_num);
        if (!adapter)
            ret = NRC_BRIDGE;
        else
        {
            if (adapter->shuttingDown)
                ret = NRC_IFBUSY;
            else if (adapter->resetting)
                ret = NRC_TOOMANY;
            else
            {
                /* non-asynch commands first */
                if (cmd == NCBCANCEL)
                    ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret =
                     nbCancel(adapter, ncb);
                else if (cmd == NCBSSTAT)
                    ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret =
                     nbSStat(adapter, ncb);
                else
                {
                    if (ncb->ncb_command & ASYNCH)
                    {
                        HANDLE thread = CreateThread(NULL, 0, nbCmdThread, ncb,
                         CREATE_SUSPENDED, NULL);

                        if (thread != NULL)
                        {
                            ncb->ncb_retcode = ncb->ncb_cmd_cplt = NRC_PENDING;
                            if (ncb->ncb_event)
                                ResetEvent(ncb->ncb_event);
                            ResumeThread(thread);
                            CloseHandle(thread);
                            ret = NRC_GOODRET;
                        }
                        else
                        ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret =
                         NRC_OSRESNOTAV;
                    }
                    else
                        ncb->ncb_retcode = ncb->ncb_cmd_cplt = ret =
                         nbDispatch(adapter, ncb);
                }
            }
        }
    }
    TRACE("returning 0x%02x\n", ret);
    return ret;
}

⌨️ 快捷键说明

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