Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

412 lines
16 KiB

//++
//
// Copyright (C) Microsoft Corporation, 1987 - 1999
//
// Module Name:
//
// ndisquer.c
//
// Abstract:
//
// Queries into network drivers
//
// Author:
//
// Anilth - 4-20-1998
//
// Environment:
//
// User mode only.
// Contains NT-specific code.
//
// Revision History:
//
//--
#include "precomp.h"
#pragma pack(push)
#pragma pack()
#include <ndispnp.h>
#pragma pack(pop)
#include <malloc.h>
//#include <cfgmgr32.h>
const TCHAR c_szDevicePath[] = _T("\\DEVICE\\");
const LPCTSTR c_ppszNetCardStatus[] = {
"CONNECTED",
"DISCONNECTED",
"UNKNOWN"
};
LPTSTR UTOTWithAlloc(IN PUNICODE_STRING U);
DWORD
CheckThisDriver(
NETDIAG_RESULT *pResults,
PNDIS_INTERFACE pInterface,
DWORD *pdwNetCardStatus);
WCHAR BLBuf[4096];
PNDIS_ENUM_INTF Interfaces = (PNDIS_ENUM_INTF)BLBuf;
//
// This routine first gets the list of all Network drivers and then query
// them for the statistics
//
// Arguments:
// None.
//
// Return Value:
// TRUE: Test suceeded.
// FALSE: Test failed
//
HRESULT NdisTest(NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults)
{
HRESULT hr = S_OK;
BOOL bAtleastOneDriverOK = FALSE;
int iIfIndex;
PrintStatusMessage( pParams, 4, IDS_NDIS_STATUS_MSG );
InitializeListHead(&pResults->Ndis.lmsgOutput);
//IDS_NDIS_16000 "\n Information of Netcard drivers:\n\n"
AddMessageToListId( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16000);
if (NdisEnumerateInterfaces(Interfaces, sizeof(BLBuf)))
{
UINT i;
for (i = 0; i < Interfaces->TotalInterfaces; i++)
{
//we also put the netcard status to the per interface results if the interface
//is bound to tcpip or ipx
INTERFACE_RESULT* pIfResults = NULL;
LPTSTR pszDeviceDescription = UTOTWithAlloc(&Interfaces->Interface[i].DeviceDescription);
LPTSTR pszDeviceName = UTOTWithAlloc(&Interfaces->Interface[i].DeviceName);
DWORD dwCardStatus = NETCARD_CONNECTED;
if (pszDeviceDescription == NULL || pszDeviceName == NULL)
{
// memory allocation failed
continue;
}
//$REVIEW should we ignore WAN minports?
if(NULL != _tcsstr(pszDeviceDescription, "WAN Miniport")){
// ignore WAN miniports
continue;
}
if(NULL != _tcsstr(pszDeviceDescription, "ATM Emulated LAN")){
// ignore ATM Emulated LAN
continue;
}
if(NULL != _tcsstr(pszDeviceDescription, "Direct Parallel"))
{
// ignore "Direct Parallel" interface because it doesn't support NdisQueryStatistics()
continue;
}
//IDS_NDIS_16001 " ---------------------------------------------------------------------------\n"
AddMessageToListId( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16001);
//IDS_NDIS_16002 " Description: %s\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose,
IDS_NDIS_16002, pszDeviceDescription);
//IDS_NDIS_16003 " Device: %s\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose,
IDS_NDIS_16003, pszDeviceName);
//try to find a match in the current interface list
if( 0 == StrniCmp(c_szDevicePath, pszDeviceName, _tcslen(c_szDevicePath)))
{
LPTSTR pszAdapterName = pszDeviceName + _tcslen(c_szDevicePath);
for ( iIfIndex=0; iIfIndex<pResults->cNumInterfaces; iIfIndex++)
{
if (_tcscmp(pResults->pArrayInterface[iIfIndex].pszName,
pszAdapterName) == 0)
{
pIfResults = pResults->pArrayInterface + iIfIndex;
break;
}
}
}
Free(pszDeviceDescription);
Free(pszDeviceName);
CheckThisDriver(pResults, &Interfaces->Interface[i], &dwCardStatus);
if(NETCARD_CONNECTED == dwCardStatus)
bAtleastOneDriverOK = TRUE;
//if the interface is in the tcpip or ipx binding path, save the status
//in the per interface result
if (pIfResults)
pIfResults->dwNetCardStatus = dwCardStatus;
}
}
else
{
//IDS_NDIS_16004 " Enumerate failed 0x%lX\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_Quiet, IDS_NDIS_16004, Win32ErrorToString(GetLastError()));
hr = S_FALSE;
}
//IDS_NDIS_16005 " ---------------------------------------------------------------------------\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16005);
if(!bAtleastOneDriverOK)
{
BOOL fAllCardDown = TRUE;
for ( iIfIndex=0; iIfIndex<pResults->cNumInterfaces; iIfIndex++)
{
if (NETCARD_DISCONNECTED != pResults->pArrayInterface[iIfIndex].dwNetCardStatus)
{
fAllCardDown = FALSE;
break;
}
}
//IDS_NDIS_16006 " [FATAL] - None of the Netcard drivers gave satisfactory results!\n"
AddMessageToListId( &pResults->Ndis.lmsgOutput, Nd_Quiet, IDS_NDIS_16006);
if (fAllCardDown)
{
//IDS_NDIS_ALL_CARD_DOWN "\nSince there is no network connection for this machine, we do not need to perform any more network diagnostics.\n"
AddMessageToListId( &pResults->Ndis.lmsgOutput, Nd_Quiet, IDS_NDIS_ALL_CARD_DOWN);
hr = E_FAIL;
}
else
hr = S_FALSE;
}
else
{
//IDS_NDIS_16007 " [SUCCESS] - At least one Netcard driver gave satisfactory results!\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16007);
}
if ( FHrOK(hr) )
{
PrintStatusMessage(pParams, 0, IDS_GLOBAL_PASS_NL);
}
else
{
PrintStatusMessage(pParams, 0, IDS_GLOBAL_FAIL_NL);
}
pResults->Ndis.hrTestResult = hr;
return hr;
}
//Convert a UNICODE_STRING to a TString with memory allocation.
//It's the caller's responsibility to free the memory with Free()
LPTSTR UTOTWithAlloc(IN PUNICODE_STRING U)
{
LPTSTR pszBuf = (LPTSTR)Malloc(U->Length + sizeof(TCHAR));
if (pszBuf != NULL)
StrnCpyTFromW(pszBuf, U->Buffer, U->Length/(sizeof(*(U->Buffer))) + 1);
return pszBuf;
}
//Map a NetCardStatus code to the description string
LPCTSTR MapNetCardStatusToString(DWORD dwNicStatus)
{
return c_ppszNetCardStatus[dwNicStatus];
}
#define SECS_PER_DAY (24*60*60)
#define SECS_PER_HOUR (60*60)
#define SECS_PER_MIN 60
//Check and print the NIC driver status. pdwNetCardStatus will contain the net card status when
//the function returns. If the query failed, *pdwNetCardStatus will be set
// as NETCARD_STATUS_UNKNOWN.
// Return: the Windows Error code.
DWORD
CheckThisDriver(NETDIAG_RESULT *pResults, PNDIS_INTERFACE pInterface, DWORD *pdwNetCardStatus)
{
NIC_STATISTICS Stats;
DWORD dwReturnVal = ERROR_SUCCESS;
DWORD dwNicStatus = NETCARD_CONNECTED;
assert(pdwNetCardStatus);
memset(&Stats, 0, sizeof(NIC_STATISTICS));
Stats.Size = sizeof(NIC_STATISTICS);
if(NdisQueryStatistics(&pInterface->DeviceName, &Stats))
{
//IDS_NDIS_16008 "\n Media State: %s\n"
AddMessageToListId(&pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16008);
switch(Stats.MediaState)
{
case MEDIA_STATE_CONNECTED:
AddMessageToListId(&pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_CONNECTED);
break;
case MEDIA_STATE_DISCONNECTED:
dwNicStatus = NETCARD_DISCONNECTED;
AddMessageToListId(&pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_DISCONNECTED);
break;
default:
dwNicStatus = NETCARD_STATUS_UNKNOWN;
AddMessageToListId(&pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_UNKNOWN);
break;
}
//IDS_NDIS_16009 "\n Device State: "
AddMessageToListId( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16009);
switch(Stats.DeviceState)
{
case DEVICE_STATE_CONNECTED:
AddMessageToListId(&pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_CONNECTED);
break;
case DEVICE_STATE_DISCONNECTED:
AddMessageToListId(&pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_DISCONNECTED);
break;
default:
AddMessageToListId(&pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_UNKNOWN);
break;
}
//IDS_NDIS_16010 " Connect Time: "
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16010);
if (Stats.ConnectTime > SECS_PER_DAY)
{
//IDS_NDIS_16011 "%d days, "
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16011, Stats.ConnectTime / SECS_PER_DAY);
Stats.ConnectTime %= SECS_PER_DAY;
}
//IDS_NDIS_16012 "%02d:"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16012, Stats.ConnectTime / SECS_PER_HOUR);
Stats.ConnectTime %= SECS_PER_HOUR;
//IDS_NDIS_16013 "%02d:"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16013, Stats.ConnectTime / SECS_PER_MIN);
Stats.ConnectTime %= SECS_PER_MIN;
//IDS_NDIS_16014 "%02d\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16014, Stats.ConnectTime);
Stats.LinkSpeed *= 100;
if (Stats.LinkSpeed >= 1000000000)
//IDS_NDIS_16015 " Media Speed: %d Gbps\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16015,
Stats.LinkSpeed / 1000000);
else if (Stats.LinkSpeed >= 1000000)
//IDS_NDIS_16016 " Media Speed: %d Mbps\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16016,
Stats.LinkSpeed / 1000000);
else if (Stats.LinkSpeed >= 1000)
//IDS_NDIS_16017 " Media Speed: %d Kbps\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16017,
Stats.LinkSpeed / 1000);
else
//IDS_NDIS_16018 " Media Speed: %d bps\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16018,
Stats.LinkSpeed);
//IDS_NDIS_16019 "\n Packets Sent: %d\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16019, Stats.PacketsSent);
//IDS_NDIS_16020 " Bytes Sent (Optional): %d\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16020, Stats.BytesSent);
//IDS_NDIS_16021 "\n Packets Received: %d\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16021,
Stats.PacketsReceived);
//IDS_NDIS_16022 " Directed Pkts Recd (Optional): %d\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16022,
Stats.DirectedPacketsReceived);
//IDS_NDIS_16023 " Bytes Received (Optional): %d\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16023,
Stats.BytesReceived);
//IDS_NDIS_16024 " Directed Bytes Recd (Optional): %d\n\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16024,
Stats.DirectedBytesReceived);
if (Stats.PacketsSendErrors != 0)
//IDS_NDIS_16025 " Packets SendError: %d\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16025,
Stats.PacketsSendErrors);
if (Stats.PacketsReceiveErrors != 0)
//IDS_NDIS_16026 " Packets RecvError: %d\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16026,
Stats.PacketsReceiveErrors);
// if we received packets, consider this driver to be fine
if(NETCARD_CONNECTED != dwNicStatus)
{
//IDS_NDIS_16029 " [WARNING] The net card '%wZ' may not work!\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_Quiet, IDS_NDIS_16029,
&pInterface->DeviceDescription);
}
else if (!Stats.PacketsReceived)
{
//IDS_NDIS_NO_RCV " [WARNING] The net card '%wZ' may not be working because it receives no packets!\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_Quiet, IDS_NDIS_NO_RCV,
&pInterface->DeviceDescription);
}
} else {
dwReturnVal = GetLastError();
//IDS_NDIS_16027 " GetStats failed for '%wZ'. [%s]\n"
AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_Quiet, IDS_NDIS_16027,
&pInterface->DeviceDescription, Win32ErrorToString(dwReturnVal));
dwNicStatus = NETCARD_STATUS_UNKNOWN;
}
*pdwNetCardStatus = dwNicStatus;
return dwReturnVal;
}
void NdisGlobalPrint(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults)
{
if (pParams->fVerbose || !FHrOK(pResults->Ndis.hrTestResult))
{
PrintNewLine(pParams, 2);
PrintTestTitleResult(pParams,
IDS_NDIS_LONG,
IDS_NDIS_SHORT,
TRUE,
pResults->Ndis.hrTestResult,
0);
}
PrintMessageList(pParams, &pResults->Ndis.lmsgOutput);
}
void NdisPerInterfacePrint(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults, INTERFACE_RESULT *pInterfaceResults)
{
if (pParams->fVerbose || NETCARD_CONNECTED != pInterfaceResults->dwNetCardStatus)
{
PrintNewLine(pParams, 1);
if (NETCARD_CONNECTED != pInterfaceResults->dwNetCardStatus)
{
PrintTestTitleResult(pParams, IDS_NDIS_LONG, IDS_NDIS_SHORT, TRUE, S_FALSE, 8);
//IDS_NDIS_16030 " NetCard Status %s\n"
PrintMessage(pParams, IDS_NDIS_16030, MapNetCardStatusToString(pInterfaceResults->dwNetCardStatus));
if (NETCARD_DISCONNECTED == pInterfaceResults->dwNetCardStatus)
PrintMessage(pParams, IDS_NDIS_CARD_DOWN);
}
else
PrintTestTitleResult(pParams, IDS_NDIS_LONG, IDS_NDIS_SHORT, TRUE, S_OK, 8);
}
}
void NdisCleanup(IN NETDIAG_PARAMS *pParams,
IN OUT NETDIAG_RESULT *pResults)
{
MessageListCleanUp(&pResults->Ndis.lmsgOutput);
}