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

405 lines
11 KiB
C

//++
//
// Copyright (C) Microsoft Corporation, 1987 - 1999
//
// Module Name:
//
// nbttrprt.c
//
// Abstract:
//
// Queries into network drivers
//
// Author:
//
// Anilth - 4-20-1998
//
// Environment:
//
// User mode only.
// Contains NT-specific code.
//
// Revision History:
//
//--
#include "precomp.h"
#include "nbtutil.h"
BOOLEAN NlTransportGetIpAddress(IN LPWSTR TransportName,
OUT PULONG IpAddress,
IN OUT NETDIAG_RESULT *pResults);
/*!--------------------------------------------------------------------------
NetBTTest
Do whatever initialization Cliff's routines need that Karoly's will really
do as a part of his tests.
Arguments:
None.
Return Value:
S_OK: Test suceeded.
S_FALSE: Test failed
Author: KennT
---------------------------------------------------------------------------*/
HRESULT
NetBTTest(NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults)
{
HRESULT hr = hrOK;
NET_API_STATUS NetStatus;
PWKSTA_TRANSPORT_INFO_0 pWti0 = NULL;
DWORD EntriesRead;
DWORD TotalEntries;
DWORD i;
PNETBT_TRANSPORT pNetbtTransport;
LONG cNetbtTransportCount = 0;
//
// Generate a global list of NetbtTransports.
// ?? Karoly, Please populate GlobalNetbtTransports and cNetbtTransportCount
// using some mechanism lower level mechanism.
//
if (!pResults->Global.fHasNbtEnabledInterface)
{
pResults->NetBt.fPerformed = FALSE;
//IDS_NETBT_SKIP
SetMessage(&pResults->NetBt.msgTestResult,
Nd_Verbose,
IDS_NETBT_SKIP);
return S_OK;
}
PrintStatusMessage(pParams,0, IDS_NETBT_STATUS_MSG);
pResults->NetBt.fPerformed = TRUE;
NetStatus = NetWkstaTransportEnum(
NULL,
0,
(LPBYTE *)&pWti0,
0xFFFFFFFF, // MaxPreferredLength
&EntriesRead,
&TotalEntries,
NULL ); // Optional resume handle
if (NetStatus != NERR_Success)
{
// IDS_NETBT_11403 " NetBt : [FATAL] Unable to retrieve transport list from Redir. [%s]\n"
SetMessage(&pResults->NetBt.msgTestResult,
Nd_Quiet,
IDS_NETBT_11403, NetStatusToString(NetStatus));
// the test failed, but we can continue with the other tests
hr = S_FALSE;
}
else
{
cNetbtTransportCount = 0;
for ( i=0; i<EntriesRead; i++ )
{
UNICODE_STRING TransportName;
RtlInitUnicodeString( &TransportName, (LPWSTR)pWti0[i].wkti0_transport_name );
if ( TransportName.Length >= sizeof(NETBT_DEVICE_PREFIX) &&
_wcsnicmp( TransportName.Buffer, NETBT_DEVICE_PREFIX, (sizeof(NETBT_DEVICE_PREFIX)/sizeof(WCHAR)-1)) == 0 ) {
//
// Determine if this is a duplicate transport
//
pNetbtTransport = FindNetbtTransport( pResults, TransportName.Buffer );
if ( pNetbtTransport != NULL )
{
// IDS_NETBT_DUPLICATE " NetBt : [WARNING] Transport %-16.16wZ is a duplicate"
PrintStatusMessage(pParams,0, IDS_NETBT_DUPLICATE,
&TransportName);
}
else
{
//
// Allocate a new netbt transport
//
pNetbtTransport = (PNETBT_TRANSPORT) Malloc(
sizeof(NETBT_TRANSPORT) +
TransportName.Length + sizeof(WCHAR));
if ( pNetbtTransport == NULL )
{
// IDS_NETBT_11404 " NetBt : [FATAL] Out of memory."
SetMessage(&pResults->NetBt.msgTestResult,
Nd_Quiet,
IDS_NETBT_11404);
// the test failed, but we can continue with the other tests
hr = S_FALSE;
goto Cleanup;
}
ZeroMemory( pNetbtTransport,
sizeof(NETBT_TRANSPORT) +
TransportName.Length + sizeof(WCHAR));
wcscpy( pNetbtTransport->pswzTransportName, TransportName.Buffer );
pNetbtTransport->Flags = 0;
if ( !NlTransportGetIpAddress( pNetbtTransport->pswzTransportName,
&pNetbtTransport->IpAddress,
pResults) )
{
// the test failed, but we can continue with the other tests
hr = S_FALSE;
goto Cleanup;
}
InsertTailList( &pResults->NetBt.Transports,
&pNetbtTransport->Next );
cNetbtTransportCount ++;
}
}
}
if ( cNetbtTransportCount == 0 )
{
// IDS_NETBT_11405 " NetBt : [FATAL] No NetBt transports are configured"
SetMessage(&pResults->NetBt.msgTestResult,
Nd_Quiet,
IDS_NETBT_11405);
// the test failed, but we can continue with the other tests
hr = S_FALSE;
}
else
{
int ids;
TCHAR szBuffer[256];
if (cNetbtTransportCount > 1)
{
ids = IDS_NETBT_11406;
// IDS_NETBT_11406 " %ld NetBt transport%s currently configured.\n"
}
else
{
ids = IDS_NETBT_11407;
// IDS_NETBT_11407 " 1 NetBt transport currently configured.\n"
}
SetMessage(&pResults->NetBt.msgTestResult,
Nd_Verbose,
ids,
cNetbtTransportCount);
}
}
pResults->NetBt.cTransportCount = cNetbtTransportCount;
Cleanup:
if ( pWti0 )
{
NetApiBufferFree( pWti0 );
}
pResults->NetBt.hr = hr;
return hr;
}
BOOLEAN
NlTransportGetIpAddress(
IN LPWSTR pswzTransportName,
OUT PULONG IpAddress,
IN OUT NETDIAG_RESULT *pResults
)
/*++
Routine Description:
Get the IP Address associated with the specified transport.
Arguments:
pswzTransportName - Name of the transport to query.
IpAddress - IP address of the transport.
Zero if the transport currently has no address or
if the transport is not IP.
Return Value:
TRUE: transport is an IP transport
--*/
{
NTSTATUS Status;
BOOLEAN RetVal = FALSE;
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING TransportNameString;
HANDLE TransportHandle = NULL;
ULONG IpAddresses[NBT_MAXIMUM_BINDINGS+1];
ULONG BytesReturned;
//
// Open the transport device directly.
//
*IpAddress = 0;
RtlInitUnicodeString( &TransportNameString, pswzTransportName );
InitializeObjectAttributes(
&ObjectAttributes,
&TransportNameString,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
Status = NtOpenFile(
&TransportHandle,
SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
0,
0 );
if (NT_SUCCESS(Status)) {
Status = IoStatusBlock.Status;
}
if (! NT_SUCCESS(Status))
{
// IDS_NETBT_11408 " [FATAL] Cannot open netbt driver '%ws'\n"
SetMessage(&pResults->NetBt.msgTestResult,
Nd_Quiet,
IDS_NETBT_11408,
pswzTransportName);
goto Cleanup;
}
//
// Query the IP Address
//
if (!DeviceIoControl( TransportHandle,
IOCTL_NETBT_GET_IP_ADDRS,
NULL,
0,
IpAddresses,
sizeof(IpAddresses),
&BytesReturned,
NULL))
{
TCHAR szBuffer[256];
Status = NetpApiStatusToNtStatus(GetLastError());
// IDS_NETBT_11409 " [FATAL] Cannot get IP address from netbt driver '%ws':"
SetMessage(&pResults->NetBt.msgTestResult,
Nd_Quiet,
IDS_NETBT_11409,
pswzTransportName);
goto Cleanup;
}
//
// Return IP Address
// (Netbt returns the address in host order.)
//
*IpAddress = htonl(*IpAddresses);
RetVal = TRUE;
Cleanup:
if ( TransportHandle != NULL )
{
(VOID) NtClose( TransportHandle );
}
return RetVal;
}
void NetBTGlobalPrint(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults)
{
PLIST_ENTRY ListEntry;
PNETBT_TRANSPORT pNetbtTransport;
if (pParams->fVerbose || !FHrOK(pResults->NetBt.hr))
{
PrintNewLine(pParams, 2);
PrintTestTitleResult(pParams,
IDS_NETBT_LONG,
IDS_NETBT_SHORT,
pResults->NetBt.fPerformed,
pResults->NetBt.hr,
0);
}
if ( pParams->fVerbose && pResults->NetBt.fPerformed)
{
// IDS_NETBT_11411 " List of NetBt transports currently configured.\n"
PrintMessage(pParams, IDS_NETBT_11411);
}
// Iterate through the transports
//
for ( ListEntry = pResults->NetBt.Transports.Flink ;
ListEntry != &pResults->NetBt.Transports ;
ListEntry = ListEntry->Flink )
{
//
// If the transport names match,
// return the entry
//
pNetbtTransport = CONTAINING_RECORD( ListEntry, NETBT_TRANSPORT, Next );
if (pParams->fVerbose)
{
// Strip off the "\Device\" off of the beginning of
// the string
// IDS_NETBT_11412 " %ws\n"
PrintMessage(pParams, IDS_NETBT_11412,
MapGuidToServiceNameW(pNetbtTransport->pswzTransportName+8));
}
}
PrintNdMessage(pParams, &pResults->NetBt.msgTestResult);
}
void NetBTPerInterfacePrint(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults, INTERFACE_RESULT *pInterfaceResults)
{
}
void NetBTCleanup(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults)
{
PNETBT_TRANSPORT pNetbtTransport;
PLIST_ENTRY pListEntry;
PLIST_ENTRY pListHead = &pResults->NetBt.Transports;
// Need to remove all entries from the list
while (!IsListEmpty(pListHead))
{
pListEntry = RemoveHeadList(pListHead);
pNetbtTransport = CONTAINING_RECORD( pListEntry, NETBT_TRANSPORT, Next );
Free( pNetbtTransport );
}
ClearMessage(&pResults->NetBt.msgTestResult);
}