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.

1726 lines
48 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. info.c
  5. Abstract:
  6. exports GetNetworkInformation routine
  7. --*/
  8. #include <precomp.h>
  9. //
  10. // seems that if WINS addresses not specified, NetBT reports 127.0.0.0 so if
  11. // this value is returned, we won't display them
  12. //
  13. #define LOCAL_WINS_ADDRESS 0x0000007f // 127.0.0.0
  14. #define New(Size) LocalAlloc( LPTR, Size)
  15. #define Delete(Ptr) if( NULL != Ptr ) LocalFree( Ptr )
  16. #define CheckBoolError(Internal) if( FALSE == fSuccess ) {\
  17. (*InternalError) = Internal; Error = GetLastError(); break; }
  18. #define CheckError(Internal) if( NO_ERROR != Error ) {\
  19. (*InternalError) = Internal; break; }
  20. VOID
  21. FreeIfInfo(
  22. IN OUT PINTERFACE_NETWORK_INFO IfInfo
  23. )
  24. {
  25. if( NULL == IfInfo ) return;
  26. Delete( IfInfo->FriendlyName );
  27. Delete( IfInfo->ConnectionName );
  28. Delete( IfInfo->DhcpClassId );
  29. Delete( IfInfo->IpAddress );
  30. Delete( IfInfo->Ipv6Address );
  31. Delete( IfInfo->IpMask );
  32. Delete( IfInfo->Router );
  33. Delete( IfInfo->WinsServer );
  34. Delete( IfInfo->DnsServer );
  35. Delete( IfInfo->Ipv6DnsServer );
  36. Delete( IfInfo );
  37. }
  38. VOID
  39. FreeNetworkInfo(
  40. IN OUT PNETWORK_INFO NetInfo
  41. )
  42. {
  43. DWORD i;
  44. if( NULL == NetInfo ) return;
  45. for( i = 0; i < NetInfo->nInterfaces ; i ++ ) {
  46. FreeIfInfo( NetInfo->IfInfo[i] );
  47. }
  48. Delete( NetInfo->SuffixSearchList );
  49. Delete( NetInfo );
  50. }
  51. DWORD
  52. MapIfType(
  53. IN OUT PINTERFACE_NETWORK_INFO IfInfo,
  54. IN ULONG IfType
  55. )
  56. {
  57. DWORD i;
  58. DWORD Map[][2] = {
  59. IF_TYPE_OTHER, IfTypeOther,
  60. IF_TYPE_ETHERNET_CSMACD, IfTypeEthernet,
  61. IF_TYPE_ISO88025_TOKENRING, IfTypeTokenring,
  62. IF_TYPE_FDDI, IfTypeFddi,
  63. IF_TYPE_PPP, IfTypePPP,
  64. IF_TYPE_SOFTWARE_LOOPBACK, IfTypeLoopback,
  65. IF_TYPE_SLIP, IfTypeSlip,
  66. IF_TYPE_TUNNEL, IfTypeTunnel,
  67. IF_TYPE_IEEE1394, IfType1394
  68. };
  69. for( i = 0; i < sizeof(Map)/sizeof(Map[0]); i ++ ) {
  70. if( Map[i][0] == IfType ) {
  71. IfInfo->IfType = Map[i][1];
  72. return NO_ERROR;
  73. }
  74. }
  75. return ERROR_NOT_FOUND;
  76. }
  77. LPWSTR
  78. GetProperty(
  79. IN HDEVINFO hdi,
  80. IN SP_DEVINFO_DATA *deid,
  81. IN ULONG Property
  82. )
  83. {
  84. BOOL fSuccess;
  85. ULONG Error, cbSize;
  86. LPWSTR RetVal;
  87. cbSize = 0;
  88. fSuccess = SetupDiGetDeviceRegistryPropertyW(
  89. hdi, deid, Property, NULL, NULL, 0, &cbSize
  90. );
  91. if( fSuccess ) {
  92. RetVal = LocalAlloc(LPTR, sizeof(WCHAR));
  93. if( NULL == RetVal ) return NULL;
  94. (*RetVal) = L'\0';
  95. return RetVal;
  96. }
  97. Error = GetLastError();
  98. if( ERROR_INSUFFICIENT_BUFFER != Error ) return NULL;
  99. RetVal = New( cbSize * sizeof(WCHAR) );
  100. if( NULL == RetVal ) return NULL ;
  101. fSuccess = SetupDiGetDeviceRegistryPropertyW(
  102. hdi, deid, Property, NULL, (PVOID)RetVal, cbSize, NULL
  103. );
  104. if( FALSE == fSuccess ) {
  105. Error = GetLastError();
  106. Delete( RetVal );
  107. SetLastError(Error);
  108. return NULL;
  109. }
  110. return RetVal;
  111. }
  112. LPWSTR
  113. GetDescriptionFromGuid(
  114. IN GUID *Guid
  115. )
  116. {
  117. WCHAR InstanceIdBuf[1000];
  118. ULONG BufSizeInWChars = sizeof(InstanceIdBuf)/sizeof(WCHAR);
  119. HRESULT hr;
  120. HDEVINFO hdi;
  121. SP_DEVINFO_DATA deid;
  122. BOOL fSuccess;
  123. ULONG Error;
  124. LPWSTR DescrName = NULL;
  125. deid.cbSize = sizeof(SP_DEVINFO_DATA);
  126. hr = HrPnpInstanceIdFromGuid(Guid, InstanceIdBuf, BufSizeInWChars);
  127. if( !SUCCEEDED(hr) ) {
  128. SetLastError( HRESULT_CODE(hr) );
  129. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("HrPnpInstanceIdFromGuid returns 0x%lx (%d)\n", hr, hr));
  130. return NULL;
  131. }
  132. hdi = SetupDiCreateDeviceInfoList(&GUID_DEVCLASS_NET, NULL);
  133. if( INVALID_HANDLE_VALUE != hdi ) {
  134. fSuccess = SetupDiOpenDeviceInfoW(hdi, InstanceIdBuf, NULL, 0, &deid);
  135. if( fSuccess ) {
  136. DescrName = GetProperty(hdi, &deid, SPDRP_FRIENDLYNAME);
  137. if( NULL == DescrName ) {
  138. Error = GetLastError();
  139. if( ERROR_SUCCESS != Error ) {
  140. DescrName = GetProperty( hdi, &deid, SPDRP_DEVICEDESC );
  141. if( NULL == DescrName ) {
  142. Error = GetLastError();
  143. } else {
  144. Error = ERROR_SUCCESS;
  145. }
  146. } else {
  147. //
  148. // Error already set.
  149. //
  150. }
  151. } else {
  152. //
  153. // We succeeded..
  154. //
  155. Error = ERROR_SUCCESS;
  156. }
  157. } else {
  158. Error = GetLastError();
  159. }
  160. SetupDiDestroyDeviceInfoList(hdi);
  161. } else {
  162. Error = GetLastError();
  163. }
  164. SetLastError(Error);
  165. return (ERROR_SUCCESS == Error)?DescrName:NULL;
  166. }
  167. LPWSTR
  168. GetDescription(
  169. IN GUID *Guid,
  170. IN LPWSTR GuidString
  171. )
  172. {
  173. LPWSTR RetVal = GetDescriptionFromGuid(Guid);
  174. WCHAR GuidStringBuf[500];
  175. GUID GuidStruct;
  176. ULONG Status;
  177. if( NULL != RetVal ) return RetVal;
  178. SetLastError( ERROR_CAN_NOT_COMPLETE );
  179. if( NULL == GuidString ) return NULL;
  180. if( wcslen(GuidString)*sizeof(WCHAR) >= sizeof(GuidStringBuf)) {
  181. return NULL;
  182. }
  183. if( GuidString[0] != L'{' ) return NULL;
  184. wcscpy(GuidStringBuf, &GuidString[1]);
  185. if( L'}' != GuidStringBuf[wcslen(GuidStringBuf)-1] ) {
  186. return NULL;
  187. }
  188. GuidStringBuf[wcslen(GuidStringBuf)-1] = L'\0';
  189. Status = UuidFromStringW(GuidStringBuf, &GuidStruct);
  190. if( RPC_S_OK != Status ) {
  191. SetLastError( Status );
  192. return NULL;
  193. }
  194. return GetDescriptionFromGuid(&GuidStruct);
  195. }
  196. VOID
  197. GetInterfaceGuidAndDeviceName(
  198. IN PMIB_IFROW IfRow,
  199. IN PIP_INTERFACE_INFO InterfaceInfo,
  200. IN PIP_INTERFACE_NAME_INFO IfNameInfo,
  201. IN ULONG IfNameCount,
  202. OUT GUID *IfGuid,
  203. OUT LPWSTR *IfDeviceName
  204. )
  205. {
  206. DWORD i;
  207. //
  208. // Search interface name info to get the interface guid for
  209. // this interface. Also, search the InterfaceInfo to get the
  210. // devicename for this interface.
  211. //
  212. ZeroMemory( IfGuid, sizeof(*IfGuid) );
  213. for( i = 0; i < IfNameCount ; i ++ ) {
  214. if( IfRow->dwIndex != IfNameInfo[i].Index ) continue;
  215. (*IfGuid) = IfNameInfo[i].InterfaceGuid;
  216. break;
  217. }
  218. (*IfDeviceName) = NULL;
  219. for( i = 0; i < (DWORD)InterfaceInfo->NumAdapters; i ++ ) {
  220. if( InterfaceInfo->Adapter[i].Index != IfRow->dwIndex ) continue;
  221. (*IfDeviceName) = InterfaceInfo->Adapter[i].Name + strlen(
  222. "\\Device\\Tcpip_" );
  223. break;
  224. }
  225. }
  226. DWORD
  227. MapFriendlyAndConnectionNames(
  228. IN OUT PINTERFACE_NETWORK_INFO IfInfo,
  229. IN PMIB_IFROW IfRow,
  230. IN GUID IfGuid,
  231. IN LPWSTR IfDeviceName
  232. )
  233. {
  234. DWORD Size, Error;
  235. WCHAR ConnName[500];
  236. //
  237. // Try to get friendly device name from IfGuid or DeviceName
  238. // or failing both just use the description provided by tcpip
  239. //
  240. IfInfo->FriendlyName = GetDescription( &IfGuid, IfDeviceName );
  241. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("GetDescription returns %p for %ws\n", IfInfo->FriendlyName, IfDeviceName));
  242. if( NULL == IfInfo->FriendlyName ) {
  243. Size = MultiByteToWideChar(
  244. CP_ACP, 0, (LPSTR)IfRow->bDescr, IfRow->dwDescrLen, NULL, 0 );
  245. if( Size == 0 ) return GetLastError();
  246. Size ++;
  247. IfInfo->FriendlyName = New( Size * sizeof(WCHAR) );
  248. if (IfInfo->FriendlyName == NULL) return GetLastError();
  249. Size = MultiByteToWideChar(
  250. CP_ACP, 0, (LPSTR)IfRow->bDescr, IfRow->dwDescrLen,
  251. IfInfo->FriendlyName, Size );
  252. if( 0 == Size ) return GetLastError();
  253. }
  254. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\tFriendly Name: %ws\n", IfInfo->FriendlyName));
  255. //
  256. // Now get the connection name. First try with LAN, then RAS
  257. //
  258. Size = sizeof(ConnName)/sizeof(WCHAR);
  259. Error = HrLanConnectionNameFromGuidOrPath(
  260. NULL, IfDeviceName, ConnName, &Size );
  261. if( NO_ERROR != Error ) {
  262. Size = sizeof(ConnName)/sizeof(WCHAR);
  263. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("HrLanConnectionNameFromGuidOrPath fails 0x%lx(%d)", Error, Error));
  264. Error = NhGetInterfaceNameFromGuid(
  265. &IfGuid, ConnName, &Size, FALSE, FALSE );
  266. if( NO_ERROR != Error ) {
  267. ConnName[0] = L'\0';
  268. IPCFG_TRACE(IPCFG_TRACE_TCPIP, (" NhGetInterfaceNameFromGuid fails 0x%lx(%d)", Error, Error));
  269. //return Error;
  270. }
  271. }
  272. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\tConnection Name: %ws\n", ConnName));
  273. IfInfo->ConnectionName = New( sizeof(WCHAR)*(1+wcslen(ConnName)));
  274. if( NULL == IfInfo->ConnectionName ) return GetLastError();
  275. wcscpy(IfInfo->ConnectionName, ConnName );
  276. return NO_ERROR;
  277. }
  278. DWORD
  279. GetMediaStatus(
  280. IN LPWSTR IfDeviceName,
  281. OUT BOOL *fDisconnected
  282. )
  283. {
  284. WCHAR NdisDeviceString[512];
  285. UNICODE_STRING NdisDevice;
  286. NIC_STATISTICS NdisStats;
  287. wcscpy((LPWSTR)NdisDeviceString, (LPWSTR)L"\\Device\\" );
  288. wcscat((LPWSTR)NdisDeviceString, IfDeviceName );
  289. ZeroMemory(&NdisStats, sizeof(NdisStats));
  290. NdisStats.Size = sizeof(NdisStats);
  291. RtlInitUnicodeString(&NdisDevice, (LPWSTR)NdisDeviceString);
  292. if( FALSE == NdisQueryStatistics(&NdisDevice, &NdisStats) ) {
  293. ULONG Error;
  294. //
  295. // Could not get statistics.. use default answer.
  296. //
  297. Error = GetLastError();
  298. if( ERROR_NOT_READY == Error ) {
  299. *fDisconnected = TRUE;
  300. return NO_ERROR;
  301. }
  302. return Error;
  303. }
  304. if( NdisStats.MediaState == MEDIA_STATE_DISCONNECTED ) {
  305. *fDisconnected = TRUE;
  306. } else {
  307. *fDisconnected = FALSE;
  308. }
  309. return NO_ERROR;
  310. }
  311. BOOL
  312. IsMediaSenseDisabled(
  313. HKEY RegKey
  314. )
  315. {
  316. LPTSTR regValueName = (LPTSTR)(TEXT ("DisableDHCPMediaSense") );
  317. DWORD regValueData;
  318. DWORD regValueDataType;
  319. DWORD regValueDataLen = sizeof(DWORD);
  320. DWORD Error;
  321. Error = RegQueryValueEx(
  322. RegKey,
  323. regValueName,
  324. NULL,
  325. &regValueDataType,
  326. (LPBYTE)&regValueData,
  327. &regValueDataLen);
  328. return (Error == NO_ERROR) &&
  329. (regValueDataType == REG_DWORD) &&
  330. (regValueData != 0);
  331. }
  332. DWORD
  333. OpenRegKey(
  334. IN LPCWSTR Device,
  335. IN DWORD KeyType,
  336. IN DWORD AccessType,
  337. OUT HKEY *phKey
  338. )
  339. {
  340. DWORD Access;
  341. WCHAR KeyLoc[256];
  342. LPTSTR TcpipParmLoc = (LPTSTR)(TEXT( "SYSTEM\\CurrentControlSet\\Services" )
  343. TEXT( "\\Tcpip\\Parameters" ) );
  344. LPTSTR TcpipLoc = (LPTSTR)(TEXT( "SYSTEM\\CurrentControlSet\\Services" )
  345. TEXT( "\\Tcpip\\Parameters\\Interfaces\\") );
  346. LPTSTR NbtLoc = (LPTSTR)(TEXT("SYSTEM\\CurrentControlSet\\Services")
  347. TEXT("\\Netbt\\Parameters\\Interfaces\\Tcpip_"));
  348. switch (KeyType)
  349. {
  350. case OpenTcpipParmKey:
  351. wcscpy(KeyLoc, TcpipParmLoc);
  352. break;
  353. case OpenTcpipKey:
  354. wcscpy(KeyLoc, TcpipLoc);
  355. wcscat(KeyLoc, Device);
  356. break;
  357. case OpenNbtKey:
  358. wcscpy(KeyLoc, NbtLoc);
  359. wcscat(KeyLoc, Device);
  360. break;
  361. }
  362. Access = KEY_READ;
  363. if( AccessType & OpenKeyForWrite ) Access |= KEY_WRITE;
  364. return RegOpenKeyEx(
  365. HKEY_LOCAL_MACHINE, KeyLoc, 0, Access, phKey );
  366. }
  367. VOID
  368. SecondsToAbsolute(
  369. OUT FILETIME *SysTime,
  370. IN LONGLONG SecondsDifference
  371. )
  372. {
  373. LONGLONG Diff = SecondsDifference;
  374. Diff *= 10000; Diff *= 1000;
  375. GetSystemTimeAsFileTime( SysTime );
  376. (*((LONGLONG UNALIGNED64 *)SysTime)) -= Diff;
  377. }
  378. DWORD
  379. GetDhcpValues(
  380. IN PNETWORK_INFO NetInfo,
  381. IN OUT PINTERFACE_NETWORK_INFO IfInfo,
  382. IN HKEY hKey
  383. )
  384. {
  385. WCHAR ClassId[200];
  386. LPSTR DhcpServer;
  387. DWORD Error, Value, Size, Type;
  388. time_t CurrentTime, Obtained, Expires;
  389. //
  390. // First check if dhcp is enabled
  391. //
  392. do {
  393. Size = sizeof(Value);
  394. Error = RegQueryValueEx(
  395. hKey, (LPTSTR)TEXT("EnableDHCP"), NULL, &Type,
  396. (LPBYTE)&Value, &Size );
  397. if( NO_ERROR != Error ) return Error;
  398. if( Type != REG_DWORD ) return ERROR_INVALID_DATA;
  399. IfInfo->EnableDhcp = (Value != 0 );
  400. } while ( 0 );
  401. //
  402. // Now check for class id
  403. //
  404. do {
  405. Size = sizeof(ClassId);
  406. Error = RegQueryValueExW(
  407. hKey, (LPWSTR)L"DhcpClassId", NULL, &Type, (LPBYTE)ClassId,
  408. &Size );
  409. if( ERROR_FILE_NOT_FOUND == Error ) {
  410. Error = NO_ERROR;
  411. Size = 0;
  412. }
  413. if( NO_ERROR != Error ) return Error;
  414. if( Size == 0 ) break;
  415. if( Type != REG_SZ ) return ERROR_INVALID_DATA;
  416. Size = sizeof(WCHAR)*(1+wcslen(ClassId));
  417. IfInfo->DhcpClassId = New( Size );
  418. if( NULL == IfInfo->DhcpClassId ) return GetLastError();
  419. wcscpy(IfInfo->DhcpClassId, ClassId );
  420. } while( 0 );
  421. //
  422. // Now check if autoconfiguration is enabled
  423. //
  424. if( IfInfo->EnableDhcp ) do {
  425. Size = sizeof(Value);
  426. Error = RegQueryValueEx(
  427. hKey, (LPTSTR)TEXT("IPAutoconfigurationEnabled"),
  428. NULL, &Type, (LPBYTE)&Value, &Size );
  429. if( ERROR_FILE_NOT_FOUND == Error ) {
  430. IfInfo->EnableAutoconfig = NetInfo->GlobalEnableAutoconfig;
  431. } else if( NO_ERROR != Error ) return Error;
  432. else if( REG_DWORD != Type ) return ERROR_INVALID_DATA;
  433. else IfInfo->EnableAutoconfig = (Value != 0 );
  434. } while ( 0 );
  435. //
  436. // Get Dhcp server value
  437. //
  438. if( IfInfo->EnableDhcp ) do {
  439. Size = sizeof(ClassId);
  440. DhcpServer = (LPSTR)ClassId;
  441. Error = RegQueryValueExA(
  442. hKey, "DhcpServer", NULL, &Type,
  443. (LPBYTE)DhcpServer, &Size );
  444. if( ERROR_FILE_NOT_FOUND == Error ) break;
  445. if( NO_ERROR != Error ) return Error;
  446. if( REG_SZ != Type ) return ERROR_INVALID_DATA;
  447. IfInfo->DhcpServer = inet_addr(DhcpServer);
  448. } while( 0 );
  449. //
  450. // Now get lease expired and obtained times
  451. //
  452. CurrentTime = time(NULL);
  453. if( IfInfo->EnableDhcp ) do {
  454. Size = sizeof(Value);
  455. Error = RegQueryValueEx(
  456. hKey, (LPTSTR)TEXT("LeaseObtainedTime"),
  457. NULL, &Type, (LPBYTE)&Value, &Size );
  458. if( ERROR_FILE_NOT_FOUND == Error ) break;
  459. if( NO_ERROR != Error ) return Error;
  460. if( REG_DWORD != Type ) return ERROR_INVALID_DATA;
  461. Obtained = (time_t)Value;
  462. SecondsToAbsolute(
  463. (FILETIME *)(&IfInfo->LeaseObtainedTime),
  464. ((LONGLONG)CurrentTime) - ((LONGLONG)Obtained) );
  465. } while ( 0 );
  466. if( IfInfo->EnableDhcp ) do {
  467. Size = sizeof(Value);
  468. Error = RegQueryValueEx(
  469. hKey, (LPTSTR)TEXT("LeaseTerminatesTime"),
  470. NULL, &Type, (LPBYTE)&Value, &Size );
  471. if( ERROR_FILE_NOT_FOUND == Error ) break;
  472. if( NO_ERROR != Error ) return Error;
  473. if( REG_DWORD != Type ) return ERROR_INVALID_DATA;
  474. Expires = (time_t)Value;
  475. SecondsToAbsolute(
  476. (FILETIME *)(&IfInfo->LeaseExpiresTime),
  477. ((LONGLONG)CurrentTime) - ((LONGLONG)Expires) );
  478. } while ( 0 );
  479. return NO_ERROR;
  480. }
  481. DWORD
  482. GetDnsValues(
  483. IN OUT PINTERFACE_NETWORK_INFO IfInfo,
  484. IN HKEY hKey
  485. )
  486. {
  487. CHAR *Servers = NULL, *Str;
  488. DWORD Error, BufferSize, Size, Type, i, Count, *ThisAddr;
  489. //
  490. // First get DnsSuffix for the interface
  491. //
  492. Size = sizeof(IfInfo->DnsSuffix)/sizeof(WCHAR);
  493. Error = RegQueryValueExW(
  494. hKey, (LPWSTR)L"Domain", NULL, &Type,
  495. (LPBYTE)IfInfo->DnsSuffix, &Size );
  496. if( NO_ERROR != Error ) {
  497. if( ERROR_FILE_NOT_FOUND != Error ) return Error;
  498. Size = 0;
  499. Type = REG_SZ;
  500. }
  501. if( REG_SZ != Type ) return ERROR_INVALID_DATA;
  502. if( 0 == Size || 0 == wcslen(IfInfo->DnsSuffix) ) {
  503. Size = sizeof(IfInfo->DnsSuffix)/sizeof(WCHAR);
  504. Error = RegQueryValueExW(
  505. hKey, (LPWSTR)L"DhcpDomain", NULL, &Type,
  506. (LPBYTE)IfInfo->DnsSuffix, &Size );
  507. if( NO_ERROR != Error ) {
  508. if( ERROR_FILE_NOT_FOUND != Error ) return Error;
  509. Size = 0;
  510. IfInfo->DnsSuffix[0] = L'\0';
  511. }
  512. }
  513. //
  514. // Now attempt to read the DnsServers list
  515. //
  516. BufferSize = 800;
  517. do {
  518. Servers = New( BufferSize );
  519. if( NULL == Servers) return GetLastError();
  520. ZeroMemory(Servers, BufferSize);
  521. Size = BufferSize;
  522. Error = RegQueryValueExA(
  523. hKey, (LPSTR)"NameServer", NULL, &Type, (LPBYTE)Servers,
  524. &Size );
  525. if( NO_ERROR == Error ) {
  526. break;
  527. }
  528. Delete(Servers);
  529. Servers = NULL;
  530. if( ERROR_FILE_NOT_FOUND == Error ) {
  531. Size = 0;
  532. Type = REG_SZ;
  533. break;
  534. }
  535. if (Error != ERROR_MORE_DATA) {
  536. return Error;
  537. }
  538. BufferSize *= 2;
  539. } while(1);
  540. if( REG_SZ != Type ) return ERROR_INVALID_DATA;
  541. if( 0 == Size || NULL == Servers || 0 == strlen(Servers) ) {
  542. if (Servers) Delete(Servers);
  543. BufferSize = 800;
  544. do {
  545. Servers = New( BufferSize );
  546. if( NULL == Servers) return GetLastError();
  547. ZeroMemory(Servers, BufferSize);
  548. Size = BufferSize;
  549. Error = RegQueryValueExA(
  550. hKey, (LPSTR)"DhcpNameServer", NULL, &Type,
  551. (LPBYTE)Servers, &Size );
  552. if( NO_ERROR == Error ) {
  553. break;
  554. }
  555. Delete(Servers);
  556. Servers = NULL;
  557. if( ERROR_FILE_NOT_FOUND == Error ) {
  558. Size = 0;
  559. Type = REG_SZ;
  560. break;
  561. }
  562. if (Error != ERROR_MORE_DATA) {
  563. return Error;
  564. }
  565. BufferSize *= 2;
  566. } while(1);
  567. }
  568. //
  569. // If there are any DNS Servers, convert them to IPaddr
  570. //
  571. if( 0 != Size && NULL != Servers && strlen(Servers) ) {
  572. for( i = 0; i < Size; i ++ ) {
  573. if( Servers[i] == ' ' || Servers[i] == ','
  574. || Servers[i] == ';' ) {
  575. Servers[i] = '\0';
  576. }
  577. }
  578. Servers[Size] = '\0';
  579. Count = 0; Str = (LPSTR)Servers;
  580. while( strlen(Str) ) {
  581. Count ++;
  582. Str += strlen(Str); Str ++;
  583. }
  584. ThisAddr = New( sizeof(IPV4_ADDRESS) * Count );
  585. if( NULL == ThisAddr ) return GetLastError();
  586. IfInfo->DnsServer = ThisAddr;
  587. for (i = 0, Str = (LPSTR)Servers;
  588. *Str != '\0';
  589. Str += strlen(Str) + 1)
  590. {
  591. IfInfo->DnsServer[i] = inet_addr( Str );
  592. if (IfInfo->DnsServer[i] != 0)
  593. i++;
  594. }
  595. IfInfo->nDnsServers = i;
  596. }
  597. if (Servers) {
  598. Delete (Servers);
  599. }
  600. return NO_ERROR;
  601. }
  602. DWORD
  603. GetWinsValues(
  604. IN OUT PINTERFACE_NETWORK_INFO IfInfo,
  605. IN LPCWSTR DeviceName,
  606. IN OUT ULONG *NodeType
  607. )
  608. {
  609. WCHAR NbtDevice[MAX_PATH];
  610. UNICODE_STRING NbtDeviceString;
  611. HANDLE h;
  612. OBJECT_ATTRIBUTES objAttr;
  613. IO_STATUS_BLOCK iosb;
  614. NTSTATUS status;
  615. tWINS_NODE_INFO NodeInfo;
  616. DWORD Count;
  617. INT i;
  618. wcscpy(NbtDevice, (LPWSTR)L"\\Device\\NetBT_Tcpip_");
  619. wcscat(NbtDevice, DeviceName);
  620. RtlInitUnicodeString( &NbtDeviceString, (LPWSTR)NbtDevice );
  621. InitializeObjectAttributes(
  622. &objAttr,
  623. &NbtDeviceString,
  624. OBJ_CASE_INSENSITIVE,
  625. (HANDLE)NULL,
  626. (PSECURITY_DESCRIPTOR)NULL
  627. );
  628. status = NtCreateFile(
  629. &h, SYNCHRONIZE | GENERIC_EXECUTE, &objAttr, &iosb, NULL,
  630. FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE,
  631. FILE_OPEN_IF, 0, NULL, 0 );
  632. if (!NT_SUCCESS(status)) {
  633. DWORD w32error = RtlNtStatusToDosError( status );
  634. IfInfo->EnableNbtOverTcpip = FALSE;
  635. (*NodeType) = NodeTypeUnknown;
  636. return w32error == ERROR_FILE_NOT_FOUND ? NO_ERROR : w32error;
  637. }
  638. status = NtDeviceIoControlFile(
  639. h, NULL, NULL, NULL, &iosb, IOCTL_NETBT_GET_WINS_ADDR,
  640. NULL, 0, (PVOID)&NodeInfo, sizeof(NodeInfo) );
  641. if (status == STATUS_PENDING) {
  642. status = NtWaitForSingleObject(h, TRUE, NULL);
  643. if (NT_SUCCESS(status)) {
  644. status = iosb.Status;
  645. }
  646. }
  647. NtClose(h);
  648. if (!NT_SUCCESS(status)) {
  649. return RtlNtStatusToDosError( status );
  650. }
  651. //
  652. // for some reason, NetBT returns the addresses in low-byte order. We have
  653. // to swap them
  654. //
  655. Count = 0;
  656. for( i = 0; i < 2+MAX_NUM_OTHER_NAME_SERVERS; i ++ ) {
  657. NodeInfo.AllNameServers[i] = htonl(NodeInfo.AllNameServers[i]);
  658. if( LOCAL_WINS_ADDRESS == NodeInfo.AllNameServers[i] ||
  659. INADDR_ANY == NodeInfo.AllNameServers[i] ||
  660. INADDR_BROADCAST == NodeInfo.AllNameServers[i] ) {
  661. break;
  662. }
  663. Count ++;
  664. }
  665. for ( i = IfInfo->nIpAddresses-1; i >= 0; i--)
  666. if (IfInfo->IpAddress[i] != 0)
  667. break;
  668. if (Count > (DWORD)(NodeInfo.NumOtherServers + 2)) {
  669. Count = (DWORD)(NodeInfo.NumOtherServers + 2);
  670. }
  671. if( i != -1 && Count != 0 ) {
  672. IfInfo->WinsServer = New( sizeof(IPV4_ADDRESS)*Count );
  673. if( NULL == IfInfo->WinsServer ) return GetLastError();
  674. IfInfo->nWinsServers = Count;
  675. for( i = 0; (DWORD)i < Count; i ++ ) {
  676. IfInfo->WinsServer[i] = NodeInfo.AllNameServers[i];
  677. }
  678. }
  679. IfInfo->EnableNbtOverTcpip = NodeInfo.NetbiosEnabled;
  680. #define NODE_TYPE_BROADCAST 1
  681. #define NODE_TYPE_PEER_PEER 2
  682. #define NODE_TYPE_MIXED 4
  683. #define NODE_TYPE_HYBRID 8
  684. switch( NodeInfo.NodeType ) {
  685. case NODE_TYPE_BROADCAST : (*NodeType) = NodeTypeBroadcast; break;
  686. case NODE_TYPE_PEER_PEER : (*NodeType) = NodeTypePeerPeer; break;
  687. case NODE_TYPE_MIXED : (*NodeType) = NodeTypeMixed; break;
  688. case NODE_TYPE_HYBRID : (*NodeType) = NodeTypeHybrid ; break;
  689. default: (*NodeType) = NodeTypeUnknown; break;
  690. }
  691. return NO_ERROR;
  692. }
  693. DWORD
  694. GetAddressValues(
  695. IN OUT PINTERFACE_NETWORK_INFO IfInfo,
  696. IN PMIB_IPADDRTABLE AddrTable,
  697. IN ULONG IfIndex
  698. )
  699. {
  700. DWORD i, Count;
  701. if( NULL == AddrTable ) return ERROR_NOT_FOUND;
  702. Count = 0;
  703. for( i = 0; i < AddrTable->dwNumEntries ; i ++ ) {
  704. if( AddrTable->table[i].dwIndex == IfIndex ) {
  705. Count ++;
  706. }
  707. }
  708. if( 0 == Count ) return NO_ERROR;
  709. //
  710. // Allocate space for this
  711. //
  712. IfInfo->IpAddress = New( sizeof(IPV4_ADDRESS)*Count );
  713. if( NULL == IfInfo->IpAddress ) return GetLastError();
  714. IfInfo->IpMask = New( sizeof(IPV4_ADDRESS)*Count );
  715. if( NULL == IfInfo->IpMask ) return GetLastError();
  716. IfInfo->nIpAddresses = IfInfo->nIpMasks = Count;
  717. //
  718. // First add the primary addresses
  719. //
  720. Count = 0;
  721. for( i = 0; i < AddrTable->dwNumEntries; i ++ ) {
  722. if( AddrTable->table[i].dwIndex != IfIndex ) continue;
  723. if( !(AddrTable->table[i].wType & MIB_IPADDR_PRIMARY)) continue;
  724. IfInfo->IpAddress[Count] = AddrTable->table[i].dwAddr;
  725. IfInfo->IpMask[Count] = AddrTable->table[i].dwMask;
  726. Count ++;
  727. }
  728. //
  729. // Now add just the non-primary addresses
  730. //
  731. for( i = 0; i < AddrTable->dwNumEntries; i ++ ) {
  732. if( AddrTable->table[i].dwIndex != IfIndex ) continue;
  733. if(AddrTable->table[i].wType & MIB_IPADDR_PRIMARY) continue;
  734. IfInfo->IpAddress[Count] = AddrTable->table[i].dwAddr;
  735. IfInfo->IpMask[Count] = AddrTable->table[i].dwMask;
  736. Count ++;
  737. }
  738. return NO_ERROR;
  739. }
  740. DWORD
  741. GetRouteValues(
  742. IN OUT PINTERFACE_NETWORK_INFO IfInfo,
  743. IN PMIB_IPFORWARDTABLE RouteTable,
  744. IN ULONG IfIndex
  745. )
  746. {
  747. DWORD i, Count;
  748. if( NULL == RouteTable ) return ERROR_NOT_FOUND;
  749. Count = 0;
  750. for( i = 0; i < RouteTable->dwNumEntries; i ++ ) {
  751. if( RouteTable->table[i].dwForwardIfIndex == IfIndex &&
  752. INADDR_ANY == RouteTable->table[i].dwForwardDest &&
  753. MIB_IPROUTE_TYPE_INVALID !=
  754. RouteTable->table[i].dwForwardType ) {
  755. Count ++;
  756. }
  757. }
  758. if( 0 == Count ) return NO_ERROR;
  759. IfInfo->Router = New( sizeof(IPV4_ADDRESS)*Count);
  760. if( NULL == IfInfo->Router ) return GetLastError();
  761. IfInfo->nRouters = Count;
  762. Count = 0;
  763. for( i = 0; i < RouteTable->dwNumEntries; i ++ ) {
  764. if( RouteTable->table[i].dwForwardIfIndex == IfIndex &&
  765. INADDR_ANY == RouteTable->table[i].dwForwardDest &&
  766. MIB_IPROUTE_TYPE_INVALID !=
  767. RouteTable->table[i].dwForwardType ) {
  768. IfInfo->Router[Count] = RouteTable->table[i].dwForwardNextHop;
  769. Count ++;
  770. }
  771. }
  772. return NO_ERROR;
  773. }
  774. VOID
  775. IncrementCount(
  776. IN IPV6_INFO_ROUTE_TABLE *RTE,
  777. IN PVOID Arg1,
  778. IN OUT PVOID Count
  779. )
  780. {
  781. PIP_ADAPTER_ADDRESSES If = (PIP_ADAPTER_ADDRESSES)Arg1;
  782. if ((RTE->This.PrefixLength == 0) &&
  783. (RTE->This.Neighbor.IF.Index == If->Ipv6IfIndex)) {
  784. (*(ULONG *)Count)++;
  785. }
  786. }
  787. VOID
  788. AddRouter(
  789. IN IPV6_INFO_ROUTE_TABLE *RTE,
  790. IN PVOID Arg1,
  791. IN OUT PVOID Arg2
  792. )
  793. {
  794. PIP_ADAPTER_ADDRESSES If = (PIP_ADAPTER_ADDRESSES)Arg1;
  795. PINTERFACE_NETWORK_INFO pIfInfo = (PINTERFACE_NETWORK_INFO)Arg2;
  796. ULONG Index;
  797. LPSOCKADDR_IN6 Addr;
  798. if (RTE->This.PrefixLength != 0) {
  799. return;
  800. }
  801. if (RTE->This.Neighbor.IF.Index != If->Ipv6IfIndex) {
  802. return;
  803. }
  804. //
  805. // We now have a default router to add to the list.
  806. //
  807. Index = pIfInfo->nIpv6Routers++;
  808. Addr = &pIfInfo->Ipv6Router[Index];
  809. Addr->sin6_family = AF_INET6;
  810. Addr->sin6_addr = RTE->This.Neighbor.Address;
  811. Addr->sin6_port = 0;
  812. if (IN6_IS_ADDR_LINKLOCAL(&Addr->sin6_addr)) {
  813. Addr->sin6_scope_id = If->ZoneIndices[ScopeLevelLink];
  814. } else if (IN6_IS_ADDR_SITELOCAL(&Addr->sin6_addr)) {
  815. Addr->sin6_scope_id = If->ZoneIndices[ScopeLevelSite];
  816. } else {
  817. Addr->sin6_scope_id = 0;
  818. }
  819. }
  820. ULONG
  821. ForEachRoute(
  822. IN VOID (*Func)(IPV6_INFO_ROUTE_TABLE *, PVOID, PVOID),
  823. IN PVOID Arg1,
  824. IN OUT PVOID Arg2
  825. )
  826. {
  827. IPV6_QUERY_ROUTE_TABLE Query, NextQuery;
  828. IPV6_INFO_ROUTE_TABLE RTE;
  829. ULONG BytesReturned;
  830. static HANDLE Ipv6Handle = INVALID_HANDLE_VALUE;
  831. if (Ipv6Handle == INVALID_HANDLE_VALUE) {
  832. //
  833. // Open a handle to the IPv6 device on our first invocation.
  834. // Keep it open until the process terminates, since we'll
  835. // terminate once we've generated the output.
  836. //
  837. Ipv6Handle = CreateFileW(WIN_IPV6_DEVICE_NAME,
  838. 0,
  839. FILE_SHARE_READ | FILE_SHARE_WRITE,
  840. NULL, // security attributes
  841. OPEN_EXISTING,
  842. 0, // flags & attributes
  843. NULL); // template file
  844. }
  845. NextQuery.Neighbor.IF.Index = 0;
  846. for (;;) {
  847. Query = NextQuery;
  848. if (!DeviceIoControl(Ipv6Handle, IOCTL_IPV6_QUERY_ROUTE_TABLE,
  849. &Query, sizeof Query,
  850. &RTE, sizeof RTE, &BytesReturned,
  851. NULL)) {
  852. return GetLastError();
  853. }
  854. NextQuery = RTE.Next;
  855. if (Query.Neighbor.IF.Index != 0) {
  856. RTE.This = Query;
  857. (*Func)(&RTE, Arg1, Arg2);
  858. }
  859. if (NextQuery.Neighbor.IF.Index == 0)
  860. break;
  861. }
  862. return NO_ERROR;
  863. }
  864. VOID
  865. AddIpv6PerInterfaceInfo(
  866. IN DWORD IfIndex,
  867. IN PINTERFACE_NETWORK_INFO pIfInfo,
  868. IN PIP_ADAPTER_ADDRESSES IfList
  869. )
  870. {
  871. PIP_ADAPTER_ADDRESSES If;
  872. PIP_ADAPTER_UNICAST_ADDRESS Addr;
  873. PIP_ADAPTER_DNS_SERVER_ADDRESS Dns;
  874. ULONG Count, BytesReturned;
  875. LPSOCKADDR_IN6 SockAddr;
  876. IPV6_QUERY_ROUTE_TABLE Query, NextQuery;
  877. IPV6_INFO_ROUTE_TABLE RTE;
  878. //
  879. // Find matching entry in the IPv6 interface list.
  880. //
  881. for (If = IfList; If; If = If->Next) {
  882. if (IfIndex == If->IfIndex) {
  883. break;
  884. }
  885. }
  886. if ((If == NULL) || (If->Ipv6IfIndex == 0)) {
  887. return;
  888. }
  889. //
  890. // Append IPv6 unicast addresses.
  891. //
  892. Count = 0;
  893. for (Addr = If->FirstUnicastAddress; Addr; Addr = Addr->Next) {
  894. if ((Addr->Address.lpSockaddr->sa_family == AF_INET6) &&
  895. (Addr->DadState >= IpDadStateDeprecated)) {
  896. Count++;
  897. }
  898. }
  899. pIfInfo->Ipv6Address = New(Count * sizeof(SOCKADDR_IN6));
  900. if (pIfInfo->Ipv6Address != NULL) {
  901. Count = 0;
  902. for (Addr = If->FirstUnicastAddress; Addr; Addr = Addr->Next) {
  903. if ((Addr->Address.lpSockaddr->sa_family == AF_INET6) &&
  904. (Addr->DadState >= IpDadStateDeprecated)) {
  905. CopyMemory(&pIfInfo->Ipv6Address[Count++],
  906. Addr->Address.lpSockaddr,
  907. sizeof(SOCKADDR_IN6));
  908. }
  909. }
  910. pIfInfo->nIpv6Addresses = Count;
  911. } else {
  912. pIfInfo->nIpv6Addresses = 0;
  913. }
  914. //
  915. // Append IPv6 DNS server addresses.
  916. //
  917. Count = 0;
  918. for (Dns = If->FirstDnsServerAddress; Dns; Dns = Dns->Next) {
  919. if (Dns->Address.lpSockaddr->sa_family == AF_INET6) {
  920. Count++;
  921. }
  922. }
  923. pIfInfo->Ipv6DnsServer = New(Count * sizeof(SOCKADDR_IN6));
  924. if (pIfInfo->Ipv6DnsServer != NULL) {
  925. Count = 0;
  926. for (Dns = If->FirstDnsServerAddress; Dns; Dns = Dns->Next) {
  927. if (Dns->Address.lpSockaddr->sa_family == AF_INET6) {
  928. CopyMemory(&pIfInfo->Ipv6DnsServer[Count++],
  929. Dns->Address.lpSockaddr,
  930. sizeof(SOCKADDR_IN6));
  931. }
  932. }
  933. pIfInfo->nIpv6DnsServers = Count;
  934. } else {
  935. pIfInfo->nIpv6DnsServers = 0;
  936. }
  937. //
  938. // Append IPv6 default router addresses.
  939. //
  940. Count = 0;
  941. ForEachRoute(IncrementCount, If, &Count);
  942. pIfInfo->nIpv6Routers = 0;
  943. pIfInfo->Ipv6Router = New(Count * sizeof(SOCKADDR_IN6));
  944. if (pIfInfo->Ipv6Router != NULL) {
  945. ForEachRoute(AddRouter, If, pIfInfo);
  946. }
  947. }
  948. DWORD
  949. GetPerInterfaceInfo(
  950. IN OUT PNETWORK_INFO NetInfo,
  951. OUT PINTERFACE_NETWORK_INFO *pIfInfo,
  952. IN PMIB_IFROW IfRow,
  953. IN PIP_INTERFACE_INFO InterfaceInfo,
  954. IN PIP_INTERFACE_NAME_INFO IfNameInfo,
  955. IN ULONG IfNameCount,
  956. IN PMIB_IPADDRTABLE AddrTable,
  957. IN PMIB_IPFORWARDTABLE RouteTable,
  958. IN PIP_ADAPTER_ADDRESSES IfList,
  959. IN OUT DWORD *InternalError
  960. )
  961. {
  962. DWORD Error, NodeType;
  963. PINTERFACE_NETWORK_INFO IfInfo = New( sizeof(*IfInfo) );
  964. GUID IfGuid;
  965. LPWSTR IfDeviceName;
  966. HKEY TcpipKey = NULL;
  967. HKEY TcpipParmKey = NULL;
  968. if( NULL == IfInfo ) return GetLastError();
  969. (*pIfInfo) = IfInfo;
  970. ZeroMemory( &IfGuid, sizeof(IfGuid) );
  971. IfDeviceName = NULL;
  972. GetInterfaceGuidAndDeviceName(
  973. IfRow, InterfaceInfo, IfNameInfo, IfNameCount,
  974. &IfGuid, &IfDeviceName );
  975. if( NULL == IfDeviceName ) {
  976. (*InternalError) = InterfaceUnknownTcpipDevice;
  977. return ERROR_NOT_FOUND;
  978. }
  979. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\tDeviceName: %ws\n", IfDeviceName));
  980. wcscpy(IfInfo->DeviceGuidName, IfDeviceName );
  981. Error = OpenRegKey(
  982. IfDeviceName, OpenTcpipKey, OpenKeyForRead, &TcpipKey );
  983. if (Error == NO_ERROR)
  984. Error = OpenRegKey(
  985. IfDeviceName, OpenTcpipParmKey, OpenKeyForRead, &TcpipParmKey );
  986. if( NO_ERROR != Error ) {
  987. (*InternalError) = InterfaceOpenTcpipKeyReadFailure;
  988. }
  989. while (Error == NO_ERROR)
  990. {
  991. Error = MapIfType( IfInfo, IfRow->dwType);
  992. CheckError( InterfaceUnknownType );
  993. IfInfo->PhysicalNameLength = IfRow->dwPhysAddrLen;
  994. CopyMemory(
  995. IfInfo->PhysicalName,IfRow->bPhysAddr,
  996. IfRow->dwPhysAddrLen );
  997. Error = MapFriendlyAndConnectionNames(
  998. IfInfo, IfRow, IfGuid, IfDeviceName );
  999. CheckError( InterfaceUnknownFriendlyName );
  1000. if( IfRow->dwType == IF_TYPE_PPP ||
  1001. IfRow->dwType == IF_TYPE_TUNNEL ||
  1002. IsMediaSenseDisabled(TcpipParmKey)) {
  1003. IfInfo->MediaDisconnected = FALSE;
  1004. } else {
  1005. Error = GetMediaStatus(
  1006. IfDeviceName, &IfInfo->MediaDisconnected );
  1007. CheckError( InterfaceUnknownMediaStatus );
  1008. }
  1009. Error = GetDhcpValues( NetInfo, IfInfo, TcpipKey );
  1010. CheckError( InterfaceDhcpValuesFailure );
  1011. Error = GetDnsValues( IfInfo, TcpipKey );
  1012. CheckError( InterfaceDnsValuesFailure );
  1013. Error = GetAddressValues(
  1014. IfInfo, AddrTable, IfRow->dwIndex );
  1015. CheckError( InterfaceAddressValuesFailure );
  1016. Error = GetRouteValues(
  1017. IfInfo, RouteTable, IfRow->dwIndex );
  1018. CheckError( InterfaceRouteValuesFailure );
  1019. Error = GetWinsValues( IfInfo, IfDeviceName, &NodeType );
  1020. CheckError( InterfaceWinsValuesFailure );
  1021. //
  1022. // Now set the node type as well
  1023. //
  1024. NetInfo->NodeType = NodeType;
  1025. //
  1026. // Now write out if autoconfig is active. The way this
  1027. // works is to check if dhcp is enabled and dhcpserver
  1028. // address is zero or all ones
  1029. //
  1030. if( IfInfo->EnableDhcp && IfInfo->EnableAutoconfig
  1031. && IfInfo->nIpAddresses
  1032. && IfInfo->IpAddress[0] != INADDR_ANY
  1033. && ( IfInfo->DhcpServer == INADDR_BROADCAST ||
  1034. IfInfo->DhcpServer == INADDR_ANY ) ) {
  1035. IfInfo->AutoconfigActive = TRUE;
  1036. }
  1037. break;
  1038. }
  1039. if (TcpipKey != NULL)
  1040. RegCloseKey( TcpipKey );
  1041. if (TcpipParmKey != NULL)
  1042. RegCloseKey( TcpipParmKey );
  1043. AddIpv6PerInterfaceInfo( IfRow->dwIndex, IfInfo, IfList );
  1044. return Error;
  1045. }
  1046. DWORD
  1047. GetIpv6OnlyPerInterfaceInfo(
  1048. OUT PINTERFACE_NETWORK_INFO *pIfInfo,
  1049. IN PIP_ADAPTER_ADDRESSES If
  1050. )
  1051. {
  1052. DWORD Error = NO_ERROR;
  1053. PINTERFACE_NETWORK_INFO IfInfo;
  1054. IfInfo = New( sizeof(*IfInfo) );
  1055. if( NULL == IfInfo ) return GetLastError();
  1056. (*pIfInfo) = IfInfo;
  1057. ZeroMemory(IfInfo, sizeof(*IfInfo));
  1058. MapIfType(IfInfo, If->IfType);
  1059. IfInfo->PhysicalNameLength = If->PhysicalAddressLength;
  1060. CopyMemory(IfInfo->PhysicalName, If->PhysicalAddress,
  1061. If->PhysicalAddressLength);
  1062. //
  1063. // INTERFACE_NETWORK_INFO has weird field names compared to
  1064. // IP_ADAPTER_ADDRESSES. The former puts the description in its
  1065. // "friendly name" field.
  1066. //
  1067. IfInfo->FriendlyName = New((wcslen(If->Description) + 1) * sizeof(WCHAR));
  1068. if( NULL != IfInfo->FriendlyName ) {
  1069. wcscpy(IfInfo->FriendlyName, If->Description);
  1070. }
  1071. IfInfo->ConnectionName = New((wcslen(If->FriendlyName) + 1) * sizeof(WCHAR));
  1072. if( NULL != IfInfo->ConnectionName ) {
  1073. wcscpy(IfInfo->ConnectionName, If->FriendlyName);
  1074. }
  1075. IfInfo->MediaDisconnected = (If->OperStatus == IfOperStatusLowerLayerDown);
  1076. IfInfo->EnableAutoconfig = TRUE;
  1077. wcscpy(IfInfo->DnsSuffix, If->DnsSuffix);
  1078. AddIpv6PerInterfaceInfo(0, IfInfo, If);
  1079. return Error;
  1080. }
  1081. BOOL
  1082. GetGlobalTcpipAutoconfigFlag()
  1083. {
  1084. HKEY hKey;
  1085. BOOL rtn;
  1086. DWORD Error;
  1087. DWORD Type, Value, Size;
  1088. rtn = TRUE;
  1089. Error = OpenRegKey(
  1090. NULL, OpenTcpipParmKey, OpenKeyForRead, &hKey );
  1091. if (Error != NO_ERROR) {
  1092. return TRUE;
  1093. }
  1094. Error = RegQueryValueEx(
  1095. hKey, (LPTSTR)TEXT("IPAutoconfigurationEnabled"),
  1096. NULL, &Type, (LPBYTE)&Value, &Size );
  1097. if (Error == NO_ERROR && Type == REG_DWORD) {
  1098. rtn = (Value)? TRUE: FALSE;
  1099. }
  1100. RegCloseKey( hKey );
  1101. return rtn;
  1102. }
  1103. ULONG
  1104. CountIpv6OnlyInterfaces(
  1105. IN PIP_ADAPTER_ADDRESSES IfList
  1106. )
  1107. {
  1108. PIP_ADAPTER_ADDRESSES If;
  1109. ULONG Count = 0;
  1110. for (If = IfList; If; If = If->Next) {
  1111. if ((If->IfIndex == 0) && (If->Ipv6IfIndex != 0) &&
  1112. (If->IfType != IF_TYPE_SOFTWARE_LOOPBACK) &&
  1113. ((If->IfType != IF_TYPE_TUNNEL) || (If->FirstUnicastAddress != NULL))) {
  1114. Count++;
  1115. }
  1116. }
  1117. return Count;
  1118. }
  1119. DWORD
  1120. GetNetworkInformation(
  1121. OUT PNETWORK_INFO *pNetInfo,
  1122. IN OUT DWORD *InternalError
  1123. )
  1124. {
  1125. DWORD Size, Length, Error, i, j, k, IfNameCount, IfCount;
  1126. BOOL fSuccess;
  1127. PNETWORK_INFO NetInfo;
  1128. MIB_IPSTATS IpStats;
  1129. FIXED_INFO *FixedInfo;
  1130. PDNS_SEARCH_INFORMATION SearchInfo;
  1131. PMIB_IFTABLE pIfTable;
  1132. PIP_INTERFACE_INFO InterfaceInfo;
  1133. PIP_INTERFACE_NAME_INFO IfNameInfo;
  1134. PMIB_IPADDRTABLE AddrTable;
  1135. PMIB_IPFORWARDTABLE RouteTable;
  1136. PIP_ADAPTER_ADDRESSES IfList, If;
  1137. ULONG BufferLength, Flags;
  1138. //
  1139. // Allocate main structure
  1140. //
  1141. (*InternalError) = NO_ERROR;
  1142. (*pNetInfo) = NetInfo = New( sizeof(NETWORK_INFO ) );
  1143. if( NULL == NetInfo ) return GetLastError();
  1144. Flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST;
  1145. GetAdaptersAddresses(AF_UNSPEC, Flags, NULL, NULL, &BufferLength);
  1146. IfList = (PIP_ADAPTER_ADDRESSES)New(BufferLength);
  1147. if( NULL == IfList ) return GetLastError();
  1148. Error = GetAdaptersAddresses(AF_UNSPEC, Flags, NULL, IfList, &BufferLength);
  1149. if( Error != NO_ERROR ) {
  1150. Delete(IfList);
  1151. return Error;
  1152. }
  1153. SearchInfo = NULL;
  1154. pIfTable = NULL;
  1155. InterfaceInfo = NULL;
  1156. IfNameInfo = NULL;
  1157. AddrTable = NULL;
  1158. RouteTable = NULL;
  1159. do {
  1160. //
  1161. // Fill important fields of the main structure
  1162. //
  1163. Length = MaxHostNameSize;
  1164. fSuccess = GetComputerNameExW(
  1165. ComputerNameDnsHostname, NetInfo->HostName, &Length );
  1166. CheckBoolError( GlobalHostNameFailure );
  1167. Length = MaxDomainNameSize;
  1168. fSuccess = GetComputerNameExW(
  1169. ComputerNameDnsDomain, NetInfo->DomainName, &Length );
  1170. if( FALSE == fSuccess ) NetInfo->DomainName[0] = L'\0';
  1171. Error = GetIpStatistics( &IpStats );
  1172. CheckError( GlobalEnableRouterFailure );
  1173. NetInfo->EnableRouting = (
  1174. IpStats.dwForwarding == MIB_IP_FORWARDING );
  1175. //
  1176. // EnableProxy and EnableDnsForNetbios both come from the
  1177. // registry directly? We will use the GetNetworkParams
  1178. // API for this instead.
  1179. //
  1180. Size = 1000;
  1181. FixedInfo = NULL;
  1182. do {
  1183. Delete(FixedInfo);
  1184. FixedInfo = (PFIXED_INFO)New(Size);
  1185. if (NULL == FixedInfo) {
  1186. Error = ERROR_NOT_ENOUGH_MEMORY;
  1187. break;
  1188. }
  1189. Length = Size;
  1190. Error = GetNetworkParams( FixedInfo, &Length );
  1191. Size = Length;
  1192. } while (Error == ERROR_BUFFER_OVERFLOW);
  1193. CheckError( GlobalEnableDnsFailure );
  1194. NetInfo->EnableProxy = FixedInfo->EnableProxy;
  1195. NetInfo->EnableDnsForNetbios = FixedInfo->EnableDns;
  1196. Delete(FixedInfo);
  1197. FixedInfo = NULL;
  1198. //
  1199. // Now get the suffix search list from Dns
  1200. //
  1201. SearchInfo = DnsQueryConfigAlloc(
  1202. DnsConfigSearchInformation,
  1203. NULL );
  1204. if( NULL != SearchInfo ) {
  1205. Length = 0;
  1206. for( i = 0; i < SearchInfo->cNameCount ; i ++ ) {
  1207. Length += MultiByteToWideChar(
  1208. CP_UTF8, 0, SearchInfo->aSearchListNames[i],
  1209. -1, NULL, 0 );
  1210. }
  1211. if( Length != 0 ) {
  1212. Length ++;
  1213. NetInfo->SuffixSearchList = New( sizeof(WCHAR)*Length);
  1214. if( NULL == NetInfo->SuffixSearchList ) {
  1215. Error = GetLastError(); break;
  1216. }
  1217. Size = Length; Length = 0;
  1218. for( i = 0; i < SearchInfo->cNameCount ; i ++ ) {
  1219. Length += MultiByteToWideChar(
  1220. CP_UTF8, 0, SearchInfo->aSearchListNames[i],
  1221. -1, &NetInfo->SuffixSearchList[Length],
  1222. Size - Length );
  1223. }
  1224. }
  1225. }
  1226. //
  1227. // Now go for the interface specific stuff.
  1228. //
  1229. Error = NhpAllocateAndGetInterfaceInfoFromStack(
  1230. &IfNameInfo, &IfNameCount, TRUE, GetProcessHeap(),
  1231. HEAP_NO_SERIALIZE );
  1232. CheckError( GlobalIfNameInfoFailure );
  1233. #ifdef __IPCFG_ENABLE_LOG__
  1234. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("NhpAllocateAndGetInterfaceInfoFromStack returns 0x%lx (%d) %d Interfaces\n",
  1235. Error, Error, IfNameCount));
  1236. for (i = 0; i < IfNameCount; i++) {
  1237. LPWSTR DeviceGuid, InterfaceGuid;
  1238. DeviceGuid = InterfaceGuid = NULL;
  1239. UuidToStringW(&IfNameInfo[i].DeviceGuid, &DeviceGuid);
  1240. UuidToStringW(&IfNameInfo[i].InterfaceGuid, &InterfaceGuid);
  1241. if (DeviceGuid == NULL || InterfaceGuid == NULL) {
  1242. if (DeviceGuid) RpcStringFree(&DeviceGuid);
  1243. if (InterfaceGuid) RpcStringFree(&InterfaceGuid);
  1244. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\t%2d. Index=0x%x DeviceGUID=<fail> InterfaceGUID=<fail>\n",
  1245. i + 1, IfNameInfo[i].Index));
  1246. } else {
  1247. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\t%2d. Index=0x%x\n\t DeviceGUID=%ws\n\t InterfaceGUID=%ws\n",
  1248. i + 1, IfNameInfo[i].Index, DeviceGuid, InterfaceGuid));
  1249. RpcStringFree(&DeviceGuid);
  1250. RpcStringFree(&InterfaceGuid);
  1251. }
  1252. }
  1253. #endif
  1254. Size = 1000;
  1255. do {
  1256. Delete( RouteTable );
  1257. RouteTable = New( Size );
  1258. if( NULL == RouteTable ) {
  1259. Error = GetLastError();
  1260. } else {
  1261. Error = GetIpForwardTable(
  1262. RouteTable, &Size, FALSE );
  1263. }
  1264. } while( ERROR_INSUFFICIENT_BUFFER == Error );
  1265. #ifdef __IPCFG_ENABLE_LOG__
  1266. if (RouteTable) {
  1267. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("GetIpForwardTable returns 0x%lx (%d) %d routing entries\n",
  1268. Error, Error, RouteTable->dwNumEntries));
  1269. for (i = 0; i < RouteTable->dwNumEntries; i++) {
  1270. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\t%2d. Index=0x%x Next Hop=%s ",
  1271. i + 1, RouteTable->table[i].dwForwardIfIndex,
  1272. inet_ntoa(*(struct in_addr*)&RouteTable->table[i].dwForwardNextHop)));
  1273. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("Mask=%s Type=0x%x\n",
  1274. inet_ntoa(*(struct in_addr*)&RouteTable->table[i].dwForwardMask),
  1275. RouteTable->table[i].dwForwardType));
  1276. }
  1277. }
  1278. #endif
  1279. Size = 1000;
  1280. do {
  1281. Delete( AddrTable );
  1282. AddrTable = New( Size );
  1283. if( NULL == AddrTable ) {
  1284. Error = GetLastError();
  1285. } else {
  1286. Error = GetIpAddrTable( AddrTable, &Size, TRUE );
  1287. }
  1288. } while( ERROR_INSUFFICIENT_BUFFER == Error );
  1289. CheckError( GlobalAddrTableFailure );
  1290. #ifdef __IPCFG_ENABLE_LOG__
  1291. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("GetIpAddrTable returns 0x%lx (%d) %d IP entries\n",
  1292. Error, Error, AddrTable->dwNumEntries));
  1293. for (i = 0; i < AddrTable->dwNumEntries; i++) {
  1294. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\t%2d. Index=0x%x IP=%s",
  1295. i + 1, AddrTable->table[i].dwIndex,
  1296. inet_ntoa(*(struct in_addr*)&AddrTable->table[i].dwAddr)));
  1297. IPCFG_TRACE(IPCFG_TRACE_TCPIP, (" mask=%s Type=0x%x\n",
  1298. inet_ntoa(*(struct in_addr*)&AddrTable->table[i].dwMask),
  1299. AddrTable->table[i].wType));
  1300. }
  1301. #endif
  1302. Size = 1000;
  1303. do {
  1304. Delete( pIfTable );
  1305. pIfTable = New( Size );
  1306. if( NULL == pIfTable ) {
  1307. Error = GetLastError();
  1308. } else {
  1309. Error = GetIfTable( pIfTable, &Size, TRUE );
  1310. }
  1311. } while( ERROR_INSUFFICIENT_BUFFER == Error );
  1312. CheckError( GlobalIfTableFailure );
  1313. #ifdef __IPCFG_ENABLE_LOG__
  1314. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("GetIfTable returns 0x%lx (%d) %d Interfaces\n",
  1315. Error, Error, pIfTable->dwNumEntries));
  1316. for( i = 0; i < pIfTable->dwNumEntries; i ++ ) {
  1317. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\t%2d. IfIndex=0x%x Name=%ws IfType=0x%x\n",
  1318. i + 1, pIfTable->table[i].dwIndex, pIfTable->table[i].wszName, pIfTable->table[i].dwType));
  1319. }
  1320. #endif
  1321. Size = 1000;
  1322. do {
  1323. Delete( InterfaceInfo );
  1324. InterfaceInfo = New( Size );
  1325. if( NULL == InterfaceInfo ) {
  1326. Error = GetLastError();
  1327. } else {
  1328. Error = GetInterfaceInfo( InterfaceInfo, &Size );
  1329. }
  1330. } while( ERROR_INSUFFICIENT_BUFFER == Error );
  1331. CheckError( GlobalIfInfoFailure );
  1332. #ifdef __IPCFG_ENABLE_LOG__
  1333. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("GetInterfaceInfo returns 0x%lx (%d) %d Interfaces\n",
  1334. Error, Error, InterfaceInfo->NumAdapters));
  1335. for( i = 0; i < (DWORD)InterfaceInfo->NumAdapters; i ++ ) {
  1336. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\t%2d. Index=0x%x\n\t Name=%ws\n",
  1337. i + 1, InterfaceInfo->Adapter[i].Index, InterfaceInfo->Adapter[i].Name));
  1338. }
  1339. #endif
  1340. //
  1341. // Get global AutoConfig settings
  1342. //
  1343. NetInfo->GlobalEnableAutoconfig = GetGlobalTcpipAutoconfigFlag();
  1344. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("GlobalAutoConfigFlag: %d\n", NetInfo->GlobalEnableAutoconfig));
  1345. //
  1346. // Check for number of interfaces and allocate required
  1347. // space in the IfInfo field
  1348. //
  1349. IfCount = pIfTable->dwNumEntries;
  1350. IfCount += CountIpv6OnlyInterfaces(IfList);
  1351. if( IfCount > 1 ) {
  1352. NetInfo->nInterfaces = IfCount-1;
  1353. NetInfo->IfInfo = New(
  1354. NetInfo->nInterfaces * sizeof(PVOID) );
  1355. if( NULL == NetInfo->IfInfo ) {
  1356. Error = GetLastError(); break;
  1357. }
  1358. //
  1359. // First add interfaces running IPv4.
  1360. //
  1361. j = 0;
  1362. for( i = 0; i < pIfTable->dwNumEntries ; i ++ ) {
  1363. BOOL fFound = FALSE;
  1364. for( k = 0; k <
  1365. (DWORD)InterfaceInfo->NumAdapters; k ++ ) {
  1366. if( pIfTable->table[i].dwIndex ==
  1367. InterfaceInfo->Adapter[k].Index ) {
  1368. fFound = TRUE;
  1369. break;
  1370. }
  1371. }
  1372. if( fFound &&
  1373. pIfTable->table[i].dwType != IF_TYPE_SOFTWARE_LOOPBACK ) {
  1374. IPCFG_TRACE(IPCFG_TRACE_TCPIP, ("\n\n************ GetPerInterfaceInfo for "
  1375. "IfIndex=0x%x Name=%ws IfType=0x%x\n",
  1376. pIfTable->table[i].dwIndex, pIfTable->table[i].wszName, pIfTable->table[i].dwType));
  1377. Error = GetPerInterfaceInfo(
  1378. NetInfo, &NetInfo->IfInfo[j],
  1379. &pIfTable->table[i], InterfaceInfo,
  1380. IfNameInfo, IfNameCount, AddrTable,
  1381. RouteTable, IfList, InternalError );
  1382. if( NO_ERROR != Error ) break;
  1383. j ++;
  1384. }
  1385. }
  1386. //
  1387. // Now add any IPv6-only interfaces.
  1388. //
  1389. for (If = IfList; If; If = If->Next) {
  1390. if ((If->IfIndex == 0) && (If->Ipv6IfIndex != 0) &&
  1391. (If->IfType != IF_TYPE_SOFTWARE_LOOPBACK) &&
  1392. ((If->IfType != IF_TYPE_TUNNEL) || (If->FirstUnicastAddress != NULL))) {
  1393. Error = GetIpv6OnlyPerInterfaceInfo(&NetInfo->IfInfo[j],
  1394. If);
  1395. if( NO_ERROR != Error ) break;
  1396. j ++;
  1397. }
  1398. }
  1399. NetInfo->nInterfaces = j;
  1400. if( NO_ERROR != Error ) break;
  1401. }
  1402. } while ( 0 );
  1403. Delete( pIfTable );
  1404. Delete( InterfaceInfo );
  1405. Delete( IfNameInfo );
  1406. Delete( AddrTable );
  1407. Delete( RouteTable );
  1408. Delete( FixedInfo );
  1409. Delete( IfList );
  1410. if ( SearchInfo ) {
  1411. DnsFreeConfigStructure(
  1412. SearchInfo,
  1413. DnsConfigSearchInformation );
  1414. }
  1415. return Error;
  1416. }