📄 nbt.c
字号:
else if (NCB_CANCELLED(ncb))
{
LeaveCriticalSection(&session->cs);
ret = NRC_CMDCAN;
}
else
{
if (bufferCount == 2)
{
if (buffer[0] == NBSS_KEEPALIVE)
{
LeaveCriticalSection(&session->cs);
FIXME("Oops, received a session keepalive and lost my place\n");
/* need to read another session header until we get a session
* message header. */
NetBIOSHangupSession(ncb);
ret = NRC_SABORT;
}
else if (buffer[0] != NBSS_MSG)
{
LeaveCriticalSection(&session->cs);
FIXME("Received unexpected session msg type %d\n", buffer[0]);
NetBIOSHangupSession(ncb);
ret = NRC_SABORT;
}
else
{
if (buffer[1] & NBSS_EXTENSION)
{
LeaveCriticalSection(&session->cs);
FIXME("Received a message that's too long for my taste\n");
NetBIOSHangupSession(ncb);
ret = NRC_SABORT;
}
else
{
session->bytesPending = NBSS_HDRSIZE
+ NBR_GETWORD(&buffer[2]) - bytesReceived;
ncb->ncb_length = bytesReceived - NBSS_HDRSIZE;
LeaveCriticalSection(&session->cs);
}
}
}
else
{
if (bytesReceived < session->bytesPending)
session->bytesPending -= bytesReceived;
else
session->bytesPending = 0;
LeaveCriticalSection(&session->cs);
ncb->ncb_length = bytesReceived;
}
if (session->bytesPending > 0)
ret = NRC_INCOMP;
else
{
ret = NRC_GOODRET;
adapter->recv_success++;
}
}
TRACE("returning 0x%02x\n", ret);
return ret;
}
static UCHAR NetBTHangup(void *adapt, void *sess)
{
NetBTSession *session = (NetBTSession *)sess;
TRACE("adapt %p, session %p\n", adapt, session);
if (!session) return NRC_SNUMOUT;
/* I don't lock the session, because NetBTRecv knows not to decrement
* past 0, so if a receive completes after this it should still deal.
*/
closesocket(session->fd);
session->fd = INVALID_SOCKET;
session->bytesPending = 0;
DeleteCriticalSection(&session->cs);
HeapFree(GetProcessHeap(), 0, session);
return NRC_GOODRET;
}
static void NetBTCleanupAdapter(void *adapt)
{
TRACE("adapt %p\n", adapt);
if (adapt)
{
NetBTAdapter *adapter = (NetBTAdapter *)adapt;
if (adapter->nameCache)
NBNameCacheDestroy(adapter->nameCache);
HeapFree(GetProcessHeap(), 0, adapt);
}
}
static void NetBTCleanup(void)
{
TRACE("\n");
if (gNameCache)
{
NBNameCacheDestroy(gNameCache);
gNameCache = NULL;
}
}
static UCHAR NetBTRegisterAdapter(PMIB_IPADDRROW ipRow)
{
UCHAR ret;
NetBTAdapter *adapter;
if (!ipRow) return NRC_BADDR;
adapter = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(NetBTAdapter));
if (adapter)
{
memcpy(&adapter->ipr, ipRow, sizeof(MIB_IPADDRROW));
if (!NetBIOSRegisterAdapter(gTransportID, ipRow->dwIndex, adapter))
{
NetBTCleanupAdapter(adapter);
ret = NRC_SYSTEM;
}
else
ret = NRC_GOODRET;
}
else
ret = NRC_OSRESNOTAV;
return ret;
}
/* Callback for NetBIOS adapter enumeration. Assumes closure is a pointer to
* a MIB_IPADDRTABLE containing all the IP adapters needed to be added to the
* NetBIOS adapter table. For each callback, checks if the passed-in adapt
* has an entry in the table; if so, this adapter was enumerated previously,
* and it's enabled. As a flag, the table's dwAddr entry is changed to
* INADDR_LOOPBACK, since this is an invalid address for a NetBT adapter.
* The NetBTEnum function will add any remaining adapters from the
* MIB_IPADDRTABLE to the NetBIOS adapter table.
*/
static BOOL NetBTEnumCallback(UCHAR totalLANAs, UCHAR lanaIndex,
ULONG transport, const NetBIOSAdapterImpl *data, void *closure)
{
BOOL ret;
PMIB_IPADDRTABLE table = (PMIB_IPADDRTABLE)closure;
if (table && data)
{
DWORD ndx;
ret = FALSE;
for (ndx = 0; !ret && ndx < table->dwNumEntries; ndx++)
{
const NetBTAdapter *adapter = (const NetBTAdapter *)data->data;
if (table->table[ndx].dwIndex == adapter->ipr.dwIndex)
{
NetBIOSEnableAdapter(data->lana);
table->table[ndx].dwAddr = INADDR_LOOPBACK;
ret = TRUE;
}
}
}
else
ret = FALSE;
return ret;
}
/* Enumerates adapters by:
* - retrieving the IP address table for the local machine
* - eliminating loopback addresses from the table
* - eliminating redundant addresses, that is, multiple addresses on the same
* subnet
* Calls NetBIOSEnumAdapters, passing the resulting table as the callback
* data. The callback reenables each adapter that's already in the NetBIOS
* table. After NetBIOSEnumAdapters returns, this function adds any remaining
* adapters to the NetBIOS table.
*/
static UCHAR NetBTEnum(void)
{
UCHAR ret;
DWORD size = 0;
TRACE("\n");
if (GetIpAddrTable(NULL, &size, FALSE) == ERROR_INSUFFICIENT_BUFFER)
{
PMIB_IPADDRTABLE ipAddrs, coalesceTable = NULL;
DWORD numIPAddrs = (size - sizeof(MIB_IPADDRTABLE)) /
sizeof(MIB_IPADDRROW) + 1;
ipAddrs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
if (ipAddrs)
coalesceTable = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, sizeof(MIB_IPADDRTABLE) +
(min(numIPAddrs, MAX_LANA + 1) - 1) * sizeof(MIB_IPADDRROW));
if (ipAddrs && coalesceTable)
{
if (GetIpAddrTable(ipAddrs, &size, FALSE) == ERROR_SUCCESS)
{
DWORD ndx;
for (ndx = 0; ndx < ipAddrs->dwNumEntries; ndx++)
{
if ((ipAddrs->table[ndx].dwAddr &
ipAddrs->table[ndx].dwMask) !=
htonl((INADDR_LOOPBACK & IN_CLASSA_NET)))
{
BOOL newNetwork = TRUE;
DWORD innerIndex;
/* make sure we don't have more than one entry
* for a subnet */
for (innerIndex = 0; newNetwork &&
innerIndex < coalesceTable->dwNumEntries; innerIndex++)
if ((ipAddrs->table[ndx].dwAddr &
ipAddrs->table[ndx].dwMask) ==
(coalesceTable->table[innerIndex].dwAddr
& coalesceTable->table[innerIndex].dwMask))
newNetwork = FALSE;
if (newNetwork)
memcpy(&coalesceTable->table[
coalesceTable->dwNumEntries++],
&ipAddrs->table[ndx], sizeof(MIB_IPADDRROW));
}
}
NetBIOSEnumAdapters(gTransportID, NetBTEnumCallback,
coalesceTable);
ret = NRC_GOODRET;
for (ndx = 0; ret == NRC_GOODRET &&
ndx < coalesceTable->dwNumEntries; ndx++)
if (coalesceTable->table[ndx].dwAddr != INADDR_LOOPBACK)
ret = NetBTRegisterAdapter(&coalesceTable->table[ndx]);
}
else
ret = NRC_SYSTEM;
HeapFree(GetProcessHeap(), 0, ipAddrs);
HeapFree(GetProcessHeap(), 0, coalesceTable);
}
else
ret = NRC_OSRESNOTAV;
}
else
ret = NRC_SYSTEM;
TRACE("returning 0x%02x\n", ret);
return ret;
}
static const WCHAR VxD_MSTCPW[] = { 'S','Y','S','T','E','M','\\','C','u','r',
'r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\','S','e','r','v',
'i','c','e','s','\\','V','x','D','\\','M','S','T','C','P','\0' };
static const WCHAR NetBT_ParametersW[] = { 'S','Y','S','T','E','M','\\','C','u',
'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\','S','e','r',
'v','i','c','e','s','\\','N','e','t','B','T','\\','P','a','r','a','m','e','t',
'e','r','s','\0' };
static const WCHAR EnableDNSW[] = { 'E','n','a','b','l','e','D','N','S','\0' };
static const WCHAR BcastNameQueryCountW[] = { 'B','c','a','s','t','N','a','m',
'e','Q','u','e','r','y','C','o','u','n','t','\0' };
static const WCHAR BcastNameQueryTimeoutW[] = { 'B','c','a','s','t','N','a','m',
'e','Q','u','e','r','y','T','i','m','e','o','u','t','\0' };
static const WCHAR NameSrvQueryCountW[] = { 'N','a','m','e','S','r','v',
'Q','u','e','r','y','C','o','u','n','t','\0' };
static const WCHAR NameSrvQueryTimeoutW[] = { 'N','a','m','e','S','r','v',
'Q','u','e','r','y','T','i','m','e','o','u','t','\0' };
static const WCHAR ScopeIDW[] = { 'S','c','o','p','e','I','D','\0' };
static const WCHAR CacheTimeoutW[] = { 'C','a','c','h','e','T','i','m','e','o',
'u','t','\0' };
static const WCHAR Config_NetworkW[] = { 'S','o','f','t','w','a','r','e','\\',
'W','i','n','e','\\','N','e','t','w','o','r','k','\0' };
/* Initializes global variables and registers the NetBT transport */
void NetBTInit(void)
{
HKEY hKey;
NetBIOSTransport transport;
LONG ret;
TRACE("\n");
gEnableDNS = TRUE;
gBCastQueries = BCAST_QUERIES;
gBCastQueryTimeout = BCAST_QUERY_TIMEOUT;
gWINSQueries = WINS_QUERIES;
gWINSQueryTimeout = WINS_QUERY_TIMEOUT;
gNumWINSServers = 0;
memset(gWINSServers, 0, sizeof(gWINSServers));
gScopeID[0] = '\0';
gCacheTimeout = CACHE_TIMEOUT;
/* Try to open the Win9x NetBT configuration key */
ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, VxD_MSTCPW, 0, KEY_READ, &hKey);
/* If that fails, try the WinNT NetBT configuration key */
if (ret != ERROR_SUCCESS)
ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, NetBT_ParametersW, 0, KEY_READ,
&hKey);
if (ret == ERROR_SUCCESS)
{
DWORD dword, size;
size = sizeof(dword);
if (RegQueryValueExW(hKey, EnableDNSW, NULL, NULL,
(LPBYTE)&dword, &size) == ERROR_SUCCESS)
gEnableDNS = dword;
size = sizeof(dword);
if (RegQueryValueExW(hKey, BcastNameQueryCountW, NULL, NULL,
(LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_QUERIES
&& dword <= MAX_QUERIES)
gBCastQueries = dword;
size = sizeof(dword);
if (RegQueryValueExW(hKey, BcastNameQueryTimeoutW, NULL, NULL,
(LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_QUERY_TIMEOUT
&& dword <= MAX_QUERY_TIMEOUT)
gBCastQueryTimeout = dword;
size = sizeof(dword);
if (RegQueryValueExW(hKey, NameSrvQueryCountW, NULL, NULL,
(LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_QUERIES
&& dword <= MAX_QUERIES)
gWINSQueries = dword;
size = sizeof(dword);
if (RegQueryValueExW(hKey, NameSrvQueryTimeoutW, NULL, NULL,
(LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_QUERY_TIMEOUT
&& dword <= MAX_QUERY_TIMEOUT)
gWINSQueryTimeout = dword;
size = MAX_DOMAIN_NAME_LEN - 1;
if (RegQueryValueExW(hKey, ScopeIDW, NULL, NULL, (LPBYTE)gScopeID + 1, &size)
== ERROR_SUCCESS)
{
/* convert into L2-encoded version, suitable for use by
NetBTNameEncode */
char *ptr, *lenPtr;
for (ptr = gScopeID + 1; *ptr &&
ptr - gScopeID < MAX_DOMAIN_NAME_LEN; )
{
for (lenPtr = ptr - 1, *lenPtr = 0; *ptr && *ptr != '.' &&
ptr - gScopeID < MAX_DOMAIN_NAME_LEN; ptr++)
*lenPtr += 1;
ptr++;
}
}
if (RegQueryValueExW(hKey, CacheTimeoutW, NULL, NULL,
(LPBYTE)&dword, &size) == ERROR_SUCCESS && dword >= MIN_CACHE_TIMEOUT)
gCacheTimeout = dword;
RegCloseKey(hKey);
}
/* WINE-specific NetBT registry settings. Because our adapter naming is
* different than MS', we can't do per-adapter WINS configuration in the
* same place. Just do a global WINS configuration instead.
*/
/* @@ Wine registry key: HKCU\Software\Wine\Network */
if (RegOpenKeyW(HKEY_CURRENT_USER, Config_NetworkW, &hKey) == ERROR_SUCCESS)
{
static const char *nsValueNames[] = { "WinsServer", "BackupWinsServer" };
char nsString[16];
DWORD size, ndx;
for (ndx = 0; ndx < sizeof(nsValueNames) / sizeof(nsValueNames[0]);
ndx++)
{
size = sizeof(nsString) / sizeof(char);
if (RegQueryValueExA(hKey, nsValueNames[ndx], NULL, NULL,
(LPBYTE)nsString, &size) == ERROR_SUCCESS)
{
unsigned long addr = inet_addr(nsString);
if (addr != INADDR_NONE && gNumWINSServers < MAX_WINS_SERVERS)
gWINSServers[gNumWINSServers++] = addr;
}
}
RegCloseKey(hKey);
}
transport.enumerate = NetBTEnum;
transport.astat = NetBTAstat;
transport.findName = NetBTFindName;
transport.call = NetBTCall;
transport.send = NetBTSend;
transport.recv = NetBTRecv;
transport.hangup = NetBTHangup;
transport.cleanupAdapter = NetBTCleanupAdapter;
transport.cleanup = NetBTCleanup;
memcpy(&gTransportID, TRANSPORT_NBT, sizeof(ULONG));
NetBIOSRegisterTransport(gTransportID, &transport);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -