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