//++ // // 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 #pragma pack(pop) #include //#include 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; iIfIndexcNumInterfaces; 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; iIfIndexcNumInterfaces; 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); }