Leaked source code of windows server 2003
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

  1. //++
  2. //
  3. // Copyright (C) Microsoft Corporation, 1987 - 1999
  4. //
  5. // Module Name:
  6. //
  7. // ndisquer.c
  8. //
  9. // Abstract:
  10. //
  11. // Queries into network drivers
  12. //
  13. // Author:
  14. //
  15. // Anilth - 4-20-1998
  16. //
  17. // Environment:
  18. //
  19. // User mode only.
  20. // Contains NT-specific code.
  21. //
  22. // Revision History:
  23. //
  24. //--
  25. #include "precomp.h"
  26. #pragma pack(push)
  27. #pragma pack()
  28. #include <ndispnp.h>
  29. #pragma pack(pop)
  30. #include <malloc.h>
  31. //#include <cfgmgr32.h>
  32. const TCHAR c_szDevicePath[] = _T("\\DEVICE\\");
  33. const LPCTSTR c_ppszNetCardStatus[] = {
  34. "CONNECTED",
  35. "DISCONNECTED",
  36. "UNKNOWN"
  37. };
  38. LPTSTR UTOTWithAlloc(IN PUNICODE_STRING U);
  39. DWORD
  40. CheckThisDriver(
  41. NETDIAG_RESULT *pResults,
  42. PNDIS_INTERFACE pInterface,
  43. DWORD *pdwNetCardStatus);
  44. WCHAR BLBuf[4096];
  45. PNDIS_ENUM_INTF Interfaces = (PNDIS_ENUM_INTF)BLBuf;
  46. //
  47. // This routine first gets the list of all Network drivers and then query
  48. // them for the statistics
  49. //
  50. // Arguments:
  51. // None.
  52. //
  53. // Return Value:
  54. // TRUE: Test suceeded.
  55. // FALSE: Test failed
  56. //
  57. HRESULT NdisTest(NETDIAG_PARAMS* pParams, NETDIAG_RESULT* pResults)
  58. {
  59. HRESULT hr = S_OK;
  60. BOOL bAtleastOneDriverOK = FALSE;
  61. int iIfIndex;
  62. PrintStatusMessage( pParams, 4, IDS_NDIS_STATUS_MSG );
  63. InitializeListHead(&pResults->Ndis.lmsgOutput);
  64. //IDS_NDIS_16000 "\n Information of Netcard drivers:\n\n"
  65. AddMessageToListId( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16000);
  66. if (NdisEnumerateInterfaces(Interfaces, sizeof(BLBuf)))
  67. {
  68. UINT i;
  69. for (i = 0; i < Interfaces->TotalInterfaces; i++)
  70. {
  71. //we also put the netcard status to the per interface results if the interface
  72. //is bound to tcpip or ipx
  73. INTERFACE_RESULT* pIfResults = NULL;
  74. LPTSTR pszDeviceDescription = UTOTWithAlloc(&Interfaces->Interface[i].DeviceDescription);
  75. LPTSTR pszDeviceName = UTOTWithAlloc(&Interfaces->Interface[i].DeviceName);
  76. DWORD dwCardStatus = NETCARD_CONNECTED;
  77. if (pszDeviceDescription == NULL || pszDeviceName == NULL)
  78. {
  79. // memory allocation failed
  80. continue;
  81. }
  82. //$REVIEW should we ignore WAN minports?
  83. if(NULL != _tcsstr(pszDeviceDescription, "WAN Miniport")){
  84. // ignore WAN miniports
  85. continue;
  86. }
  87. if(NULL != _tcsstr(pszDeviceDescription, "ATM Emulated LAN")){
  88. // ignore ATM Emulated LAN
  89. continue;
  90. }
  91. if(NULL != _tcsstr(pszDeviceDescription, "Direct Parallel"))
  92. {
  93. // ignore "Direct Parallel" interface because it doesn't support NdisQueryStatistics()
  94. continue;
  95. }
  96. //IDS_NDIS_16001 " ---------------------------------------------------------------------------\n"
  97. AddMessageToListId( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16001);
  98. //IDS_NDIS_16002 " Description: %s\n"
  99. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose,
  100. IDS_NDIS_16002, pszDeviceDescription);
  101. //IDS_NDIS_16003 " Device: %s\n"
  102. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose,
  103. IDS_NDIS_16003, pszDeviceName);
  104. //try to find a match in the current interface list
  105. if( 0 == StrniCmp(c_szDevicePath, pszDeviceName, _tcslen(c_szDevicePath)))
  106. {
  107. LPTSTR pszAdapterName = pszDeviceName + _tcslen(c_szDevicePath);
  108. for ( iIfIndex=0; iIfIndex<pResults->cNumInterfaces; iIfIndex++)
  109. {
  110. if (_tcscmp(pResults->pArrayInterface[iIfIndex].pszName,
  111. pszAdapterName) == 0)
  112. {
  113. pIfResults = pResults->pArrayInterface + iIfIndex;
  114. break;
  115. }
  116. }
  117. }
  118. Free(pszDeviceDescription);
  119. Free(pszDeviceName);
  120. CheckThisDriver(pResults, &Interfaces->Interface[i], &dwCardStatus);
  121. if(NETCARD_CONNECTED == dwCardStatus)
  122. bAtleastOneDriverOK = TRUE;
  123. //if the interface is in the tcpip or ipx binding path, save the status
  124. //in the per interface result
  125. if (pIfResults)
  126. pIfResults->dwNetCardStatus = dwCardStatus;
  127. }
  128. }
  129. else
  130. {
  131. //IDS_NDIS_16004 " Enumerate failed 0x%lX\n"
  132. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_Quiet, IDS_NDIS_16004, Win32ErrorToString(GetLastError()));
  133. hr = S_FALSE;
  134. }
  135. //IDS_NDIS_16005 " ---------------------------------------------------------------------------\n"
  136. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16005);
  137. if(!bAtleastOneDriverOK)
  138. {
  139. BOOL fAllCardDown = TRUE;
  140. for ( iIfIndex=0; iIfIndex<pResults->cNumInterfaces; iIfIndex++)
  141. {
  142. if (NETCARD_DISCONNECTED != pResults->pArrayInterface[iIfIndex].dwNetCardStatus)
  143. {
  144. fAllCardDown = FALSE;
  145. break;
  146. }
  147. }
  148. //IDS_NDIS_16006 " [FATAL] - None of the Netcard drivers gave satisfactory results!\n"
  149. AddMessageToListId( &pResults->Ndis.lmsgOutput, Nd_Quiet, IDS_NDIS_16006);
  150. if (fAllCardDown)
  151. {
  152. //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"
  153. AddMessageToListId( &pResults->Ndis.lmsgOutput, Nd_Quiet, IDS_NDIS_ALL_CARD_DOWN);
  154. hr = E_FAIL;
  155. }
  156. else
  157. hr = S_FALSE;
  158. }
  159. else
  160. {
  161. //IDS_NDIS_16007 " [SUCCESS] - At least one Netcard driver gave satisfactory results!\n"
  162. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16007);
  163. }
  164. if ( FHrOK(hr) )
  165. {
  166. PrintStatusMessage(pParams, 0, IDS_GLOBAL_PASS_NL);
  167. }
  168. else
  169. {
  170. PrintStatusMessage(pParams, 0, IDS_GLOBAL_FAIL_NL);
  171. }
  172. pResults->Ndis.hrTestResult = hr;
  173. return hr;
  174. }
  175. //Convert a UNICODE_STRING to a TString with memory allocation.
  176. //It's the caller's responsibility to free the memory with Free()
  177. LPTSTR UTOTWithAlloc(IN PUNICODE_STRING U)
  178. {
  179. LPTSTR pszBuf = (LPTSTR)Malloc(U->Length + sizeof(TCHAR));
  180. if (pszBuf != NULL)
  181. StrnCpyTFromW(pszBuf, U->Buffer, U->Length/(sizeof(*(U->Buffer))) + 1);
  182. return pszBuf;
  183. }
  184. //Map a NetCardStatus code to the description string
  185. LPCTSTR MapNetCardStatusToString(DWORD dwNicStatus)
  186. {
  187. return c_ppszNetCardStatus[dwNicStatus];
  188. }
  189. #define SECS_PER_DAY (24*60*60)
  190. #define SECS_PER_HOUR (60*60)
  191. #define SECS_PER_MIN 60
  192. //Check and print the NIC driver status. pdwNetCardStatus will contain the net card status when
  193. //the function returns. If the query failed, *pdwNetCardStatus will be set
  194. // as NETCARD_STATUS_UNKNOWN.
  195. // Return: the Windows Error code.
  196. DWORD
  197. CheckThisDriver(NETDIAG_RESULT *pResults, PNDIS_INTERFACE pInterface, DWORD *pdwNetCardStatus)
  198. {
  199. NIC_STATISTICS Stats;
  200. DWORD dwReturnVal = ERROR_SUCCESS;
  201. DWORD dwNicStatus = NETCARD_CONNECTED;
  202. assert(pdwNetCardStatus);
  203. memset(&Stats, 0, sizeof(NIC_STATISTICS));
  204. Stats.Size = sizeof(NIC_STATISTICS);
  205. if(NdisQueryStatistics(&pInterface->DeviceName, &Stats))
  206. {
  207. //IDS_NDIS_16008 "\n Media State: %s\n"
  208. AddMessageToListId(&pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16008);
  209. switch(Stats.MediaState)
  210. {
  211. case MEDIA_STATE_CONNECTED:
  212. AddMessageToListId(&pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_CONNECTED);
  213. break;
  214. case MEDIA_STATE_DISCONNECTED:
  215. dwNicStatus = NETCARD_DISCONNECTED;
  216. AddMessageToListId(&pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_DISCONNECTED);
  217. break;
  218. default:
  219. dwNicStatus = NETCARD_STATUS_UNKNOWN;
  220. AddMessageToListId(&pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_UNKNOWN);
  221. break;
  222. }
  223. //IDS_NDIS_16009 "\n Device State: "
  224. AddMessageToListId( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16009);
  225. switch(Stats.DeviceState)
  226. {
  227. case DEVICE_STATE_CONNECTED:
  228. AddMessageToListId(&pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_CONNECTED);
  229. break;
  230. case DEVICE_STATE_DISCONNECTED:
  231. AddMessageToListId(&pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_DISCONNECTED);
  232. break;
  233. default:
  234. AddMessageToListId(&pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_UNKNOWN);
  235. break;
  236. }
  237. //IDS_NDIS_16010 " Connect Time: "
  238. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16010);
  239. if (Stats.ConnectTime > SECS_PER_DAY)
  240. {
  241. //IDS_NDIS_16011 "%d days, "
  242. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16011, Stats.ConnectTime / SECS_PER_DAY);
  243. Stats.ConnectTime %= SECS_PER_DAY;
  244. }
  245. //IDS_NDIS_16012 "%02d:"
  246. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16012, Stats.ConnectTime / SECS_PER_HOUR);
  247. Stats.ConnectTime %= SECS_PER_HOUR;
  248. //IDS_NDIS_16013 "%02d:"
  249. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16013, Stats.ConnectTime / SECS_PER_MIN);
  250. Stats.ConnectTime %= SECS_PER_MIN;
  251. //IDS_NDIS_16014 "%02d\n"
  252. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16014, Stats.ConnectTime);
  253. Stats.LinkSpeed *= 100;
  254. if (Stats.LinkSpeed >= 1000000000)
  255. //IDS_NDIS_16015 " Media Speed: %d Gbps\n"
  256. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16015,
  257. Stats.LinkSpeed / 1000000000);
  258. else if (Stats.LinkSpeed >= 1000000)
  259. //IDS_NDIS_16016 " Media Speed: %d Mbps\n"
  260. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16016,
  261. Stats.LinkSpeed / 1000000);
  262. else if (Stats.LinkSpeed >= 1000)
  263. //IDS_NDIS_16017 " Media Speed: %d Kbps\n"
  264. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16017,
  265. Stats.LinkSpeed / 1000);
  266. else
  267. //IDS_NDIS_16018 " Media Speed: %d bps\n"
  268. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16018,
  269. Stats.LinkSpeed);
  270. //IDS_NDIS_16019 "\n Packets Sent: %d\n"
  271. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16019, Stats.PacketsSent);
  272. //IDS_NDIS_16020 " Bytes Sent (Optional): %d\n"
  273. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16020, Stats.BytesSent);
  274. //IDS_NDIS_16021 "\n Packets Received: %d\n"
  275. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16021,
  276. Stats.PacketsReceived);
  277. //IDS_NDIS_16022 " Directed Pkts Recd (Optional): %d\n"
  278. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16022,
  279. Stats.DirectedPacketsReceived);
  280. //IDS_NDIS_16023 " Bytes Received (Optional): %d\n"
  281. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16023,
  282. Stats.BytesReceived);
  283. //IDS_NDIS_16024 " Directed Bytes Recd (Optional): %d\n\n"
  284. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16024,
  285. Stats.DirectedBytesReceived);
  286. if (Stats.PacketsSendErrors != 0)
  287. //IDS_NDIS_16025 " Packets SendError: %d\n"
  288. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16025,
  289. Stats.PacketsSendErrors);
  290. if (Stats.PacketsReceiveErrors != 0)
  291. //IDS_NDIS_16026 " Packets RecvError: %d\n"
  292. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_ReallyVerbose, IDS_NDIS_16026,
  293. Stats.PacketsReceiveErrors);
  294. // if we received packets, consider this driver to be fine
  295. if(NETCARD_CONNECTED != dwNicStatus)
  296. {
  297. //IDS_NDIS_16029 " [WARNING] The net card '%wZ' may not work!\n"
  298. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_Quiet, IDS_NDIS_16029,
  299. &pInterface->DeviceDescription);
  300. }
  301. else if (!Stats.PacketsReceived)
  302. {
  303. //IDS_NDIS_NO_RCV " [WARNING] The net card '%wZ' may not be working because it receives no packets!\n"
  304. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_Quiet, IDS_NDIS_NO_RCV,
  305. &pInterface->DeviceDescription);
  306. }
  307. } else {
  308. dwReturnVal = GetLastError();
  309. //IDS_NDIS_16027 " GetStats failed for '%wZ'. [%s]\n"
  310. AddMessageToList( &pResults->Ndis.lmsgOutput, Nd_Quiet, IDS_NDIS_16027,
  311. &pInterface->DeviceDescription, Win32ErrorToString(dwReturnVal));
  312. dwNicStatus = NETCARD_STATUS_UNKNOWN;
  313. }
  314. *pdwNetCardStatus = dwNicStatus;
  315. return dwReturnVal;
  316. }
  317. void NdisGlobalPrint(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults)
  318. {
  319. if (pParams->fVerbose || !FHrOK(pResults->Ndis.hrTestResult))
  320. {
  321. PrintNewLine(pParams, 2);
  322. PrintTestTitleResult(pParams,
  323. IDS_NDIS_LONG,
  324. IDS_NDIS_SHORT,
  325. TRUE,
  326. pResults->Ndis.hrTestResult,
  327. 0);
  328. }
  329. PrintMessageList(pParams, &pResults->Ndis.lmsgOutput);
  330. }
  331. void NdisPerInterfacePrint(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults, INTERFACE_RESULT *pInterfaceResults)
  332. {
  333. if (pParams->fVerbose || NETCARD_CONNECTED != pInterfaceResults->dwNetCardStatus)
  334. {
  335. PrintNewLine(pParams, 1);
  336. if (NETCARD_CONNECTED != pInterfaceResults->dwNetCardStatus)
  337. {
  338. PrintTestTitleResult(pParams, IDS_NDIS_LONG, IDS_NDIS_SHORT, TRUE, S_FALSE, 8);
  339. //IDS_NDIS_16030 " NetCard Status %s\n"
  340. PrintMessage(pParams, IDS_NDIS_16030, MapNetCardStatusToString(pInterfaceResults->dwNetCardStatus));
  341. if (NETCARD_DISCONNECTED == pInterfaceResults->dwNetCardStatus)
  342. PrintMessage(pParams, IDS_NDIS_CARD_DOWN);
  343. }
  344. else
  345. PrintTestTitleResult(pParams, IDS_NDIS_LONG, IDS_NDIS_SHORT, TRUE, S_OK, 8);
  346. }
  347. }
  348. void NdisCleanup(IN NETDIAG_PARAMS *pParams,
  349. IN OUT NETDIAG_RESULT *pResults)
  350. {
  351. MessageListCleanUp(&pResults->Ndis.lmsgOutput);
  352. }