windows-nt/Source/XPSP1/NT/net/diagnostics/netdiag/nbtnm.c
2020-09-26 16:20:57 +08:00

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);
}
}