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.

1182 lines
32 KiB

  1. //++
  2. //
  3. // Copyright (C) Microsoft Corporation, 1987 - 1999
  4. //
  5. // Module Name:
  6. //
  7. // ipcfg.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. #include "ipcfg.h"
  27. #include "regutil.h"
  28. #include "mprapi.h" // for friendly-name interface mapping
  29. #include "strings.h"
  30. LPTSTR MapScopeId(PVOID Param);
  31. LPTSTR MapAdapterType(UINT type);
  32. LPTSTR MapAdapterAddress(PIP_ADAPTER_INFO pAdapterInfo, LPTSTR Buffer);
  33. VOID PingDhcpServer(NETDIAG_PARAMS *pParams, IPCONFIG_TST *pIpConfig);
  34. VOID PingWinsServers(NETDIAG_PARAMS *pParams, IPCONFIG_TST *pIpConfig);
  35. /*==========================< Iphlpapi functions >===========================*/
  36. DWORD GetAdaptersInfo(
  37. PIP_ADAPTER_INFO pAdapterInfo,
  38. PULONG pOutBufLen
  39. );
  40. DWORD GetNetworkParams(
  41. PFIXED_INFO pFixedInfo,
  42. PULONG pOutBufLen
  43. );
  44. // -----------------------------------------------------------------
  45. HRESULT GetAdditionalInfo(NETDIAG_PARAMS *pParams, NETDIAG_RESULT *pResults);
  46. HRESULT
  47. IpConfigTest(
  48. NETDIAG_PARAMS* pParams,
  49. NETDIAG_RESULT* pResults
  50. )
  51. {
  52. HRESULT hr = hrOK;
  53. int i;
  54. IP_ADAPTER_INFO * pIpAdapterInfo;
  55. IPCONFIG_TST * pIpConfig;
  56. ULONG uDefGateway, uAddress, uMask;
  57. DWORD dwDefGateway, dwAddress, dwMask;
  58. hr = InitIpconfig(pParams, pResults);
  59. if (!FHrSucceeded(hr))
  60. {
  61. // "Cannot retrieve IP configuration from registry!\n"
  62. PrintDebug(pParams, 0, IDS_IPCFG_CANNOT_GET_IP_INFO);
  63. return hr;
  64. }
  65. for ( i = 0; i<pResults->cNumInterfaces; i++)
  66. {
  67. pIpConfig = &pResults->pArrayInterface[i].IpConfig;
  68. pIpAdapterInfo = pIpConfig->pAdapterInfo;
  69. if (!pResults->pArrayInterface[i].IpConfig.fActive ||
  70. NETCARD_DISCONNECTED == pResults->pArrayInterface[i].dwNetCardStatus)
  71. continue;
  72. // Ping the DHCP server
  73. if (pIpAdapterInfo->DhcpEnabled)
  74. {
  75. if (!ZERO_IP_ADDRESS(pIpAdapterInfo->DhcpServer.IpAddress.String))
  76. PingDhcpServer(pParams, pIpConfig);
  77. else
  78. {
  79. pIpConfig->hrPingDhcpServer = E_FAIL;
  80. pIpConfig->hr = E_FAIL;
  81. // " [WARNING] Though, the card is Dhcp Enabled, you dont have a valid DHCP server address for the card.\n"
  82. SetMessage(&pIpConfig->msgPingDhcpServer,
  83. Nd_Quiet,
  84. IDS_IPCFG_INVALID_DHCP_ADDRESS);
  85. }
  86. }
  87. if (pResults->pArrayInterface[i].fNbtEnabled)
  88. {
  89. // Ping the primary and secondary WINS servers
  90. PingWinsServers(pParams, pIpConfig);
  91. }
  92. if(pIpAdapterInfo->GatewayList.IpAddress.String[0] != 0)
  93. {
  94. // If the default gateway is defined,
  95. // then test to see if the gateway is on the same subnet as our IP address
  96. //
  97. uDefGateway = inet_addrA(pIpAdapterInfo->GatewayList.IpAddress.String);
  98. uAddress = inet_addrA(pIpAdapterInfo->IpAddressList.IpAddress.String);
  99. uMask = inet_addrA(pIpAdapterInfo->IpAddressList.IpMask.String);
  100. dwDefGateway = ntohl(uDefGateway);
  101. dwAddress = ntohl(uAddress);
  102. dwMask = ntohl(uMask);
  103. if ((dwDefGateway & dwMask) != (dwAddress & dwMask))
  104. {
  105. pIpConfig->hr = E_FAIL;
  106. pIpConfig->hrDefGwSubnetCheck = E_FAIL;
  107. }
  108. }
  109. }
  110. return hr;
  111. }
  112. LPTSTR MapScopeId(PVOID Param)
  113. {
  114. return !strcmp((LPTSTR)Param, _T("*")) ? _T("") : (LPTSTR)Param;
  115. }
  116. #define dim(X) (sizeof(X)/sizeof((X)[0]))
  117. /*!--------------------------------------------------------------------------
  118. MapGuidToServiceName
  119. -
  120. Author: KennT
  121. ---------------------------------------------------------------------------*/
  122. LPTSTR MapGuidToServiceName(LPCTSTR pszServiceGuid)
  123. {
  124. DWORD dwRetVal = ERROR_SUCCESS;
  125. static TCHAR s_szServiceName[MAX_ALLOWED_ADAPTER_NAME_LENGTH + 1];
  126. WCHAR swzServiceGuid[256], swzServiceName[256];
  127. // Copy guid into return buffer
  128. lstrcpyn(s_szServiceName, pszServiceGuid, DimensionOf(s_szServiceName));
  129. if( NULL == pfnGuidToFriendlyName )
  130. return s_szServiceName;
  131. StrCpyWFromT(swzServiceGuid, pszServiceGuid);
  132. if( !pfnGuidToFriendlyName(swzServiceGuid,
  133. swzServiceName,
  134. DimensionOf(swzServiceName)) )
  135. {
  136. StrnCpyTFromW(s_szServiceName, swzServiceName, DimensionOf(s_szServiceName));
  137. }
  138. return s_szServiceName;
  139. }
  140. /*!--------------------------------------------------------------------------
  141. MapGuidToServiceNameW
  142. -
  143. Author: KennT
  144. ---------------------------------------------------------------------------*/
  145. LPWSTR MapGuidToServiceNameW(LPCWSTR pswzServiceGuid)
  146. {
  147. DWORD dwRetVal = ERROR_SUCCESS;
  148. static WCHAR s_swzServiceName[1024];
  149. // Copy guid into return buffer
  150. StrnCpyW(s_swzServiceName, pswzServiceGuid, DimensionOf(s_swzServiceName));
  151. if (NULL == pfnGuidToFriendlyName)
  152. return s_swzServiceName;
  153. if (ERROR_SUCCESS != pfnGuidToFriendlyName((LPWSTR) pswzServiceGuid,
  154. s_swzServiceName,
  155. DimensionOf(s_swzServiceName)) )
  156. {
  157. //we still want to keep the GUID as service name if cannot find the friendly name
  158. StrnCpyW(s_swzServiceName, pswzServiceGuid, DimensionOf(s_swzServiceName));
  159. }
  160. return s_swzServiceName;
  161. }
  162. /*!--------------------------------------------------------------------------
  163. MapGuidToAdapterName
  164. -
  165. Author: KennT
  166. ---------------------------------------------------------------------------*/
  167. LPTSTR MapGuidToAdapterName(LPCTSTR pszAdapterGuid)
  168. {
  169. HANDLE hConfig;
  170. WCHAR swzAdapterGuid[256], swzAdapterName[256];
  171. static TCHAR s_szAdapterName[1024];
  172. HRESULT hr = hrOK;
  173. // Copy guid into return buffer
  174. StrnCpy(s_szAdapterName, pszAdapterGuid, DimensionOf(s_szAdapterName));
  175. StrnCpyWFromT(swzAdapterGuid, pszAdapterGuid, DimensionOf(swzAdapterGuid));
  176. CheckErr( MprConfigServerConnect(NULL, &hConfig) );
  177. CheckErr( MprConfigGetFriendlyName(hConfig, swzAdapterGuid,
  178. swzAdapterName,
  179. sizeof(swzAdapterName)
  180. ) );
  181. MprConfigServerDisconnect(hConfig);
  182. StrnCpyTFromW(s_szAdapterName, swzAdapterName, DimensionOf(s_szAdapterName));
  183. Error:
  184. return s_szAdapterName;
  185. }
  186. void
  187. PingDhcpServer(
  188. NETDIAG_PARAMS *pParams,
  189. IPCONFIG_TST *pIpConfig)
  190. {
  191. PrintStatusMessage(pParams, 4, IDS_IPCFG_STATUS_MSG);
  192. if (IsIcmpResponseA(pIpConfig->pAdapterInfo->DhcpServer.IpAddress.String))
  193. {
  194. pIpConfig->hrPingDhcpServer = S_OK;
  195. PrintStatusMessage(pParams,0, IDS_GLOBAL_PASS_NL);
  196. // " Pinging DHCP server - reachable\n"
  197. SetMessage(&pIpConfig->msgPingDhcpServer,
  198. Nd_ReallyVerbose,
  199. IDS_IPCFG_PING_DHCP_OK);
  200. }
  201. else
  202. {
  203. pIpConfig->hrPingDhcpServer = S_FALSE;
  204. if (FHrSucceeded(pIpConfig->hr))
  205. pIpConfig->hr = S_FALSE;
  206. PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
  207. // " Pinging DHCP server - not reachable\n"
  208. // " WARNING: DHCP server may be down.\n"
  209. SetMessage(&pIpConfig->msgPingDhcpServer,
  210. Nd_Quiet,
  211. IDS_IPCFG_PING_DHCP_BAD);
  212. }
  213. }
  214. VOID
  215. PingWinsServers(
  216. NETDIAG_PARAMS* pParams,
  217. IPCONFIG_TST *pIpConfig)
  218. {
  219. TCHAR szBuffer[256];
  220. if (!ZERO_IP_ADDRESS(pIpConfig->pAdapterInfo->PrimaryWinsServer.IpAddress.String))
  221. {
  222. PrintStatusMessage(pParams,4, IDS_IPCFG_WINS_STATUS_MSG);
  223. if (IsIcmpResponseA(pIpConfig->pAdapterInfo->PrimaryWinsServer.IpAddress.String))
  224. {
  225. pIpConfig->hrPingPrimaryWinsServer = S_OK;
  226. PrintStatusMessage(pParams,0, IDS_GLOBAL_PASS_NL);
  227. // " Pinging Primary WINS Server %s - reachable\n"
  228. SetMessage(&pIpConfig->msgPingPrimaryWinsServer,
  229. Nd_ReallyVerbose,
  230. IDS_IPCFG_PING_WINS,
  231. pIpConfig->pAdapterInfo->PrimaryWinsServer.IpAddress.String);
  232. }
  233. else
  234. {
  235. pIpConfig->hrPingPrimaryWinsServer = S_FALSE;
  236. if (FHrSucceeded(pIpConfig->hr))
  237. pIpConfig->hr = S_FALSE;
  238. PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
  239. // " Pinging Primary WINS Server %s - not reachable\n"
  240. SetMessage(&pIpConfig->msgPingPrimaryWinsServer,
  241. Nd_Quiet,
  242. IDS_IPCFG_PING_WINS_FAIL,
  243. pIpConfig->pAdapterInfo->PrimaryWinsServer.IpAddress.String);
  244. }
  245. }
  246. if (!ZERO_IP_ADDRESS(pIpConfig->pAdapterInfo->SecondaryWinsServer.IpAddress.String))
  247. {
  248. PrintStatusMessage(pParams,4, IDS_IPCFG_WINS2_STATUS_MSG);
  249. if (IsIcmpResponseA(pIpConfig->pAdapterInfo->SecondaryWinsServer.IpAddress.String))
  250. {
  251. pIpConfig->hrPingSecondaryWinsServer = S_OK;
  252. PrintStatusMessage(pParams,0, IDS_GLOBAL_PASS_NL);
  253. // " Pinging Secondary WINS Server %s - reachable\n"
  254. SetMessage(&pIpConfig->msgPingSecondaryWinsServer,
  255. Nd_ReallyVerbose,
  256. IDS_IPCFG_PING_WINS2,
  257. pIpConfig->pAdapterInfo->SecondaryWinsServer.IpAddress.String);
  258. }
  259. else
  260. {
  261. pIpConfig->hrPingSecondaryWinsServer = S_FALSE;
  262. if (FHrSucceeded(pIpConfig->hr))
  263. pIpConfig->hr = S_FALSE;
  264. PrintStatusMessage(pParams,0, IDS_GLOBAL_FAIL_NL);
  265. // " Pinging Secondary WINS Server %s - not reachable\n"
  266. SetMessage(&pIpConfig->msgPingSecondaryWinsServer,
  267. Nd_Quiet,
  268. IDS_IPCFG_PING_WINS2_FAIL,
  269. pIpConfig->pAdapterInfo->SecondaryWinsServer.IpAddress.String);
  270. }
  271. }
  272. return;
  273. }
  274. LPTSTR MapAdapterAddress(PIP_ADAPTER_INFO pAdapterInfo, LPTSTR Buffer)
  275. {
  276. LPTSTR format;
  277. int separator;
  278. int len;
  279. int i;
  280. LPTSTR pbuf = Buffer;
  281. UINT mask;
  282. len = min((int)pAdapterInfo->AddressLength, sizeof(pAdapterInfo->Address));
  283. mask = 0xff;
  284. separator = TRUE;
  285. switch (pAdapterInfo->Type)
  286. {
  287. case IF_TYPE_ETHERNET_CSMACD:
  288. case IF_TYPE_ISO88025_TOKENRING:
  289. case IF_TYPE_FDDI:
  290. format = _T("%02X");
  291. break;
  292. default:
  293. format = _T("%02x");
  294. break;
  295. }
  296. for (i = 0; i < len; ++i)
  297. {
  298. pbuf += wsprintf(pbuf, format, pAdapterInfo->Address[i] & mask);
  299. if (separator && (i != len - 1))
  300. {
  301. pbuf += wsprintf(pbuf, _T("-"));
  302. }
  303. }
  304. return Buffer;
  305. }
  306. void IpConfigCleanup(IN NETDIAG_PARAMS *pParams,
  307. IN OUT NETDIAG_RESULT *pResults)
  308. {
  309. int i;
  310. IPCONFIG_TST * pIpConfig;
  311. // Free up the global information
  312. // ----------------------------------------------------------------
  313. Free(pResults->IpConfig.pFixedInfo);
  314. pResults->IpConfig.pFixedInfo = NULL;
  315. // free up the list of adapters
  316. // ----------------------------------------------------------------
  317. Free(pResults->IpConfig.pAdapterInfoList);
  318. pResults->IpConfig.pAdapterInfoList = NULL;
  319. // set all of the adapter pointers to NULL
  320. // ----------------------------------------------------------------
  321. for ( i=0; i < pResults->cNumInterfaces; i++)
  322. {
  323. pIpConfig = &pResults->pArrayInterface[i].IpConfig;
  324. FreeIpAddressStringList(pIpConfig->DnsServerList.Next);
  325. pIpConfig->pAdapterInfo = NULL;
  326. ClearMessage(&pIpConfig->msgPingDhcpServer);
  327. ClearMessage(&pIpConfig->msgPingPrimaryWinsServer);
  328. ClearMessage(&pIpConfig->msgPingSecondaryWinsServer);
  329. }
  330. pResults->IpConfig.fInitIpconfigCalled = FALSE;
  331. }
  332. int AddIpAddressString(PIP_ADDR_STRING AddressList, LPSTR Address, LPSTR Mask)
  333. {
  334. PIP_ADDR_STRING ipAddr;
  335. if (AddressList->IpAddress.String[0])
  336. {
  337. for (ipAddr = AddressList; ipAddr->Next; ipAddr = ipAddr->Next)
  338. {
  339. ;
  340. }
  341. ipAddr->Next = (PIP_ADDR_STRING) Malloc(sizeof(IP_ADDR_STRING));
  342. if (!ipAddr->Next)
  343. {
  344. return FALSE;
  345. }
  346. ZeroMemory(ipAddr->Next, sizeof(IP_ADDR_STRING));
  347. ipAddr = ipAddr->Next;
  348. }
  349. else
  350. {
  351. ipAddr = AddressList;
  352. }
  353. lstrcpynA(ipAddr->IpAddress.String, Address,
  354. sizeof(ipAddr->IpAddress.String));
  355. lstrcpynA(ipAddr->IpMask.String, Mask,
  356. sizeof(ipAddr->IpMask.String));
  357. return TRUE;
  358. }
  359. VOID FreeIpAddressStringList(PIP_ADDR_STRING pAddressList)
  360. {
  361. PIP_ADDR_STRING pNext;
  362. if (pAddressList == NULL)
  363. return;
  364. do
  365. {
  366. // get the next address
  367. pNext = pAddressList->Next;
  368. // free the current one
  369. Free(pAddressList);
  370. // move onto the next
  371. pAddressList = pNext;
  372. } while( pNext );
  373. return;
  374. }
  375. // Go through the ADAPTER_INFO list to count the number of interfaces
  376. LONG CountInterfaces(PIP_ADAPTER_INFO ListAdapterInfo)
  377. {
  378. LONG cNum = 0;
  379. PIP_ADAPTER_INFO pAdapter;
  380. for(pAdapter = ListAdapterInfo; pAdapter != NULL; pAdapter = pAdapter->Next) {
  381. cNum ++;
  382. }
  383. return cNum;
  384. }
  385. /*!--------------------------------------------------------------------------
  386. InitIpconfig
  387. Description:
  388. This function will get all the ipconfig information by using calls into
  389. iphlpapi.lib.
  390. The iphlpapi.lib returns an IP_ADAPTER_INFO structure which doesnt contain
  391. many fields present int the ADAPTER_INFO structure found in ipconfig code.
  392. Since the majority of the code uses ADAPTER_INFO structure, this fucntion
  393. will copy the values found in IP_ADAPTER_INFO to ADAPTER_INFO.
  394. The values which are not supplied by iphlpapi.lib calls will be obtained
  395. by ourselves.
  396. Arguments:
  397. None.
  398. Author:
  399. 05-aug-1998 (t-rajkup)
  400. Creation History:
  401. The function aims at breaking nettest code away from ipconfig code.
  402. Author: NSun
  403. ---------------------------------------------------------------------------*/
  404. HRESULT
  405. InitIpconfig(IN NETDIAG_PARAMS *pParams,
  406. IN OUT NETDIAG_RESULT *pResults)
  407. {
  408. DWORD dwError;
  409. ULONG uSize = 0;
  410. int i;
  411. HRESULT hr = hrOK;
  412. LONG cInterfaces;
  413. IP_ADAPTER_INFO * pIpAdapter;
  414. HINSTANCE hDll;
  415. // Just initialize this once
  416. if (pResults->IpConfig.fInitIpconfigCalled == TRUE)
  417. return hrOK;
  418. // LoadLibrary the pfnGuidToFriendlyName
  419. // ----------------------------------------------------------------
  420. hDll = LoadLibrary(_T("netcfgx.dll"));
  421. if (hDll)
  422. {
  423. pfnGuidToFriendlyName = (PFNGUIDTOFRIENDLYNAME) GetProcAddress(hDll, "GuidToFriendlyName");
  424. }
  425. // Get the size of the FIXED_INFO structure and allocate
  426. // some memory for it.
  427. // ----------------------------------------------------------------
  428. GetNetworkParams(NULL, &uSize);
  429. pResults->IpConfig.pFixedInfo = Malloc(uSize);
  430. if (pResults->IpConfig.pFixedInfo == NULL)
  431. return E_OUTOFMEMORY;
  432. ZeroMemory(pResults->IpConfig.pFixedInfo, uSize);
  433. dwError = GetNetworkParams(pResults->IpConfig.pFixedInfo, &uSize);
  434. if (dwError != ERROR_SUCCESS)
  435. {
  436. TCHAR szError[256];
  437. FormatWin32Error(dwError, szError, DimensionOf(szError));
  438. PrintMessage(pParams, IDS_GLOBAL_ERR_InitIpConfig,
  439. szError, dwError);
  440. CheckErr( dwError );
  441. }
  442. // Get the per-interface information from IP
  443. // ----------------------------------------------------------------
  444. GetAdaptersInfo(NULL, &uSize);
  445. pResults->IpConfig.pAdapterInfoList = Malloc(uSize);
  446. if (pResults->IpConfig.pAdapterInfoList == NULL)
  447. {
  448. Free(pResults->IpConfig.pFixedInfo);
  449. CheckHr( E_OUTOFMEMORY );
  450. }
  451. ZeroMemory(pResults->IpConfig.pAdapterInfoList, uSize);
  452. dwError = GetAdaptersInfo(pResults->IpConfig.pAdapterInfoList, &uSize);
  453. if (dwError != ERROR_SUCCESS)
  454. {
  455. TCHAR szError[256];
  456. FormatWin32Error(dwError, szError, DimensionOf(szError));
  457. PrintMessage(pParams, IDS_GLOBAL_ERR_GetAdaptersInfo,
  458. szError, dwError);
  459. CheckErr( dwError );
  460. }
  461. // Now that we have the full list, count the number of interfaces
  462. // and setup the per-interface section of the results structure.
  463. // ----------------------------------------------------------------
  464. cInterfaces = CountInterfaces(pResults->IpConfig.pAdapterInfoList);
  465. // Allocate some additional interfaces (just in case for IPX)
  466. // ----------------------------------------------------------------
  467. pResults->pArrayInterface = Malloc((cInterfaces+8) * sizeof(INTERFACE_RESULT));
  468. if (pResults->pArrayInterface == NULL)
  469. CheckHr( E_OUTOFMEMORY );
  470. ZeroMemory(pResults->pArrayInterface, (cInterfaces+8)*sizeof(INTERFACE_RESULT));
  471. // set the individual interface pointers
  472. // ----------------------------------------------------------------
  473. pResults->cNumInterfaces = cInterfaces;
  474. pResults->cNumInterfacesAllocated = cInterfaces + 8;
  475. pIpAdapter = pResults->IpConfig.pAdapterInfoList;
  476. for (i=0; i<cInterfaces; i++)
  477. {
  478. assert(pIpAdapter);
  479. pResults->pArrayInterface[i].IpConfig.pAdapterInfo = pIpAdapter;
  480. pResults->pArrayInterface[i].fActive = TRUE;
  481. pResults->pArrayInterface[i].IpConfig.fActive = TRUE;
  482. if( FLAG_DONT_SHOW_PPP_ADAPTERS &&
  483. (pIpAdapter->Type == IF_TYPE_PPP))
  484. {
  485. // NDIS Wan adapter... Check to see if it has got any address..
  486. if( ZERO_IP_ADDRESS(pIpAdapter->IpAddressList.IpAddress.String) )
  487. {
  488. // No address ? Dont display this!
  489. pResults->pArrayInterface[i].IpConfig.fActive = FALSE;
  490. // If IP is not active, then don't activate the entire
  491. // adapter. If IPX is active, then it can reactivate
  492. // the adapter.
  493. pResults->pArrayInterface[i].fActive = FALSE;
  494. }
  495. }
  496. pResults->pArrayInterface[i].pszName = StrDup(pIpAdapter->AdapterName);
  497. pResults->pArrayInterface[i].pszFriendlyName =
  498. StrDup( MapGuidToAdapterName(pIpAdapter->AdapterName) );
  499. pIpAdapter = pIpAdapter->Next;
  500. }
  501. // Read the rest of the per adapter information not provided by
  502. // GetAdaptersInfo
  503. // ----------------------------------------------------------------
  504. CheckHr( GetAdditionalInfo(pParams, pResults) );
  505. pResults->IpConfig.fInitIpconfigCalled = TRUE;
  506. pResults->IpConfig.fEnabled = TRUE;
  507. Error:
  508. if (!FHrSucceeded(hr))
  509. {
  510. pResults->IpConfig.fEnabled = FALSE;
  511. IpConfigCleanup(pParams, pResults);
  512. }
  513. return hr;
  514. }
  515. DWORD GetNetbiosOptions(LPSTR paszAdapterName, BOOL * pfNbtOptions)
  516. {
  517. HANDLE h;
  518. OBJECT_ATTRIBUTES objAttr;
  519. IO_STATUS_BLOCK iosb;
  520. STRING name;
  521. UNICODE_STRING uname;
  522. NTSTATUS status;
  523. char path[MAX_PATH];
  524. tWINS_NODE_INFO NodeInfo;
  525. strcpy(path, "\\Device\\NetBT_Tcpip_");
  526. strcat(path, paszAdapterName);
  527. RtlInitString(&name, path);
  528. RtlAnsiStringToUnicodeString(&uname, &name, TRUE);
  529. InitializeObjectAttributes(
  530. &objAttr,
  531. &uname,
  532. OBJ_CASE_INSENSITIVE,
  533. (HANDLE)NULL,
  534. (PSECURITY_DESCRIPTOR)NULL
  535. );
  536. status = NtCreateFile(&h,
  537. SYNCHRONIZE | GENERIC_EXECUTE,
  538. &objAttr,
  539. &iosb,
  540. NULL,
  541. FILE_ATTRIBUTE_NORMAL,
  542. FILE_SHARE_READ | FILE_SHARE_WRITE,
  543. FILE_OPEN_IF,
  544. 0,
  545. NULL,
  546. 0
  547. );
  548. RtlFreeUnicodeString(&uname);
  549. if (!NT_SUCCESS(status)) {
  550. DEBUG_PRINT(("GetWinsServers: NtCreateFile(path=%s) failed, err=%d\n",
  551. path, GetLastError() ));
  552. return FALSE;
  553. }
  554. status = NtDeviceIoControlFile(h,
  555. NULL,
  556. NULL,
  557. NULL,
  558. &iosb,
  559. IOCTL_NETBT_GET_WINS_ADDR,
  560. NULL,
  561. 0,
  562. (PVOID)&NodeInfo,
  563. sizeof(NodeInfo)
  564. );
  565. if (status == STATUS_PENDING) {
  566. status = NtWaitForSingleObject(h, TRUE, NULL);
  567. if (NT_SUCCESS(status)) {
  568. status = iosb.Status;
  569. }
  570. }
  571. NtClose(h);
  572. if (!NT_SUCCESS(status)) {
  573. DEBUG_PRINT(("GetWinsServers: NtDeviceIoControlFile failed, err=%d\n",
  574. GetLastError() ));
  575. return FALSE;
  576. }
  577. *pfNbtOptions = NodeInfo.NetbiosEnabled;
  578. return TRUE;
  579. }
  580. /*!--------------------------------------------------------------------------
  581. GetAdditionalInfo
  582. ++
  583. Description:
  584. Read the information not provided by GetAdaptersInfo and also copy the data
  585. into the PADAPTER_INFO structure.
  586. Arguments:
  587. None.
  588. Author:
  589. 05-Aug-1998 (t-rajkup)
  590. --
  591. Author: NSun
  592. ---------------------------------------------------------------------------*/
  593. HRESULT GetAdditionalInfo(IN NETDIAG_PARAMS *pParams,
  594. IN OUT NETDIAG_RESULT *pResults)
  595. {
  596. PIP_ADAPTER_INFO pIpAdapterInfo;
  597. HKEY key;
  598. char dhcpServerAddress[4 * 4];
  599. BOOL ok;
  600. ULONG length;
  601. DWORD DhcpClassIDLen;
  602. int i;
  603. INTERFACE_RESULT *pInterface = NULL;
  604. for (i=0; i<pResults->cNumInterfaces; i++)
  605. {
  606. pInterface = pResults->pArrayInterface + i;
  607. pIpAdapterInfo = pInterface->IpConfig.pAdapterInfo;
  608. assert(pIpAdapterInfo);
  609. if (pIpAdapterInfo->AdapterName[0] &&
  610. OpenAdapterKey(pIpAdapterInfo->AdapterName, &key) )
  611. {
  612. if( ! ReadRegistryDword(key,
  613. c_szRegIPAutoconfigurationEnabled,
  614. &(pInterface->IpConfig.fAutoconfigEnabled) ))
  615. {
  616. // AUTOCONFIG enabled if no regval exists for this...
  617. pInterface->IpConfig.fAutoconfigEnabled = TRUE;
  618. }
  619. if ( pInterface->IpConfig.fAutoconfigEnabled )
  620. {
  621. ReadRegistryDword(key,
  622. c_szRegAddressType,
  623. &(pInterface->IpConfig.fAutoconfigActive)
  624. );
  625. }
  626. //
  627. // domain: first try Domain then DhcpDomain
  628. //
  629. length = sizeof(pInterface->IpConfig.szDomainName);
  630. ok = ReadRegistryOemString(key,
  631. L"Domain",
  632. pInterface->IpConfig.szDomainName,
  633. &length
  634. );
  635. if (!ok)
  636. {
  637. length = sizeof(pInterface->IpConfig.szDomainName);
  638. ok = ReadRegistryOemString(key,
  639. L"DhcpDomain",
  640. pInterface->IpConfig.szDomainName,
  641. &length
  642. );
  643. }
  644. // DNS Server list.. first try NameServer and then try
  645. // DhcpNameServer..
  646. ok = ReadRegistryIpAddrString(key,
  647. c_szRegNameServer,
  648. &(pInterface->IpConfig.DnsServerList)
  649. );
  650. if (!ok) {
  651. ok = ReadRegistryIpAddrString(key,
  652. c_szRegDhcpNameServer,
  653. &(pInterface->IpConfig.DnsServerList)
  654. );
  655. }
  656. //
  657. // Read the DHCP Class Id for this interface - Rajkumar
  658. //
  659. ZeroMemory(pInterface->IpConfig.szDhcpClassID,
  660. sizeof(pInterface->IpConfig.szDhcpClassID));
  661. ReadRegistryString(key,
  662. c_szRegDhcpClassID,
  663. pInterface->IpConfig.szDhcpClassID,
  664. &DhcpClassIDLen
  665. );
  666. RegCloseKey(key);
  667. //
  668. // before getting the WINS info we must set the NodeType
  669. //
  670. pInterface->IpConfig.uNodeType = pResults->IpConfig.pFixedInfo->NodeType;
  671. }
  672. else
  673. {
  674. // IDS_IPCFG_10003 "Opening registry key for %s failed!\n"
  675. PrintMessage(pParams, IDS_IPCFG_10003,pIpAdapterInfo->AdapterName);
  676. return S_FALSE;
  677. }
  678. //be default, NetBt is enabled
  679. pInterface->fNbtEnabled = TRUE;
  680. GetNetbiosOptions(pIpAdapterInfo->AdapterName, &pInterface->fNbtEnabled);
  681. if (pInterface->fNbtEnabled)
  682. {
  683. pResults->Global.fHasNbtEnabledInterface = TRUE;
  684. }
  685. }
  686. return TRUE;
  687. }
  688. /*!--------------------------------------------------------------------------
  689. IpConfigGlobalPrint
  690. -
  691. Author: KennT
  692. ---------------------------------------------------------------------------*/
  693. void IpConfigGlobalPrint(IN NETDIAG_PARAMS *pParams,
  694. IN OUT NETDIAG_RESULT *pResults)
  695. {
  696. PFIXED_INFO pFixedInfo = pResults->IpConfig.pFixedInfo;
  697. if (pParams->fReallyVerbose)
  698. {
  699. PrintNewLine(pParams, 2);
  700. // IDS_IPCFG_10005 "IP General configuration \n"
  701. // IDS_IPCFG_10006 " LMHOSTS Enabled :"
  702. PrintMessage(pParams, IDS_IPCFG_10005);
  703. PrintMessage(pParams, IDS_IPCFG_10006);
  704. if (pResults->Global.dwLMHostsEnabled)
  705. PrintMessage(pParams, IDS_GLOBAL_YES_NL);
  706. else
  707. PrintMessage(pParams, IDS_GLOBAL_NO_NL);
  708. // IDS_IPCFG_10009 " DNS for WINS resolution:"
  709. PrintMessage(pParams, IDS_IPCFG_10009);
  710. if (pResults->Global.dwDnsForWINS)
  711. PrintMessage(pParams, IDS_GLOBAL_ENABLED_NL);
  712. else
  713. PrintMessage(pParams, IDS_GLOBAL_DISABLED_NL);
  714. // NBT node type
  715. // ------------------------------------------------------------
  716. PrintMessage(pParams, IDSSZ_IPCFG_NODETYPE,
  717. MapWinsNodeType(pFixedInfo->NodeType));
  718. // NBT scope id
  719. // ------------------------------------------------------------
  720. PrintMessage(pParams, IDSSZ_IPCFG_NBTSCOPEID,
  721. MapScopeId(pFixedInfo->ScopeId));
  722. // ip routing
  723. // ------------------------------------------------------------
  724. PrintMessage(pParams, IDSSZ_IPCFG_RoutingEnabled,
  725. MAP_YES_NO(pFixedInfo->EnableRouting));
  726. // WINS proxy
  727. // ------------------------------------------------------------
  728. PrintMessage(pParams, IDSSZ_IPCFG_WinsProxyEnabled,
  729. MAP_YES_NO(pFixedInfo->EnableProxy));
  730. // DNS resolution for apps using NetBIOS
  731. // ------------------------------------------------------------
  732. PrintMessage(pParams, IDSSZ_IPCFG_DnsForNetBios,
  733. MAP_YES_NO(pFixedInfo->EnableDns));
  734. // separate fixed and adapter information with an empty line
  735. // ------------------------------------------------------------
  736. PrintMessage(pParams, IDS_GLOBAL_EmptyLine);
  737. }
  738. }
  739. /*!--------------------------------------------------------------------------
  740. IpConfigPerInterfacePrint
  741. -
  742. Author: KennT
  743. ---------------------------------------------------------------------------*/
  744. void IpConfigPerInterfacePrint(IN NETDIAG_PARAMS *pParams,
  745. IN NETDIAG_RESULT *pResults,
  746. IN INTERFACE_RESULT *pInterfaceResults)
  747. {
  748. PIP_ADDR_STRING dnsServer;
  749. PFIXED_INFO pFixedInfo = pResults->IpConfig.pFixedInfo;
  750. IP_ADAPTER_INFO* pIpAdapterInfo;
  751. PIP_ADDR_STRING ipAddr;
  752. IPCONFIG_TST * pIpCfgResults;
  753. ULONG uDefGateway, uAddress, uMask;
  754. DWORD dwDefGateway, dwAddress, dwMask;
  755. int ids;
  756. pIpAdapterInfo = pInterfaceResults->IpConfig.pAdapterInfo;
  757. pIpCfgResults = &(pInterfaceResults->IpConfig);
  758. if (!pIpCfgResults->fActive)
  759. return;
  760. PrintNewLine(pParams, 1);
  761. if(pParams->fReallyVerbose)
  762. {
  763. // IDS_IPCFG_10012 " Adapter type : %s\n"
  764. PrintMessage(pParams, IDS_IPCFG_10012,
  765. MapAdapterType(pIpAdapterInfo->Type));
  766. }
  767. PrintMessage(pParams, IDSSZ_IPCFG_HostName,
  768. pFixedInfo->HostName,
  769. pIpCfgResults->szDomainName[0] ? _T(".") : _T(""),
  770. pIpCfgResults->szDomainName[0] ?
  771. pIpCfgResults->szDomainName : _T(""));
  772. // return;
  773. if (pParams->fReallyVerbose)
  774. {
  775. // IDS_IPCFG_10014 " Description : %s\n"
  776. PrintMessage(pParams, IDS_IPCFG_10014, pIpAdapterInfo->Description );
  777. if (pIpAdapterInfo->AddressLength)
  778. {
  779. char buffer[MAX_ADAPTER_ADDRESS_LENGTH * sizeof(_T("02-"))];
  780. // IDS_IPCFG_10015 " Physical Address : %s\n"
  781. PrintMessage(pParams, IDS_IPCFG_10015,
  782. MapAdapterAddress(pIpAdapterInfo, buffer));
  783. }
  784. // IDS_IPCFG_10016 " Dhcp Enabled : %s\n"
  785. PrintMessage(pParams, IDS_IPCFG_10016,
  786. MAP_YES_NO(pIpAdapterInfo->DhcpEnabled));
  787. // IDS_IPCFG_10017 " DHCP ClassID : %s\n"
  788. PrintMessage(pParams, IDS_IPCFG_10017, pIpCfgResults->szDhcpClassID);
  789. // IDS_IPCFG_10018 " Autoconfiguration Enabled : %s\n"
  790. PrintMessage(pParams, IDS_IPCFG_10018,
  791. MAP_YES_NO(pIpCfgResults->fAutoconfigEnabled));
  792. }
  793. //
  794. // the following 3 items are the only items displayed (per adapter) if
  795. // /all was NOT requested on the command line
  796. //
  797. for (ipAddr = &pIpAdapterInfo->IpAddressList;
  798. ipAddr;
  799. ipAddr = ipAddr->Next)
  800. {
  801. if (pIpCfgResults->fAutoconfigActive)
  802. // IDS_IPCFG_10019 " Autoconfiguration IP Address : %s\n"
  803. PrintMessage(pParams, IDS_IPCFG_10019,ipAddr->IpAddress.String);
  804. else
  805. // IDS_IPCFG_10020 " IP Address : %s\n"
  806. PrintMessage(pParams, IDS_IPCFG_10020,ipAddr->IpAddress.String);
  807. // IDS_IPCFG_10021 " Subnet Mask : %s\n"
  808. PrintMessage(pParams, IDS_IPCFG_10021, ipAddr->IpMask.String );
  809. }
  810. //
  811. // there will only be one default gateway
  812. //
  813. // IDS_IPCFG_10022 " Default Gateway : %s\n"
  814. PrintMessage(pParams, IDS_IPCFG_10022,
  815. pIpAdapterInfo->GatewayList.IpAddress.String );
  816. if (pParams->fReallyVerbose)
  817. {
  818. if (pIpAdapterInfo->DhcpEnabled && FALSE == pIpCfgResults->fAutoconfigActive) {
  819. //
  820. // there will only be 1 DHCP server (that we get info from)
  821. //
  822. // IDS_IPCFG_10023 " DHCP Server : %s\n"
  823. PrintMessage(pParams, IDS_IPCFG_10023,
  824. pIpAdapterInfo->DhcpServer.IpAddress.String );
  825. }
  826. }
  827. //
  828. // there is only 1 primary and 1 secondary WINS server
  829. //
  830. // if (pParams->fReallyVerbose)
  831. {
  832. if (pIpAdapterInfo->PrimaryWinsServer.IpAddress.String[0]
  833. && !ZERO_IP_ADDRESS(pIpAdapterInfo->PrimaryWinsServer.IpAddress.String))
  834. {
  835. // IDS_IPCFG_10024 " Primary WINS Server : %s\n"
  836. PrintMessage(pParams, IDS_IPCFG_10024,
  837. pIpAdapterInfo->PrimaryWinsServer.IpAddress.String );
  838. }
  839. if (pIpAdapterInfo->SecondaryWinsServer.IpAddress.String[0]
  840. && !ZERO_IP_ADDRESS(pIpAdapterInfo->SecondaryWinsServer.IpAddress.String)) {
  841. // IDS_IPCFG_10025 " Secondary WINS Server : %s\n"
  842. PrintMessage(pParams, IDS_IPCFG_10025,
  843. pIpAdapterInfo->SecondaryWinsServer.IpAddress.String);
  844. }
  845. if (!pInterfaceResults->fNbtEnabled)
  846. {
  847. //IDS_IPCFG_NBT_DISABLED " NetBIOS over Tcpip . . . . : Disabled\n"
  848. PrintMessage(pParams, IDS_IPCFG_NBT_DISABLED);
  849. }
  850. }
  851. //
  852. // only display lease times if this adapter is DHCP enabled and we
  853. // have a non-0 IP address and not using autoconfigured address..
  854. //
  855. if (pParams->fReallyVerbose) {
  856. if (pIpAdapterInfo->DhcpEnabled
  857. && !ZERO_IP_ADDRESS(pIpAdapterInfo->IpAddressList.IpAddress.String)
  858. && !pIpCfgResults->fAutoconfigActive) {
  859. // IDS_IPCFG_10026 " Lease Obtained : %s\n"
  860. PrintMessage(pParams, IDS_IPCFG_10026 ,
  861. MapTime(pIpAdapterInfo->LeaseObtained) );
  862. // IDS_IPCFG_10027 " Lease Expires : %s\n"
  863. PrintMessage(pParams, IDS_IPCFG_10027,
  864. MapTime(pIpAdapterInfo->LeaseExpires) );
  865. }
  866. }
  867. //
  868. // display the list of DNS servers. If the list came from SYSTEM.INI then
  869. // just display that, else if the list came from DHCP.BIN, get all DNS
  870. // servers for all NICs and display the compressed list
  871. //
  872. PrintMessage(pParams, IDS_IPCFG_DnsServers);
  873. if (pIpCfgResults->DnsServerList.IpAddress.String[0])
  874. {
  875. dnsServer = &pIpCfgResults->DnsServerList;
  876. // print out the first one
  877. PrintMessage(pParams, IDSSZ_GLOBAL_StringLine,
  878. dnsServer->IpAddress.String);
  879. dnsServer = dnsServer->Next;
  880. for ( ;
  881. dnsServer;
  882. dnsServer = dnsServer->Next)
  883. {
  884. // IDS_IPCFG_10013 " "
  885. PrintMessage(pParams, IDS_IPCFG_10013);
  886. PrintMessage(pParams, IDSSZ_GLOBAL_StringLine, dnsServer->IpAddress.String);
  887. }
  888. }
  889. PrintNewLine(pParams, 1);
  890. // If this is a verbose output, or if an error occurred with
  891. // any of the tests then we will need a header
  892. // -----------------------------------------------------------------
  893. if (pParams->fReallyVerbose || !FHrOK(pIpCfgResults->hr))
  894. {
  895. // IDS_IPCFG_10029 " IpConfig results : "
  896. PrintMessage(pParams, IDS_IPCFG_10029);
  897. if (FHrOK(pIpCfgResults->hr))
  898. ids = IDS_GLOBAL_PASS_NL;
  899. else
  900. ids = IDS_GLOBAL_FAIL_NL;
  901. PrintMessage(pParams, ids);
  902. }
  903. //
  904. // Ping the dhcp server
  905. //
  906. PrintNdMessage(pParams, &pInterfaceResults->IpConfig.msgPingDhcpServer);
  907. //
  908. // Ping the WINS servers
  909. //
  910. PrintNdMessage(pParams, &pInterfaceResults->IpConfig.msgPingPrimaryWinsServer);
  911. PrintNdMessage(pParams, &pInterfaceResults->IpConfig.msgPingSecondaryWinsServer);
  912. //
  913. // Test to see if the gateway is on the same subnet as our IP address
  914. //
  915. if (!FHrOK(pInterfaceResults->IpConfig.hrDefGwSubnetCheck))
  916. {
  917. PrintNewLine(pParams, 1);
  918. if (pIpAdapterInfo->DhcpEnabled)
  919. PrintMessage(pParams, IDS_IPCFG_WARNING_BOGUS_SUBNET_DHCP);
  920. else
  921. PrintMessage(pParams, IDS_IPCFG_WARNING_BOGUS_SUBNET);
  922. }
  923. //
  924. // if there's more to come, separate lists with empty line
  925. //
  926. PrintNewLine(pParams, 1);
  927. }
  928. /*!--------------------------------------------------------------------------
  929. ZERO_IP_ADDRESS
  930. -
  931. Author: KennT
  932. ---------------------------------------------------------------------------*/
  933. BOOL ZERO_IP_ADDRESS(LPCTSTR pszIp)
  934. {
  935. return (pszIp == NULL) ||
  936. (*pszIp == 0) ||
  937. (strcmp(pszIp, _T("0.0.0.0")) == 0);
  938. }