1151 lines
40 KiB
C
1151 lines
40 KiB
C
//++
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1987 - 1999
|
|
//
|
|
// Module Name:
|
|
//
|
|
// nbtnm.c
|
|
//
|
|
// Abstract:
|
|
//
|
|
// Queries into network drivers
|
|
//
|
|
// Author:
|
|
//
|
|
// Anilth - 4-20-1998
|
|
//
|
|
// Environment:
|
|
//
|
|
// User mode only.
|
|
// Contains NT-specific code.
|
|
//
|
|
// Revision History:
|
|
//
|
|
// NSun - 9-03-1998
|
|
//
|
|
//--
|
|
#include "precomp.h"
|
|
|
|
#include "dhcptest.h"
|
|
|
|
const TCHAR c_szPath[] = _T("\\Device\\NetBT_Tcpip_");
|
|
TCHAR pDeviceName[NBT_MAXIMUM_BINDINGS][MAX_NAME+1];
|
|
|
|
TCHAR * printable( IN TCHAR * string, IN TCHAR * StrOut );
|
|
|
|
//$REVIEW (nsun) previously using ReadNbtNameRegistry() see Bug 152014
|
|
LONG GetInterfaceList( IN OUT TCHAR pDeviceName[][MAX_NAME+1], IN OUT PUCHAR pScope );
|
|
NTSTATUS OpenNbt(IN char path[][MAX_NAME+1], OUT PHANDLE pHandle, int max_paths);
|
|
NTSTATUS DeviceIoCtrl(
|
|
IN HANDLE fd,
|
|
IN PVOID ReturnBuffer,
|
|
IN ULONG BufferSize,
|
|
IN ULONG Ioctl,
|
|
IN PVOID pInput,
|
|
IN ULONG SizeInput
|
|
);
|
|
|
|
|
|
/* =======================================================================
|
|
* name_type() -- describe NBT Name types
|
|
*
|
|
*/
|
|
|
|
char *
|
|
name_type(int t)
|
|
{
|
|
if (t & GROUP_NAME) return("GROUP");
|
|
else return("UNIQUE");
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------//
|
|
//###### N b t N m T e s t () ###########################################//
|
|
//-------------------------------------------------------------------------//
|
|
// Abstract: //
|
|
// Test that the names //
|
|
// <00> - wks svc name = NETBIOS computer name //
|
|
// <03> - messenger svc name //
|
|
// <20> - server svc name //
|
|
// are present on all interfaces and that they are not in conflict //
|
|
// Arguments: //
|
|
// none //
|
|
// Return value: //
|
|
// TRUE - test passed //
|
|
// FALSE - test failed //
|
|
// Global variables used: //
|
|
// none //
|
|
// Revision History: //
|
|
// List remote machines cache too - Rajkumar 06/30/98 //
|
|
//-------------------------------------------------------------------------//
|
|
HRESULT NbtNmTest(NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
TCHAR pScope[MAX_NAME + 1];
|
|
int index;
|
|
HANDLE hNbt = (HANDLE) -1;
|
|
ULONG BufferSize = sizeof(tADAPTERSTATUS);
|
|
PVOID pBuffer = NULL;
|
|
LONG lCount;
|
|
int nNameProblemCnt = 0;
|
|
BOOL is00, is03, is20, isGlobal00, isGlobal03, isGlobal20;
|
|
|
|
tADAPTERSTATUS *pAdapterStatus;
|
|
NAME_BUFFER *pNames;
|
|
NTSTATUS status;
|
|
TDI_REQUEST_QUERY_INFORMATION QueryInfo;
|
|
|
|
//
|
|
// Variables for Netbios Name resolution option - Rajkumar
|
|
//
|
|
|
|
HKEY hkeyNetBTKey;
|
|
HKEY hkeyNBTAdapterKey;
|
|
DWORD valueType;
|
|
DWORD valueLength;
|
|
DWORD NetbiosOptions;
|
|
INT err;
|
|
|
|
//
|
|
// For remote cache information
|
|
//
|
|
|
|
UCHAR* Addr;
|
|
TCHAR HostAddr[20];
|
|
|
|
//
|
|
// End of changes - Rajkumar 06/17/98
|
|
//
|
|
|
|
PrintStatusMessage(pParams, 4, IDS_NBTNM_STATUS_MSG);
|
|
|
|
//Init the global message link list
|
|
InitializeListHead( &pResults->NbtNm.lmsgGlobalOutput );
|
|
|
|
if (!pResults->Global.fHasNbtEnabledInterface)
|
|
{
|
|
AddMessageToList( &pResults->NbtNm.lmsgGlobalOutput, Nd_Verbose, IDS_NBTNM_ALL_DISABELED);
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// get the names of all the interfaces from the registry
|
|
//
|
|
if ( ERROR_SUCCESS != GetInterfaceList( pDeviceName, pScope ) )
|
|
{
|
|
//IDS_NBTNM_12201 " [FATAL] failed to read NBT interface info from the registry!\n"
|
|
AddMessageToListId( &pResults->NbtNm.lmsgGlobalOutput, Nd_Quiet, IDS_NBTNM_12201 );
|
|
hr = S_FALSE;
|
|
goto end_NbtNmTest;
|
|
}
|
|
|
|
|
|
if ( *pScope == '\0')
|
|
//IDS_NBTNM_12202 " No NetBT scope defined\n"
|
|
AddMessageToListId( &pResults->NbtNm.lmsgGlobalOutput, Nd_ReallyVerbose, IDS_NBTNM_12202 );
|
|
else
|
|
//IDS_NBTNM_12203 " NetBT scope: %s\n"
|
|
AddMessageToList( &pResults->NbtNm.lmsgGlobalOutput, Nd_ReallyVerbose, IDS_NBTNM_12203, pScope );
|
|
|
|
//
|
|
// loop through the interfaces and get the names on them
|
|
//
|
|
|
|
isGlobal00 = isGlobal03 = isGlobal20 = FALSE;
|
|
for ( index = 0; index < NBT_MAXIMUM_BINDINGS && pDeviceName[index][0]; index++ )
|
|
{
|
|
LPTSTR pszAdapterName;
|
|
INTERFACE_RESULT* pIfResults;
|
|
UINT c03NameProblem = 0;
|
|
|
|
pIfResults = NULL;
|
|
|
|
//try to find a match in the current interface list
|
|
//$REVIEW It seems we should always find a match here. Maybe we need print
|
|
// a FAIL message if cannot find a match.
|
|
if( 0 == _tcsncmp(c_szPath, pDeviceName[index], _tcslen(c_szPath)))
|
|
{
|
|
// LPTSTR pszAdapterName;
|
|
int i;
|
|
pszAdapterName = _tcsdup( pDeviceName[index] + _tcslen(c_szPath));
|
|
for ( i=0; i<pResults->cNumInterfaces; i++)
|
|
{
|
|
if (_tcscmp(pResults->pArrayInterface[i].pszName,
|
|
pszAdapterName) == 0)
|
|
{
|
|
pIfResults = pResults->pArrayInterface + i;
|
|
break;
|
|
}
|
|
}
|
|
Free(pszAdapterName);
|
|
}
|
|
|
|
if(NULL == pIfResults)
|
|
{
|
|
//we should be able to get the match. That is weird!
|
|
DebugMessage("[WARNING] A NetBT interface is not in our TCPIP interface list!\n");
|
|
|
|
// We need a new interface result structure, grab one
|
|
// (if it is free), else allocate more.
|
|
if (pResults->cNumInterfaces >= pResults->cNumInterfacesAllocated)
|
|
{
|
|
PVOID pv;
|
|
// Need to do a realloc to get more memory
|
|
pv = Realloc(pResults->pArrayInterface,
|
|
sizeof(INTERFACE_RESULT)*(pResults->cNumInterfacesAllocated+8));
|
|
if (pv == NULL)
|
|
{
|
|
DebugMessage(" Realloc memory failed. \n");
|
|
hr = E_OUTOFMEMORY;
|
|
goto end_NbtNmTest;
|
|
}
|
|
|
|
pResults->pArrayInterface = pv;
|
|
pResults->cNumInterfacesAllocated += 8;
|
|
}
|
|
|
|
pIfResults = pResults->pArrayInterface + pResults->cNumInterfaces;
|
|
pResults->cNumInterfaces++;
|
|
|
|
ZeroMemory(pIfResults, sizeof(INTERFACE_RESULT));
|
|
pIfResults->pszName = _tcsdup(pszAdapterName);
|
|
pIfResults->pszFriendlyName = _tcsdup(_T("Additional NetBT interface"));
|
|
|
|
pIfResults->fActive = TRUE;
|
|
pIfResults->NbtNm.fActive = TRUE;
|
|
pIfResults->NbtNm.fQuietOutput = FALSE;
|
|
}
|
|
else
|
|
{
|
|
pIfResults->NbtNm.fActive = pIfResults->fActive;
|
|
}
|
|
|
|
if(!pIfResults->NbtNm.fActive ||
|
|
NETCARD_DISCONNECTED == pIfResults->dwNetCardStatus)
|
|
continue;
|
|
|
|
InitializeListHead( &pIfResults->NbtNm.lmsgOutput );
|
|
|
|
if (!pIfResults->fNbtEnabled)
|
|
{
|
|
AddMessageToList(&pIfResults->NbtNm.lmsgOutput, Nd_Verbose, IDS_NBTNM_IF_DISABLED);
|
|
continue;
|
|
}
|
|
|
|
/* //$REVIEW Can we skip WAN adapters
|
|
if ( _tcsstr( pDeviceName[index], "NdisWan" ) ) {
|
|
//
|
|
// let's not worry about WAN interfaces yet
|
|
//
|
|
continue;
|
|
}
|
|
*/
|
|
|
|
// Strip off the "\Device\" off of the beginning of
|
|
// the string
|
|
//IDS_NBTNM_12204 " %s\n"
|
|
AddMessageToList( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12204, MapGuidToServiceName(pDeviceName[index]+8));
|
|
|
|
status = OpenNbt( &pDeviceName[index], &hNbt, NBT_MAXIMUM_BINDINGS - index );
|
|
|
|
|
|
//
|
|
// let's get the names on this interface
|
|
//
|
|
|
|
pBuffer = Malloc( BufferSize );
|
|
if ( !pBuffer ) {
|
|
DebugMessage(" [FATAL] name table buffer allocation failed!\n" );
|
|
hr = E_OUTOFMEMORY;
|
|
CloseHandle( hNbt );
|
|
goto end_NbtNmTest;
|
|
}
|
|
ZeroMemory( pBuffer, BufferSize );
|
|
|
|
QueryInfo.QueryType = TDI_QUERY_ADAPTER_STATUS; // node status or whatever
|
|
|
|
//
|
|
// find the right buffer size
|
|
//
|
|
status = STATUS_BUFFER_OVERFLOW;
|
|
while ( status == STATUS_BUFFER_OVERFLOW )
|
|
{
|
|
//$REVIEW there should be a better way to decide the buffer size
|
|
status = DeviceIoCtrl(hNbt,
|
|
pBuffer,
|
|
BufferSize,
|
|
IOCTL_TDI_QUERY_INFORMATION,
|
|
&QueryInfo,
|
|
sizeof(TDI_REQUEST_QUERY_INFORMATION)
|
|
);
|
|
if ( status == STATUS_BUFFER_OVERFLOW ) {
|
|
Free( pBuffer );
|
|
BufferSize *= 2;
|
|
pBuffer = Malloc( BufferSize );
|
|
if ( !pBuffer ) {
|
|
DebugMessage( " [FATAL] Buffer allocation for name table retrieval failed.\n" );
|
|
hr = E_OUTOFMEMORY;
|
|
CloseHandle( hNbt );
|
|
goto end_NbtNmTest;
|
|
}
|
|
ZeroMemory( pBuffer, BufferSize );
|
|
}
|
|
}
|
|
|
|
//
|
|
// at this point we have the local name table in pBuffer
|
|
//
|
|
|
|
pAdapterStatus = (tADAPTERSTATUS *)pBuffer;
|
|
if ( (pAdapterStatus->AdapterInfo.name_count == 0) ||
|
|
(status != STATUS_SUCCESS) )
|
|
{
|
|
//IDS_NBTNM_12205 " No names have been found.\n"
|
|
AddMessageToListId(&pIfResults->NbtNm.lmsgOutput, Nd_Verbose, IDS_NBTNM_12205 );
|
|
Free( pBuffer );
|
|
CloseHandle( hNbt );
|
|
continue;
|
|
}
|
|
|
|
pNames = pAdapterStatus->Names;
|
|
lCount = pAdapterStatus->AdapterInfo.name_count;
|
|
|
|
//
|
|
// cycle thorugh the names
|
|
//
|
|
|
|
nNameProblemCnt = 0;
|
|
is00 = is03 = is20 = FALSE;
|
|
while( lCount-- )
|
|
{
|
|
TCHAR szNameOut[NETBIOS_NAME_SIZE +4];
|
|
//$REVIEW (nsun) BUG227186 CliffV said problems with <03> name is not fatal.
|
|
// Just need a warning message.
|
|
BOOL f03Name = FALSE;
|
|
|
|
if ( pNames->name[NETBIOS_NAME_SIZE-1] == 0x0 )
|
|
{
|
|
isGlobal00 = TRUE;
|
|
is00 = TRUE;
|
|
if ( !(pNames->name_flags & GROUP_NAME) ) {
|
|
// unique name
|
|
memcpy( nameToQry, pNames->name, (NETBIOS_NAME_SIZE-1));
|
|
}
|
|
}
|
|
if ( pNames->name[NETBIOS_NAME_SIZE-1] == 0x3 ) {
|
|
isGlobal03 = TRUE;
|
|
is03 = TRUE;
|
|
f03Name = TRUE;
|
|
}
|
|
if ( pNames->name[NETBIOS_NAME_SIZE-1] == 0x20 ) {
|
|
isGlobal20 = TRUE;
|
|
is20 = TRUE;
|
|
}
|
|
|
|
//IDS_NBTNM_12206 "\t%-15.15s<%02.2X> %-10s "
|
|
AddMessageToList( &pIfResults->NbtNm.lmsgOutput,
|
|
Nd_ReallyVerbose,
|
|
IDS_NBTNM_12206,
|
|
printable(pNames->name, szNameOut),
|
|
pNames->name[NETBIOS_NAME_SIZE-1],
|
|
name_type(pNames->name_flags));
|
|
|
|
switch(pNames->name_flags & 0x0F)
|
|
{
|
|
case DUPLICATE_DEREG:
|
|
//IDS_NBTNM_12207 "CONFLICT_DEREGISTERED"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12207 );
|
|
|
|
if(f03Name)
|
|
c03NameProblem ++;
|
|
else
|
|
nNameProblemCnt++;
|
|
break;
|
|
case DUPLICATE:
|
|
//IDS_NBTNM_12208 "CONFLICT"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12208 );
|
|
|
|
if(f03Name)
|
|
c03NameProblem ++;
|
|
else
|
|
nNameProblemCnt++;
|
|
break;
|
|
case REGISTERING:
|
|
//IDS_NBTNM_12209 "REGISTERING"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12209 );
|
|
|
|
if(f03Name)
|
|
c03NameProblem ++;
|
|
else
|
|
nNameProblemCnt++;
|
|
break;
|
|
case DEREGISTERED:
|
|
//IDS_NBTNM_12210 "DEREGISTERED"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12210 );
|
|
|
|
if(f03Name)
|
|
c03NameProblem ++;
|
|
else
|
|
nNameProblemCnt++;
|
|
break;
|
|
case REGISTERED:
|
|
//IDS_NBTNM_12211 "REGISTERED"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12211 );
|
|
break;
|
|
default:
|
|
//$REVIEW Should have a PM to review words and grammar of the output message, DONT_KNOW
|
|
//IDS_NBTNM_12212 "DONT_KNOW"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12212 );
|
|
if(f03Name)
|
|
c03NameProblem ++;
|
|
else
|
|
nNameProblemCnt++;
|
|
break;
|
|
}
|
|
pNames++;
|
|
|
|
//IDS_GLOBAL_EmptyLine "\n"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_GLOBAL_EmptyLine );
|
|
} /* while() all the names on a given interface */
|
|
|
|
if ( nNameProblemCnt != 0 )
|
|
{
|
|
pIfResults->NbtNm.fQuietOutput = TRUE;
|
|
//if not really verbose, the device name is not printed before.
|
|
if( !pParams->fReallyVerbose)
|
|
{
|
|
//IDS_NBTNM_12204 " %s\n"
|
|
AddMessageToList( &pIfResults->NbtNm.lmsgOutput, Nd_Quiet, IDS_NBTNM_12204, pDeviceName[index] );
|
|
}
|
|
//IDS_NBTNM_12214 " [FATAL] At least one of your NetBT names is not registered properly!\n"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_Quiet, IDS_NBTNM_12214 );
|
|
//IDS_NBTNM_12215 " You have a potential name conflict!\n"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_Quiet, IDS_NBTNM_12215 );
|
|
//IDS_NBTNM_12216 " Please check that the machine name is unique!\n"
|
|
AddMessageToList( &pIfResults->NbtNm.lmsgOutput, Nd_Quiet, IDS_NBTNM_12216 );
|
|
hr = S_FALSE;
|
|
}
|
|
else if( c03NameProblem != 0 )
|
|
{
|
|
//if not really verbose, the device name is not printed before.
|
|
if( !pParams->fReallyVerbose)
|
|
{
|
|
//IDS_NBTNM_12204 " %s\n"
|
|
AddMessageToList( &pIfResults->NbtNm.lmsgOutput, Nd_Quiet, IDS_NBTNM_12204, pDeviceName[index] );
|
|
}
|
|
//IDS_NBTNM_03PROBLEM " [WARNING] At least one of your <03> NetBT names is not registered properly!\n"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_Quiet, IDS_NBTNM_03PROBLEM );
|
|
|
|
}
|
|
|
|
if ( !(is00 && is03 && is20) )
|
|
{
|
|
//if not really verbose, the device name is not printed before.
|
|
if( !pParams->fReallyVerbose)
|
|
{
|
|
//IDS_NBTNM_12204 " %s\n"
|
|
AddMessageToList( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12204, pDeviceName[index] );
|
|
}
|
|
//IDS_NBTNM_12217 " [WARNING] At least one of the <00>, <03>, <20> names is missing!\n"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_Verbose, IDS_NBTNM_12217 );
|
|
}
|
|
|
|
nNameProblemCnt = 0;
|
|
|
|
if (pParams->fReallyVerbose)
|
|
{
|
|
|
|
err = RegOpenKey(HKEY_LOCAL_MACHINE,
|
|
"SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters\\Interfaces",
|
|
&hkeyNetBTKey
|
|
);
|
|
|
|
// if we are here , then we are working on a LAN card
|
|
if( ERROR_SUCCESS != err )
|
|
{
|
|
DebugMessage("Error Opening \\NetBT\\Parameters\\Interfaces Key\n");
|
|
goto continue_NbtNmTest;
|
|
}
|
|
|
|
err = RegOpenKey(hkeyNetBTKey,
|
|
pDeviceName[index]+14,
|
|
&hkeyNBTAdapterKey
|
|
);
|
|
if( ERROR_SUCCESS != err )
|
|
{
|
|
DebugMessage2("Error Reading Adapter %s Key\n", pDeviceName[index]+14);
|
|
goto continue_NbtNmTest;
|
|
}
|
|
|
|
valueLength = sizeof(DWORD);
|
|
err = RegQueryValueEx(hkeyNBTAdapterKey,
|
|
"NetbiosOptions",
|
|
NULL,
|
|
&valueType,
|
|
(LPBYTE)&NetbiosOptions,
|
|
&valueLength
|
|
);
|
|
if( ERROR_SUCCESS != err)
|
|
{
|
|
DebugMessage("Error Reading NetbiosOptions\n");
|
|
goto continue_NbtNmTest;
|
|
}
|
|
|
|
//IDS_NBTNM_12218 "\n NetBios Resolution : "
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12218);
|
|
switch( NetbiosOptions )
|
|
{
|
|
case 0:
|
|
//IDS_NBTNM_12219 "via DHCP \n\n"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12219);
|
|
break;
|
|
case 1:
|
|
//IDS_NBTNM_12220 "Enabled\n\n"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12220);
|
|
break;
|
|
case 2:
|
|
//IDS_NBTNM_12221 "Disabled\n\n"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12221);
|
|
break;
|
|
default:
|
|
//IDS_NBTNM_12222 "Invalid Option Value!\n"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12222);
|
|
break;
|
|
}
|
|
}
|
|
continue_NbtNmTest:
|
|
|
|
//
|
|
// Start of code changes for dumping remote machine cache entries - Rajkumar
|
|
//
|
|
|
|
|
|
status = STATUS_BUFFER_OVERFLOW;
|
|
while ( status == STATUS_BUFFER_OVERFLOW )
|
|
{
|
|
status = DeviceIoCtrl(hNbt,
|
|
pBuffer,
|
|
BufferSize,
|
|
IOCTL_NETBT_GET_REMOTE_NAMES,
|
|
NULL,
|
|
0
|
|
);
|
|
if ( status == STATUS_BUFFER_OVERFLOW )
|
|
{
|
|
Free( pBuffer );
|
|
BufferSize *= 2;
|
|
pBuffer = Malloc( BufferSize );
|
|
if ( !pBuffer || (BufferSize == 0xFFFF) )
|
|
{
|
|
DebugMessage( " [FATAL] Buffer allocation for name table retrieval failed.\n" );
|
|
hr = E_OUTOFMEMORY;
|
|
CloseHandle( hNbt );
|
|
goto end_NbtNmTest;
|
|
}
|
|
ZeroMemory( pBuffer, BufferSize );
|
|
}
|
|
}
|
|
|
|
|
|
pAdapterStatus = (tADAPTERSTATUS *)pBuffer;
|
|
if ( (pAdapterStatus->AdapterInfo.name_count == 0) ||
|
|
(status != STATUS_SUCCESS)
|
|
)
|
|
{
|
|
//IDS_NBTNM_12224 " No remote names have been found.\n"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_Verbose, IDS_NBTNM_12224 );
|
|
CloseHandle( hNbt );
|
|
Free( pBuffer );
|
|
//$REVIEW Should we return S_FALSE here?
|
|
continue;
|
|
}
|
|
|
|
pNames = pAdapterStatus->Names;
|
|
lCount = pAdapterStatus->AdapterInfo.name_count;
|
|
|
|
//IDS_NBTNM_12225 "\t\tNetbios Remote Cache Table\n"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12225);
|
|
//IDS_NBTNM_12226 "\tName Type HostAddress Life [sec]\n"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12226);
|
|
//IDS_NBTNM_12227 "\t--------------------------------------------------\n"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12227);
|
|
|
|
if (lCount == 0)
|
|
//IDS_NBTNM_12228 "\nNone\n\n"
|
|
AddMessageToListId( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12228);
|
|
|
|
while (lCount-- )
|
|
{
|
|
TCHAR szNameOut[NETBIOS_NAME_SIZE +4];
|
|
|
|
//IDS_NBTNM_12229 "\t%-15.15s<%02.2X> %-10s "
|
|
AddMessageToList( &pIfResults->NbtNm.lmsgOutput,
|
|
Nd_ReallyVerbose,
|
|
IDS_NBTNM_12229,
|
|
printable(pNames->name, szNameOut),
|
|
pNames->name[NETBIOS_NAME_SIZE-1],
|
|
name_type(pNames->name_flags));
|
|
|
|
Addr = &(UCHAR)((tREMOTE_CACHE *)pNames)->IpAddress;
|
|
_stprintf( HostAddr, "%d.%d.%d.%d", Addr[3], Addr[2], Addr[1], Addr[0]);
|
|
//IDS_NBTNM_12231 "%-20.20s %-d\n"
|
|
AddMessageToList( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_NBTNM_12231, HostAddr, ((tREMOTE_CACHE *)pNames)->Ttl);
|
|
|
|
((tREMOTE_CACHE *)pNames)++;
|
|
}
|
|
|
|
//IDS_GLOBAL_EmptyLine "\n"
|
|
AddMessageToList( &pIfResults->NbtNm.lmsgOutput, Nd_ReallyVerbose, IDS_GLOBAL_EmptyLine);
|
|
Free(pBuffer);
|
|
//
|
|
// End of code changes
|
|
//
|
|
|
|
CloseHandle(hNbt);
|
|
} /* for ( all the interfaces ) */
|
|
|
|
|
|
if ( !(isGlobal00 && isGlobal03 && isGlobal20) )
|
|
{
|
|
//IDS_NBTNM_12233 " [WARNING] You don't have a single interface with the <00>, <03>, <20> names defined!\n"
|
|
AddMessageToListId( &pResults->NbtNm.lmsgGlobalOutput, Nd_Quiet, IDS_NBTNM_12233 );
|
|
}
|
|
else
|
|
{
|
|
//IDS_NBTNM_12234 "\n PASS - your NetBT configuration looks OK\n"
|
|
AddMessageToListId( &pResults->NbtNm.lmsgGlobalOutput, Nd_ReallyVerbose, IDS_NBTNM_12234 );
|
|
//IDS_NBTNM_12235 " there is at least one interface where the <00>, <03>, <20>\n"
|
|
AddMessageToList( &pResults->NbtNm.lmsgGlobalOutput, Nd_ReallyVerbose, IDS_NBTNM_12235 );
|
|
//IDS_NBTNM_12236 " names are defined and they are not in conflict.\n"
|
|
AddMessageToListId( &pResults->NbtNm.lmsgGlobalOutput, Nd_ReallyVerbose, IDS_NBTNM_12236 );
|
|
}
|
|
|
|
end_NbtNmTest:
|
|
if ( FHrOK(hr) )
|
|
{
|
|
PrintStatusMessage(pParams, 0, IDS_GLOBAL_PASS_NL);
|
|
}
|
|
else
|
|
{
|
|
PrintStatusMessage(pParams, 0, IDS_GLOBAL_FAIL_NL);
|
|
}
|
|
|
|
pResults->NbtNm.hrTestResult = hr;
|
|
return hr;
|
|
} /* END OF NbtNmTest() */
|
|
|
|
|
|
//-------------------------------------------------------------------------//
|
|
//###### O p e n N b t () ###############################################//
|
|
//-------------------------------------------------------------------------//
|
|
// Abstract: //
|
|
// Opens a handle to the device //
|
|
// Arguments: //
|
|
// path - path to the driver //
|
|
// pHandle - the handle that we return from this function //
|
|
// max_paths - I think this is unused //
|
|
// Return value: //
|
|
// 0 if successful //
|
|
// -1 otherwise //
|
|
// Global variables used: //
|
|
// none //
|
|
//-------------------------------------------------------------------------//
|
|
NTSTATUS
|
|
OpenNbt(
|
|
IN TCHAR path[][MAX_NAME+1],
|
|
OUT PHANDLE pHandle,
|
|
int max_paths
|
|
)
|
|
{
|
|
HANDLE StreamHandle;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
STRING name_string;
|
|
UNICODE_STRING uc_name_string;
|
|
NTSTATUS status;
|
|
LONG index=0;
|
|
|
|
assert( max_paths <= NBT_MAXIMUM_BINDINGS );
|
|
|
|
while ((path[index][0] != 0) && (index < max_paths))
|
|
{
|
|
|
|
RtlInitString(&name_string, path[index]);
|
|
RtlAnsiStringToUnicodeString(&uc_name_string, &name_string, TRUE);
|
|
|
|
InitializeObjectAttributes(
|
|
&ObjectAttributes,
|
|
&uc_name_string,
|
|
OBJ_CASE_INSENSITIVE,
|
|
(HANDLE) NULL,
|
|
(PSECURITY_DESCRIPTOR) NULL
|
|
);
|
|
|
|
status = NtCreateFile(
|
|
&StreamHandle,
|
|
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
|
|
&ObjectAttributes,
|
|
&IoStatusBlock,
|
|
NULL,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
FILE_OPEN_IF,
|
|
0,
|
|
NULL,
|
|
0);
|
|
|
|
RtlFreeUnicodeString(&uc_name_string);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
*pHandle = StreamHandle;
|
|
return(status);
|
|
}
|
|
|
|
++index;
|
|
}
|
|
|
|
return (status);
|
|
} /* END OF OpenNbt() */
|
|
|
|
|
|
//-------------------------------------------------------------------------//
|
|
//###### D e v i c e I o C t r l () #####################################//
|
|
//-------------------------------------------------------------------------//
|
|
// Abstract: //
|
|
// Wrapper for NtDeviceIoControlFile //
|
|
// Arguments: //
|
|
// Return value: //
|
|
// Global variables used: //
|
|
// none //
|
|
//-------------------------------------------------------------------------//
|
|
NTSTATUS
|
|
DeviceIoCtrl(
|
|
IN HANDLE fd,
|
|
IN PVOID ReturnBuffer,
|
|
IN ULONG BufferSize,
|
|
IN ULONG Ioctl,
|
|
IN PVOID pInput,
|
|
IN ULONG SizeInput
|
|
)
|
|
{
|
|
NTSTATUS status;
|
|
int retval;
|
|
ULONG QueryType;
|
|
IO_STATUS_BLOCK iosb;
|
|
|
|
|
|
status = NtDeviceIoControlFile(
|
|
fd, // Handle
|
|
NULL, // Event
|
|
NULL, // ApcRoutine
|
|
NULL, // ApcContext
|
|
&iosb, // IoStatusBlock
|
|
Ioctl, // IoControlCode
|
|
pInput, // InputBuffer
|
|
SizeInput, // InputBufferSize
|
|
(PVOID) ReturnBuffer, // OutputBuffer
|
|
BufferSize); // OutputBufferSize
|
|
|
|
|
|
if (status == STATUS_PENDING)
|
|
{
|
|
status = NtWaitForSingleObject(
|
|
fd, // Handle
|
|
TRUE, // Alertable
|
|
NULL); // Timeout
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
status = iosb.Status;
|
|
}
|
|
}
|
|
|
|
return(status);
|
|
|
|
} /* END OF DeviceIoCtrl() */
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This procedure converts non prinatble characaters to periods ('.')
|
|
|
|
Arguments:
|
|
string - the string to convert
|
|
StrOut - ptr to a string to put the converted string into
|
|
|
|
Return Value:
|
|
|
|
a ptr to the string that was converted (Strout)
|
|
|
|
--*/
|
|
|
|
TCHAR *
|
|
printable(
|
|
IN TCHAR * string,
|
|
IN TCHAR * StrOut
|
|
)
|
|
{
|
|
unsigned char *Out;
|
|
unsigned char *cp;
|
|
LONG i;
|
|
|
|
Out = StrOut;
|
|
for (cp = string, i= 0; i < NETBIOS_NAME_SIZE; cp++,i++) {
|
|
if (isprint(*cp)) {
|
|
*Out++ = *cp;
|
|
continue;
|
|
}
|
|
|
|
if (*cp >= 128) { /* extended characters are ok */
|
|
*Out++ = *cp;
|
|
continue;
|
|
}
|
|
*Out++ = '.';
|
|
}
|
|
return(StrOut);
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
NTSTATUS
|
|
GetInterfaceList( IN OUT TCHAR pDeviceName[][MAX_NAME+1],
|
|
IN OUT PUCHAR pScope
|
|
)
|
|
{
|
|
HANDLE StreamHandle;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
STRING name_string, AnsiString;
|
|
UNICODE_STRING uc_name_string;
|
|
NTSTATUS status;
|
|
char pNbtWinsDeviceName[MAX_NAME] = "\\Device\\NetBt_Wins_Export";
|
|
|
|
PUCHAR SubKeyParms="system\\currentcontrolset\\services\\netbt\\parameters";
|
|
HKEY Key;
|
|
LONG Type;
|
|
ULONG size;
|
|
CHAR pScopeBuffer[BUFF_SIZE];
|
|
PUCHAR Scope="ScopeId";
|
|
|
|
NETBT_INTERFACE_INFO *pInterfaceInfo;
|
|
ULONG InterfaceInfoSize=10*sizeof(NETBT_ADAPTER_INDEX_MAP)+sizeof(ULONG);
|
|
PVOID pInput = NULL;
|
|
ULONG SizeInput = 0;
|
|
|
|
LONG i, index=0;
|
|
|
|
pInterfaceInfo = LocalAlloc(LMEM_FIXED,InterfaceInfoSize);
|
|
if (!pInterfaceInfo)
|
|
{
|
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
|
|
RtlInitString(&name_string, pNbtWinsDeviceName);
|
|
RtlAnsiStringToUnicodeString(&uc_name_string, &name_string, TRUE);
|
|
|
|
InitializeObjectAttributes(
|
|
&ObjectAttributes,
|
|
&uc_name_string,
|
|
OBJ_CASE_INSENSITIVE,
|
|
(HANDLE) NULL,
|
|
(PSECURITY_DESCRIPTOR) NULL
|
|
);
|
|
|
|
status = NtCreateFile (&StreamHandle,
|
|
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
|
|
&ObjectAttributes,
|
|
&IoStatusBlock,
|
|
NULL,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
FILE_OPEN_IF,
|
|
0,
|
|
NULL,
|
|
0);
|
|
|
|
RtlFreeUnicodeString(&uc_name_string);
|
|
|
|
if (NT_SUCCESS (status))
|
|
{
|
|
do
|
|
{
|
|
status = DeviceIoCtrl(StreamHandle,
|
|
pInterfaceInfo,
|
|
InterfaceInfoSize,
|
|
IOCTL_NETBT_GET_INTERFACE_INFO,
|
|
pInput,
|
|
SizeInput);
|
|
|
|
if (status == STATUS_BUFFER_OVERFLOW)
|
|
{
|
|
LocalFree(pInterfaceInfo);
|
|
|
|
InterfaceInfoSize *=2;
|
|
pInterfaceInfo = LocalAlloc(LMEM_FIXED,InterfaceInfoSize);
|
|
if (!pInterfaceInfo || (InterfaceInfoSize == 0xFFFF))
|
|
{
|
|
NtClose(StreamHandle);
|
|
DebugMessage("\nUnable to allocate packet");
|
|
return(STATUS_INSUFFICIENT_RESOURCES);
|
|
}
|
|
}
|
|
else if (!NT_SUCCESS (status))
|
|
{
|
|
NtClose(StreamHandle);
|
|
return(status);
|
|
}
|
|
|
|
} while (status == STATUS_BUFFER_OVERFLOW);
|
|
NtClose (StreamHandle);
|
|
|
|
for (i=0; i<pInterfaceInfo->NumAdapters; i++)
|
|
{
|
|
RtlInitString(&name_string, NULL);
|
|
RtlInitUnicodeString(&uc_name_string, pInterfaceInfo->Adapter[i].Name);
|
|
if (NT_SUCCESS(RtlUnicodeStringToAnsiString(&name_string, &uc_name_string, TRUE)))
|
|
{
|
|
size = (name_string.Length > MAX_NAME) ? MAX_NAME : name_string.Length;
|
|
|
|
strncpy(pDeviceName[index], name_string.Buffer, size);
|
|
pDeviceName[index][size] = '\0';
|
|
RtlFreeAnsiString (&name_string);
|
|
|
|
index++;
|
|
}
|
|
}
|
|
|
|
LocalFree(pInterfaceInfo);
|
|
|
|
//
|
|
// NULL out the next device string ptr
|
|
//
|
|
if (index < NBT_MAXIMUM_BINDINGS)
|
|
{
|
|
pDeviceName[index][0] = '\0';
|
|
}
|
|
|
|
//
|
|
// Read the ScopeId key!
|
|
//
|
|
size = BUFF_SIZE;
|
|
*pScope = '\0'; // By default
|
|
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
SubKeyParms,
|
|
0,
|
|
KEY_READ,
|
|
&Key);
|
|
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
// now read the Scope key
|
|
status = RegQueryValueEx(Key, Scope, NULL, &Type, pScopeBuffer, &size);
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
strcpy(pScope,pScopeBuffer);
|
|
}
|
|
status = RegCloseKey(Key);
|
|
}
|
|
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
//-------------------------------------------------------------------------//
|
|
//###### R e a d R e g i s t r y () #####################################//
|
|
//-------------------------------------------------------------------------//
|
|
// Abstract: //
|
|
// Reads the names of the NetBT devices and the NetBT scope name form //
|
|
// the registry. The names are stored in the Linkage/Export section //
|
|
// under the NetBT key. //
|
|
// Arguments: //
|
|
// pScope - buffer where to store the scope string //
|
|
// Return value: //
|
|
// 0 if successful //
|
|
// -1 otherwise //
|
|
// Global variables used: //
|
|
// none //
|
|
//-------------------------------------------------------------------------//
|
|
LONG ReadNbtNameRegistry( IN OUT TCHAR pDeviceName[][MAX_NAME+1],
|
|
IN OUT PUCHAR pScope )
|
|
{
|
|
|
|
LPCTSTR c_szSubKeyParams = _T("system\\currentcontrolset\\services\\netbt\\parameters");
|
|
LPCTSTR c_szSubKeyLinkage = _T("system\\currentcontrolset\\services\\netbt\\linkage");
|
|
HKEY Key;
|
|
LPCTSTR c_szScope = _T("ScopeId");
|
|
LPCTSTR c_szExport = _T("Export");
|
|
DWORD dwType;
|
|
LONG status;
|
|
LONG status2;
|
|
DWORD size;
|
|
LPBYTE pBuffer;
|
|
|
|
size = BUFF_SIZE;
|
|
status = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
c_szSubKeyLinkage,
|
|
0,
|
|
KEY_READ,
|
|
&Key
|
|
);
|
|
if ( ERROR_SUCCESS != status)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
// now read the Export values
|
|
|
|
status = RegQueryValueEx( Key,
|
|
c_szExport,
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&size
|
|
);
|
|
|
|
|
|
pBuffer = Malloc(size);
|
|
if( NULL == pBuffer)
|
|
{
|
|
DebugMessage("Out of Memory!\n");
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
ZeroMemory( pBuffer, size );
|
|
|
|
status = RegQueryValueEx( Key,
|
|
c_szExport,
|
|
NULL,
|
|
&dwType,
|
|
pBuffer,
|
|
&size
|
|
);
|
|
|
|
if ( ERROR_SUCCESS != status)
|
|
{
|
|
RegCloseKey(Key);
|
|
return status;
|
|
}
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
|
|
LPBYTE curPtr = pBuffer;
|
|
LONG index = 0;
|
|
|
|
//
|
|
// Copy over all the export keys
|
|
//
|
|
|
|
while( (*curPtr) && (index < NBT_MAXIMUM_BINDINGS) )
|
|
{
|
|
_tcscpy( pDeviceName[index], curPtr );
|
|
++index;
|
|
curPtr += strlen(curPtr) + 1;
|
|
}
|
|
|
|
//
|
|
// NULL out the next device string ptr
|
|
//
|
|
if ( index < NBT_MAXIMUM_BINDINGS ) {
|
|
pDeviceName[index][0] = 0;
|
|
}
|
|
}
|
|
|
|
Free(pBuffer);
|
|
|
|
status = RegCloseKey( Key );
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
DebugMessage("Error closing the Registry key\n");
|
|
|
|
|
|
status2 = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
|
c_szSubKeyParams,
|
|
0,
|
|
KEY_READ,
|
|
&Key
|
|
);
|
|
|
|
if ( status2 == ERROR_SUCCESS )
|
|
{
|
|
// now read the linkage values
|
|
status2 = RegQueryValueEx( Key,
|
|
c_szScope,
|
|
NULL,
|
|
&dwType,
|
|
pScope,
|
|
&size
|
|
);
|
|
if( ERROR_SUCCESS != status2)
|
|
{
|
|
// No ScopeId!
|
|
*pScope = 0;
|
|
}
|
|
|
|
status2 = RegCloseKey(Key);
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
*/
|
|
|
|
|
|
|
|
|
|
void NbtNmGlobalPrint(IN NETDIAG_PARAMS *pParams,
|
|
IN OUT NETDIAG_RESULT *pResults)
|
|
{
|
|
if (pParams->fVerbose || pResults->NbtNm.hrTestResult != S_OK)
|
|
{
|
|
PrintNewLine(pParams, 2);
|
|
PrintTestTitleResult(pParams,
|
|
IDS_NBTNM_LONG,
|
|
IDS_NBTNM_SHORT,
|
|
pResults->Global.fHasNbtEnabledInterface ? TRUE : FALSE,
|
|
pResults->NbtNm.hrTestResult, 0);
|
|
}
|
|
|
|
PrintMessageList(pParams, &pResults->NbtNm.lmsgGlobalOutput);
|
|
}
|
|
|
|
void NbtNmPerInterfacePrint(IN NETDIAG_PARAMS *pParams,
|
|
IN OUT NETDIAG_RESULT *pResults,
|
|
IN INTERFACE_RESULT *pIfResults)
|
|
{
|
|
if (!pIfResults->NbtNm.fActive ||
|
|
NETCARD_DISCONNECTED == pIfResults->dwNetCardStatus)
|
|
return;
|
|
|
|
|
|
if(pParams->fVerbose || pIfResults->NbtNm.fQuietOutput)
|
|
{
|
|
PrintTestTitleResult(pParams,
|
|
IDS_NBTNM_LONG,
|
|
IDS_NBTNM_SHORT,
|
|
pIfResults->fNbtEnabled ? TRUE : FALSE,
|
|
pResults->NbtNm.hrTestResult, 8);
|
|
}
|
|
|
|
PrintMessageList(pParams, &pIfResults->NbtNm.lmsgOutput);
|
|
}
|
|
|
|
void NbtNmCleanup(IN NETDIAG_PARAMS *pParams,
|
|
IN OUT NETDIAG_RESULT *pResults)
|
|
{
|
|
int i;
|
|
MessageListCleanUp(&pResults->NbtNm.lmsgGlobalOutput);
|
|
for(i = 0; i < pResults->cNumInterfaces; i++)
|
|
{
|
|
if(pResults->pArrayInterface[i].NbtNm.fActive)
|
|
MessageListCleanUp(&pResults->pArrayInterface[i].NbtNm.lmsgOutput);
|
|
}
|
|
}
|
|
|