📄 netbios.c
字号:
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 + -