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.

2054 lines
46 KiB

  1. /*
  2. Copyright (c) 1998, Microsoft Corporation, all rights reserved
  3. Description:
  4. The old code is in SaveRegistry and LoadRegistry functions in
  5. ncpa1.1\tcpip\tcpipcpl.cxx
  6. History:
  7. Dec 1997: Vijay Baliga created original version.
  8. */
  9. #include "tcpreg_.h"
  10. /*
  11. Returns:
  12. Number of bytes in the mwsz including the two terminating NULLs.
  13. Notes:
  14. */
  15. #define RAS_LOOPBACK_ADDRESS 0x100007f
  16. DWORD
  17. MwszLength(
  18. IN WCHAR* mwsz
  19. )
  20. {
  21. DWORD dwLength = 2;
  22. RTASSERT(NULL != mwsz);
  23. while (mwsz[0] != 0 || mwsz[1] != 0)
  24. {
  25. dwLength++;
  26. mwsz++;
  27. }
  28. return(dwLength);
  29. }
  30. /*
  31. Returns:
  32. VOID
  33. Notes:
  34. There should be atleast two zeros at the end
  35. */
  36. VOID
  37. ConvertSzToMultiSz(
  38. IN CHAR* sz
  39. )
  40. {
  41. while (TRUE)
  42. {
  43. if ( (0 == sz[0])
  44. && (0 == sz[1]))
  45. {
  46. break;
  47. }
  48. if ( (' ' == sz[0])
  49. || (',' == sz[0]))
  50. {
  51. sz[0] = 0;
  52. }
  53. sz++;
  54. }
  55. }
  56. /*
  57. Returns:
  58. Win32 error code
  59. Notes:
  60. */
  61. DWORD
  62. RegQueryValueWithAllocA(
  63. IN HKEY hKey,
  64. IN CHAR* szValueName,
  65. IN DWORD dwTypeRequired,
  66. IN BYTE** ppbData
  67. )
  68. {
  69. DWORD dwType = 0;
  70. DWORD dwSize = 0;
  71. DWORD dwErr = ERROR_SUCCESS;
  72. RTASSERT(NULL != szValueName);
  73. RTASSERT(NULL != ppbData);
  74. *ppbData = NULL;
  75. dwErr = RegQueryValueExA(hKey,
  76. szValueName,
  77. NULL,
  78. &dwType,
  79. NULL,
  80. &dwSize);
  81. if (ERROR_SUCCESS != dwErr)
  82. {
  83. // TraceHlp("RegQueryValueEx(%s) failed and returned %d.",
  84. // szValueName, dwErr);
  85. goto LDone;
  86. }
  87. if (dwTypeRequired != dwType)
  88. {
  89. dwErr = E_FAIL;
  90. TraceHlp("The type of the value %s should be %d, not %d",
  91. szValueName, dwTypeRequired, dwType);
  92. goto LDone;
  93. }
  94. // For an empty MULTI-SZ, dwSize will be sizeof(CHAR) instead of
  95. // 2 * sizeof(CHAR). We also want to make sure that no matter what
  96. // the type, there will be 2 zeros at the end.
  97. dwSize += 2 * sizeof(CHAR);
  98. *ppbData = LocalAlloc(LPTR, dwSize);
  99. if (NULL == *ppbData)
  100. {
  101. dwErr = GetLastError();
  102. TraceHlp("LocalAlloc failed and returned %d", dwErr);
  103. goto LDone;
  104. }
  105. dwErr = RegQueryValueExA(hKey,
  106. szValueName,
  107. NULL,
  108. &dwType,
  109. *ppbData,
  110. &dwSize);
  111. if (ERROR_SUCCESS != dwErr)
  112. {
  113. // TraceHlp("RegQueryValueEx(%s) failed and returned %d.",
  114. // szValueName, dwErr);
  115. goto LDone;
  116. }
  117. LDone:
  118. if (NO_ERROR != dwErr)
  119. {
  120. LocalFree(*ppbData);
  121. *ppbData = NULL;
  122. }
  123. return(dwErr);
  124. }
  125. /*
  126. Returns:
  127. Win32 error code
  128. Notes:
  129. */
  130. DWORD
  131. RegQueryValueWithAllocW(
  132. IN HKEY hKey,
  133. IN WCHAR* wszValueName,
  134. IN DWORD dwTypeRequired,
  135. IN BYTE** ppbData
  136. )
  137. {
  138. DWORD dwType;
  139. DWORD dwSize = 0;
  140. DWORD dwErr = ERROR_SUCCESS;
  141. RTASSERT(NULL != wszValueName);
  142. RTASSERT(NULL != ppbData);
  143. *ppbData = NULL;
  144. dwErr = RegQueryValueExW(hKey,
  145. wszValueName,
  146. NULL,
  147. &dwType,
  148. NULL,
  149. &dwSize);
  150. if (ERROR_SUCCESS != dwErr)
  151. {
  152. // TraceHlp("RegQueryValueEx(%ws) failed and returned %d.",
  153. // wszValueName, dwErr);
  154. goto LDone;
  155. }
  156. if (dwTypeRequired != dwType)
  157. {
  158. dwErr = E_FAIL;
  159. TraceHlp("The type of the value %ws should be %d, not %d",
  160. wszValueName, dwTypeRequired, dwType);
  161. goto LDone;
  162. }
  163. // For an empty MULTI-SZ, dwSize will be sizeof(WCHAR) instead of
  164. // 2 * sizeof(WCHAR). We also want to make sure that no matter what
  165. // the type, there will be 2 zeros at the end.
  166. dwSize += sizeof(WCHAR);
  167. *ppbData = LocalAlloc(LPTR, dwSize);
  168. if (NULL == *ppbData)
  169. {
  170. dwErr = GetLastError();
  171. TraceHlp("LocalAlloc failed and returned %d", dwErr);
  172. goto LDone;
  173. }
  174. dwErr = RegQueryValueExW(hKey,
  175. wszValueName,
  176. NULL,
  177. &dwType,
  178. *ppbData,
  179. &dwSize);
  180. if (ERROR_SUCCESS != dwErr)
  181. {
  182. // TraceHlp("RegQueryValueEx(%ws) failed and returned %d.",
  183. // wszValueName, dwErr);
  184. goto LDone;
  185. }
  186. LDone:
  187. if (NO_ERROR != dwErr)
  188. {
  189. LocalFree(*ppbData);
  190. *ppbData = NULL;
  191. }
  192. return(dwErr);
  193. }
  194. /*
  195. Returns:
  196. IP address
  197. Notes:
  198. Converts caller's a.b.c.d IP address string to a network byte order IP
  199. address. 0 if formatted incorrectly.
  200. */
  201. IPADDR
  202. IpAddressFromAbcdWsz(
  203. IN WCHAR* wszIpAddress
  204. )
  205. {
  206. CHAR szIpAddress[MAXIPSTRLEN + 1];
  207. IPADDR nboIpAddr;
  208. if (0 == WideCharToMultiByte(
  209. CP_UTF8,
  210. 0,
  211. wszIpAddress,
  212. -1,
  213. szIpAddress,
  214. MAXIPSTRLEN + 1,
  215. NULL,
  216. NULL))
  217. {
  218. return(0);
  219. }
  220. nboIpAddr = inet_addr(szIpAddress);
  221. if (INADDR_NONE == nboIpAddr)
  222. {
  223. nboIpAddr = 0;
  224. }
  225. return(nboIpAddr);
  226. }
  227. /*
  228. Returns:
  229. VOID
  230. Description:
  231. Converts nboIpAddr to a string in the a.b.c.d form and returns same in
  232. caller's szIpAddress buffer. The buffer should be at least
  233. MAXIPSTRLEN + 1 characters long.
  234. */
  235. VOID
  236. AbcdSzFromIpAddress(
  237. IN IPADDR nboIpAddr,
  238. OUT CHAR* szIpAddress
  239. )
  240. {
  241. struct in_addr in_addr;
  242. CHAR* sz;
  243. in_addr.s_addr = nboIpAddr;
  244. sz = inet_ntoa(in_addr);
  245. strcpy(szIpAddress, sz ? sz : "");
  246. }
  247. /*
  248. Returns:
  249. VOID
  250. Description:
  251. Converts nboIpAddr to a string in the a.b.c.d form and returns same in
  252. caller's wszIpAddress buffer. The buffer should be at least
  253. MAXIPSTRLEN + 1 characters long.
  254. */
  255. VOID
  256. AbcdWszFromIpAddress(
  257. IN IPADDR nboIpAddr,
  258. OUT WCHAR* wszIpAddress
  259. )
  260. {
  261. CHAR szIpAddress[MAXIPSTRLEN + 1];
  262. AbcdSzFromIpAddress(nboIpAddr, szIpAddress);
  263. if (0 == MultiByteToWideChar(
  264. CP_UTF8,
  265. 0,
  266. szIpAddress,
  267. -1,
  268. wszIpAddress,
  269. MAXIPSTRLEN + 1))
  270. {
  271. wszIpAddress[0] = 0;
  272. }
  273. }
  274. /*
  275. Returns:
  276. ERROR_SUCCESS: Success (including not finding a.b.c.d)
  277. ERROR_NOT_ENOUGH_MEMORY: Failure
  278. Notes:
  279. Remove the a.b.c.d string wszIpAddress from the space-separated
  280. LocalAlloc'ed list *pwsz. *pwsz is LocalFree'ed and a new string
  281. LocalAlloc'ed and stored in *pwsz.
  282. */
  283. DWORD
  284. RemoveWszIpAddress(
  285. IN WCHAR** pwsz,
  286. IN WCHAR* wszIpAddress
  287. )
  288. {
  289. DWORD cwchIpAddress;
  290. DWORD cwchNew;
  291. WCHAR* wszFound;
  292. WCHAR* wszNew;
  293. DWORD nFoundOffset;
  294. if (NULL == *pwsz)
  295. {
  296. return(ERROR_SUCCESS);
  297. }
  298. cwchIpAddress = wcslen(wszIpAddress);
  299. wszFound = wcsstr(*pwsz, wszIpAddress);
  300. if (!wszFound)
  301. {
  302. return(ERROR_SUCCESS);
  303. }
  304. if (wszFound[cwchIpAddress] == L' ')
  305. {
  306. ++cwchIpAddress;
  307. }
  308. cwchNew = wcslen(*pwsz) - cwchIpAddress + 1;
  309. wszNew = LocalAlloc(LPTR, cwchNew * sizeof(WCHAR));
  310. if (!wszNew)
  311. {
  312. TraceHlp("RemoveWszIpAddress: LocalAlloc returned NULL");
  313. return(ERROR_NOT_ENOUGH_MEMORY);
  314. }
  315. nFoundOffset = (ULONG) (wszFound - *pwsz);
  316. wcsncpy(wszNew, *pwsz, nFoundOffset);
  317. wcscpy(wszNew + nFoundOffset, *pwsz + nFoundOffset + cwchIpAddress);
  318. LocalFree(*pwsz);
  319. *pwsz = wszNew;
  320. return(ERROR_SUCCESS);
  321. }
  322. /*
  323. Returns:
  324. Win32 error code
  325. Notes:
  326. Add the a.b.c.d string wszIpAddress to the front of the space-separated
  327. LocalAlloc'ed list *pwsz. *pwsz is LocalFree'ed and a new string
  328. LocalAlloc'ed and stored in *pwsz.
  329. */
  330. DWORD
  331. PrependWszIpAddress(
  332. IN WCHAR** pwsz,
  333. IN WCHAR* wszIpAddress
  334. )
  335. {
  336. DWORD cwchOld;
  337. DWORD cwchNew;
  338. WCHAR* wszNew;
  339. if (0 == IpAddressFromAbcdWsz(wszIpAddress))
  340. {
  341. TraceHlp("PrependWszIpAddress: Not prepending %ws", wszIpAddress);
  342. return(ERROR_SUCCESS);
  343. }
  344. cwchOld = *pwsz ? wcslen(*pwsz) : 0;
  345. cwchNew = cwchOld + wcslen(wszIpAddress) + 6;
  346. wszNew = LocalAlloc(LPTR, cwchNew * sizeof(WCHAR));
  347. if (!wszNew)
  348. {
  349. TraceHlp("PrependWszIpAddress: LocalAlloc returned NULL");
  350. return(ERROR_NOT_ENOUGH_MEMORY);
  351. }
  352. wcscpy(wszNew, wszIpAddress);
  353. if (cwchOld)
  354. {
  355. wcscat(wszNew, L" ");
  356. wcscat(wszNew, *pwsz);
  357. }
  358. if(NULL != *pwsz)
  359. {
  360. LocalFree(*pwsz);
  361. }
  362. wcscat(wszNew, L"\0");
  363. *pwsz = wszNew;
  364. return(ERROR_SUCCESS);
  365. }
  366. /*
  367. Returns:
  368. ERROR_SUCCESS: Success (including not finding a.b.c.d)
  369. ERROR_NOT_ENOUGH_MEMORY: Failure
  370. Notes:
  371. Remove the a.b.c.d string wszIpAddress from the LocalAlloc'ed MULTI_SZ
  372. *pmwsz. *pmwsz is LocalFree'ed and a new string LocalAlloc'ed and stored in
  373. *pmwsz.
  374. */
  375. DWORD
  376. RemoveWszIpAddressFromMwsz(
  377. IN WCHAR** pmwsz,
  378. IN WCHAR* wszIpAddress
  379. )
  380. {
  381. DWORD cwchIpAddress;
  382. DWORD cwchNew;
  383. WCHAR* wszFound;
  384. WCHAR* mwszNew;
  385. DWORD nFoundOffset;
  386. if (NULL == *pmwsz)
  387. {
  388. return(ERROR_SUCCESS);
  389. }
  390. cwchIpAddress = wcslen(wszIpAddress);
  391. for (wszFound = *pmwsz;
  392. wszFound[0] != 0;
  393. wszFound += wcslen(wszFound) + 1)
  394. {
  395. if (!wcscmp(wszFound, wszIpAddress))
  396. {
  397. break;
  398. }
  399. }
  400. if (!wszFound[0])
  401. {
  402. return(ERROR_SUCCESS);
  403. }
  404. if (wszFound[cwchIpAddress + 1] != 0)
  405. {
  406. ++cwchIpAddress;
  407. }
  408. cwchNew = MwszLength(*pmwsz) - cwchIpAddress;
  409. mwszNew = LocalAlloc(LPTR, cwchNew * sizeof(WCHAR));
  410. if (!mwszNew)
  411. {
  412. TraceHlp("RemoveWszIpAddress: LocalAlloc returned NULL");
  413. return(ERROR_NOT_ENOUGH_MEMORY);
  414. }
  415. nFoundOffset = (ULONG) (wszFound - *pmwsz);
  416. CopyMemory(mwszNew, *pmwsz, nFoundOffset * sizeof(WCHAR));
  417. CopyMemory(mwszNew + nFoundOffset,
  418. *pmwsz + nFoundOffset + cwchIpAddress,
  419. (cwchNew - nFoundOffset) * sizeof(WCHAR));
  420. LocalFree(*pmwsz);
  421. *pmwsz = mwszNew;
  422. return(ERROR_SUCCESS);
  423. }
  424. /*
  425. Returns:
  426. Win32 error code
  427. Notes:
  428. Add the a.b.c.d string wszIpAddress to the front of the LocalAlloc'ed
  429. MULTI_SZ *pmwsz. *pmwsz is LocalFree'ed and a new string LocalAlloc'ed and
  430. stored in *pmwsz.
  431. */
  432. DWORD
  433. PrependWszIpAddressToMwsz(
  434. IN WCHAR** pmwsz,
  435. IN WCHAR* wszIpAddress
  436. )
  437. {
  438. DWORD cwchIpAddress;
  439. DWORD cwchOld;
  440. DWORD cwchNew;
  441. WCHAR* mwszNew;
  442. cwchIpAddress = wcslen(wszIpAddress);
  443. cwchOld = *pmwsz ? MwszLength(*pmwsz) : 0;
  444. cwchNew = cwchOld + cwchIpAddress + 6;
  445. mwszNew = LocalAlloc(LPTR, cwchNew * sizeof(WCHAR));
  446. if (!mwszNew)
  447. {
  448. TraceHlp("PrependWszIpAddress: LocalAlloc returned NULL");
  449. return(ERROR_NOT_ENOUGH_MEMORY);
  450. }
  451. wcscpy(mwszNew, wszIpAddress);
  452. if (cwchOld)
  453. {
  454. CopyMemory(mwszNew + cwchIpAddress + 1, *pmwsz, cwchOld *sizeof(WCHAR));
  455. LocalFree(*pmwsz);
  456. }
  457. *pmwsz = mwszNew;
  458. return(ERROR_SUCCESS);
  459. }
  460. /*
  461. Returns:
  462. Win32 error code
  463. Notes:
  464. Add the address nboIpAddr to the front of the space-separated
  465. LocalAlloc'ed list *pwsz. *pwsz is LocalFree'ed and a new string
  466. LocalAlloc'ed and stored in *pwsz.
  467. */
  468. DWORD
  469. PrependDwIpAddress(
  470. IN WCHAR** pwsz,
  471. IN IPADDR nboIpAddr
  472. )
  473. {
  474. WCHAR wszIpAddress[MAXIPSTRLEN + 1];
  475. AbcdWszFromIpAddress(nboIpAddr, wszIpAddress);
  476. return(PrependWszIpAddress(pwsz, wszIpAddress));
  477. }
  478. /*
  479. Returns:
  480. Win32 error code
  481. Notes:
  482. Add the address nboIpAddr to the front of the LocalAlloc'ed MULTI_SZ
  483. *pmwsz. *pmwsz is LocalFree'ed and a new string LocalAlloc'ed and stored in
  484. *pmwsz.
  485. */
  486. DWORD
  487. PrependDwIpAddressToMwsz(
  488. IN WCHAR** pmwsz,
  489. IN IPADDR nboIpAddr
  490. )
  491. {
  492. WCHAR wszIpAddress[MAXIPSTRLEN + 1];
  493. AbcdWszFromIpAddress(nboIpAddr, wszIpAddress);
  494. return(PrependWszIpAddressToMwsz(pmwsz, wszIpAddress));
  495. }
  496. /*
  497. Returns:
  498. BOOL
  499. Description:
  500. Returns TRUE if there is any non zero value in pTcpipInfo. It also zeroes
  501. the value.
  502. */
  503. BOOL
  504. FJunkExists(
  505. TCPIP_INFO* pTcpipInfo
  506. )
  507. {
  508. BOOL fRet = FALSE;
  509. if ( 0 != pTcpipInfo->wszIPAddress[0]
  510. && wcscmp(pTcpipInfo->wszIPAddress, WCH_ZEROADDRESS))
  511. {
  512. fRet = TRUE;
  513. pTcpipInfo->fChanged = TRUE;
  514. pTcpipInfo->wszIPAddress[0] = 0;
  515. }
  516. if ( 0 != pTcpipInfo->wszSubnetMask[0]
  517. && wcscmp(pTcpipInfo->wszSubnetMask, WCH_ZEROADDRESS))
  518. {
  519. fRet = TRUE;
  520. pTcpipInfo->fChanged = TRUE;
  521. pTcpipInfo->wszSubnetMask[0] = 0;
  522. }
  523. if ( NULL != pTcpipInfo->wszDNSNameServers
  524. && 0 != pTcpipInfo->wszDNSNameServers[0])
  525. {
  526. fRet = TRUE;
  527. LocalFree(pTcpipInfo->wszDNSNameServers);
  528. pTcpipInfo->wszDNSNameServers = NULL;
  529. }
  530. if ( NULL != pTcpipInfo->mwszNetBIOSNameServers
  531. && 0 != pTcpipInfo->mwszNetBIOSNameServers[0]
  532. && 0 != pTcpipInfo->mwszNetBIOSNameServers[1])
  533. {
  534. fRet = TRUE;
  535. LocalFree(pTcpipInfo->mwszNetBIOSNameServers);
  536. pTcpipInfo->mwszNetBIOSNameServers = NULL;
  537. }
  538. if ( NULL != pTcpipInfo->wszDNSDomainName
  539. && 0 != pTcpipInfo->wszDNSDomainName[0])
  540. {
  541. fRet = TRUE;
  542. LocalFree(pTcpipInfo->wszDNSDomainName);
  543. pTcpipInfo->wszDNSDomainName = NULL;
  544. }
  545. return(fRet);
  546. }
  547. /*
  548. Returns:
  549. VOID
  550. Description:
  551. Clears up the stale information left in the regsitry when we AV or the
  552. machine BS's.
  553. */
  554. VOID
  555. ClearTcpipInfo(
  556. VOID
  557. )
  558. {
  559. LONG lRet;
  560. DWORD dwErr;
  561. HKEY hKeyNdisWanIp = NULL;
  562. WCHAR* mwszAdapters = NULL;
  563. WCHAR* mwszTemp;
  564. WCHAR* wszAdapterName;
  565. TCPIP_INFO* pTcpipInfo = NULL;
  566. DWORD dwPrefixLen = wcslen(WCH_TCPIP_PARAM_INT_W);
  567. DWORD dwStrLen;
  568. lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, REGKEY_TCPIP_NDISWANIP_W, 0,
  569. KEY_READ, &hKeyNdisWanIp);
  570. if (ERROR_SUCCESS != lRet)
  571. {
  572. goto LDone;
  573. }
  574. dwErr = RegQueryValueWithAllocW(hKeyNdisWanIp, REGVAL_IPCONFIG_W,
  575. REG_MULTI_SZ, (BYTE**)&mwszAdapters);
  576. if (NO_ERROR != dwErr)
  577. {
  578. goto LDone;
  579. }
  580. mwszTemp = mwszAdapters;
  581. while (mwszTemp[0] != 0)
  582. {
  583. pTcpipInfo = NULL;
  584. dwStrLen = wcslen(mwszTemp);
  585. if (dwPrefixLen >= dwStrLen)
  586. {
  587. goto LWhileEnd;
  588. }
  589. wszAdapterName = mwszTemp + dwPrefixLen;
  590. RTASSERT('{' == wszAdapterName[0]);
  591. dwErr = LoadTcpipInfo(&pTcpipInfo, wszAdapterName, FALSE);
  592. if (NO_ERROR != dwErr)
  593. {
  594. goto LWhileEnd;
  595. }
  596. if (!FJunkExists(pTcpipInfo))
  597. {
  598. goto LWhileEnd;
  599. }
  600. dwErr = SaveTcpipInfo(pTcpipInfo);
  601. if (NO_ERROR != dwErr)
  602. {
  603. goto LWhileEnd;
  604. }
  605. TraceHlp("Clearing Tcpip info for adapter %ws", wszAdapterName);
  606. dwErr = PDhcpNotifyConfigChange(NULL, wszAdapterName, TRUE, 0,
  607. 0, 0, IgnoreFlag);
  608. LWhileEnd:
  609. if (NULL != pTcpipInfo)
  610. {
  611. FreeTcpipInfo(&pTcpipInfo);
  612. }
  613. mwszTemp = mwszTemp + dwStrLen + 1;
  614. }
  615. LDone:
  616. if (NULL != hKeyNdisWanIp)
  617. {
  618. RegCloseKey(hKeyNdisWanIp);
  619. }
  620. LocalFree(mwszAdapters);
  621. }
  622. /*
  623. Returns:
  624. Win32 error code
  625. Description:
  626. Frees the TCPIP_INFO buffer.
  627. */
  628. DWORD
  629. FreeTcpipInfo(
  630. IN TCPIP_INFO** ppTcpipInfo
  631. )
  632. {
  633. if (NULL == *ppTcpipInfo)
  634. {
  635. return(NO_ERROR);
  636. }
  637. TraceHlp("Freeing Tcpip info for adapter %ws", (*ppTcpipInfo)->wszAdapterName);
  638. LocalFree((*ppTcpipInfo)->wszAdapterName);
  639. LocalFree((*ppTcpipInfo)->mwszNetBIOSNameServers);
  640. LocalFree((*ppTcpipInfo)->wszDNSDomainName);
  641. LocalFree((*ppTcpipInfo)->wszDNSNameServers);
  642. LocalFree(*ppTcpipInfo);
  643. *ppTcpipInfo = NULL;
  644. return(NO_ERROR);
  645. }
  646. /*
  647. Returns:
  648. Win32 error code
  649. Description:
  650. Reads NETBT information for the adapter pTcpipInfo->wszAdapterName from
  651. the registry.
  652. */
  653. DWORD
  654. LoadWinsParam(
  655. IN HKEY hKeyWinsParam,
  656. IN TCPIP_INFO* pTcpipInfo
  657. )
  658. {
  659. HKEY hKeyInterfaces = NULL;
  660. HKEY hKeyInterfaceParam = NULL;
  661. WCHAR* wszNetBtBindPath = NULL;
  662. DWORD dwStrLenTcpip_;
  663. DWORD dwStrLenTcpipBindPath;
  664. DWORD dwErr = ERROR_SUCCESS;
  665. RTASSERT(NULL != pTcpipInfo);
  666. RTASSERT(NULL != pTcpipInfo->wszAdapterName);
  667. RTASSERT(NULL == pTcpipInfo->mwszNetBIOSNameServers);
  668. dwErr = RegOpenKeyExW(hKeyWinsParam,
  669. REGKEY_INTERFACES_W,
  670. 0,
  671. KEY_READ,
  672. &hKeyInterfaces);
  673. if (ERROR_SUCCESS != dwErr)
  674. {
  675. TraceHlp("RegOpenKeyEx(%ws) failed and returned %d",
  676. REGKEY_INTERFACES_W, dwErr);
  677. goto LDone;
  678. }
  679. dwStrLenTcpip_ = wcslen(WCH_TCPIP_);
  680. dwStrLenTcpipBindPath = wcslen(pTcpipInfo->wszAdapterName);
  681. wszNetBtBindPath = LocalAlloc(
  682. LPTR, (dwStrLenTcpip_ + dwStrLenTcpipBindPath + 1) * sizeof(WCHAR));
  683. if (NULL == wszNetBtBindPath)
  684. {
  685. dwErr = GetLastError();
  686. TraceHlp("LocalAlloc failed and returned %d", dwErr);
  687. goto LDone;
  688. }
  689. wcscpy(wszNetBtBindPath, WCH_TCPIP_);
  690. wcscat(wszNetBtBindPath, pTcpipInfo->wszAdapterName);
  691. dwErr = RegOpenKeyExW(hKeyInterfaces,
  692. wszNetBtBindPath,
  693. 0,
  694. KEY_READ,
  695. &hKeyInterfaceParam);
  696. if (ERROR_SUCCESS != dwErr)
  697. {
  698. TraceHlp("RegOpenKeyEx(%ws) failed and returned %d",
  699. wszNetBtBindPath, dwErr);
  700. goto LDone;
  701. }
  702. // Its OK if we cannot find the value. Ignore the error.
  703. RegQueryValueWithAllocW(hKeyInterfaceParam,
  704. REGVAL_NAMESERVERLIST_W,
  705. REG_MULTI_SZ,
  706. (BYTE**)&(pTcpipInfo->mwszNetBIOSNameServers));
  707. LDone:
  708. LocalFree(wszNetBtBindPath);
  709. if (NULL != hKeyInterfaces)
  710. {
  711. RegCloseKey(hKeyInterfaces);
  712. }
  713. if (NULL != hKeyInterfaceParam)
  714. {
  715. RegCloseKey(hKeyInterfaceParam);
  716. }
  717. if (NO_ERROR != dwErr)
  718. {
  719. LocalFree(pTcpipInfo->mwszNetBIOSNameServers);
  720. pTcpipInfo->mwszNetBIOSNameServers = NULL;
  721. }
  722. return(dwErr);
  723. }
  724. /*
  725. Returns:
  726. Win32 error code
  727. Description:
  728. Reads TCPIP information for the adapter pTcpipInfo->wszAdapterName from
  729. the registry.
  730. */
  731. DWORD
  732. LoadTcpipParam(
  733. IN HKEY hKeyTcpipParam,
  734. IN TCPIP_INFO* pTcpipInfo
  735. )
  736. {
  737. HKEY hKeyInterfaces = NULL;
  738. HKEY hKeyInterfaceParam = NULL;
  739. DWORD dwType;
  740. DWORD dwSize;
  741. DWORD dwErr = ERROR_SUCCESS;
  742. RTASSERT(NULL != pTcpipInfo);
  743. RTASSERT(NULL != pTcpipInfo->wszAdapterName);
  744. _wcslwr(pTcpipInfo->wszAdapterName);
  745. RTASSERT(0 == pTcpipInfo->wszIPAddress[0]);
  746. RTASSERT(0 == pTcpipInfo->wszSubnetMask[0]);
  747. RTASSERT(NULL == pTcpipInfo->wszDNSDomainName);
  748. RTASSERT(NULL == pTcpipInfo->wszDNSNameServers);
  749. dwErr = RegOpenKeyExW(hKeyTcpipParam,
  750. REGKEY_INTERFACES_W,
  751. 0,
  752. KEY_READ,
  753. &hKeyInterfaces);
  754. if (ERROR_SUCCESS != dwErr)
  755. {
  756. TraceHlp("RegOpenKeyEx(%ws) failed and returned %d",
  757. REGKEY_INTERFACES_W, dwErr);
  758. goto LDone;
  759. }
  760. // Open subkey for this adapter under "Interfaces"
  761. dwErr = RegOpenKeyExW(hKeyInterfaces,
  762. pTcpipInfo->wszAdapterName,
  763. 0,
  764. KEY_READ,
  765. &hKeyInterfaceParam);
  766. if (ERROR_SUCCESS != dwErr)
  767. {
  768. TraceHlp("RegOpenKeyEx(%ws) failed and returned %d",
  769. pTcpipInfo->wszAdapterName, dwErr);
  770. goto LDone;
  771. }
  772. dwSize = sizeof(pTcpipInfo->wszIPAddress);
  773. // Its OK if we cannot find the value. Ignore the error.
  774. dwErr = RegQueryValueExW(hKeyInterfaceParam,
  775. REGVAL_DHCPIPADDRESS_W,
  776. NULL,
  777. &dwType,
  778. (BYTE*)pTcpipInfo->wszIPAddress,
  779. &dwSize);
  780. if (ERROR_SUCCESS != dwErr || REG_SZ != dwType)
  781. {
  782. dwErr = ERROR_SUCCESS;
  783. RTASSERT(0 == pTcpipInfo->wszIPAddress[0]);
  784. pTcpipInfo->wszIPAddress[0] = 0;
  785. }
  786. dwSize = sizeof(pTcpipInfo->wszSubnetMask);
  787. // Its OK if we cannot find the value. Ignore the error.
  788. dwErr = RegQueryValueExW(hKeyInterfaceParam,
  789. REGVAL_DHCPSUBNETMASK_W,
  790. NULL,
  791. &dwType,
  792. (BYTE*)pTcpipInfo->wszSubnetMask,
  793. &dwSize);
  794. if (ERROR_SUCCESS != dwErr || REG_SZ != dwType)
  795. {
  796. dwErr = ERROR_SUCCESS;
  797. RTASSERT(0 == pTcpipInfo->wszSubnetMask[0]);
  798. pTcpipInfo->wszSubnetMask[0] = 0;
  799. // No point in having a valid IP address with an invalid mask.
  800. pTcpipInfo->wszIPAddress[0] = 0;
  801. }
  802. // Its OK if we cannot find the value. Ignore the error.
  803. RegQueryValueWithAllocW(hKeyInterfaceParam,
  804. REGVAL_DOMAIN_W,
  805. REG_SZ,
  806. (BYTE**)&(pTcpipInfo->wszDNSDomainName));
  807. // Its OK if we cannot find the value. Ignore the error.
  808. RegQueryValueWithAllocW(hKeyInterfaceParam,
  809. REGVAL_NAMESERVER_W,
  810. REG_SZ,
  811. (BYTE**)&(pTcpipInfo->wszDNSNameServers));
  812. LDone:
  813. if (NULL != hKeyInterfaces)
  814. {
  815. RegCloseKey(hKeyInterfaces);
  816. }
  817. if (NULL != hKeyInterfaceParam)
  818. {
  819. RegCloseKey(hKeyInterfaceParam);
  820. }
  821. if (ERROR_SUCCESS != dwErr)
  822. {
  823. LocalFree(pTcpipInfo->wszDNSDomainName);
  824. pTcpipInfo->wszDNSDomainName = NULL;
  825. LocalFree(pTcpipInfo->wszDNSNameServers);
  826. pTcpipInfo->wszDNSNameServers = NULL;
  827. }
  828. return(dwErr);
  829. }
  830. /*
  831. Returns:
  832. Win32 error code
  833. Description:
  834. If fAdapterOnly is FALSE, reads NETBT and TCPIP information for the adapter
  835. wszAdapterName from the registry. *ppTcpipInfo must ultimately be freed by
  836. calling FreeTcpipInfo().
  837. */
  838. DWORD
  839. LoadTcpipInfo(
  840. IN TCPIP_INFO** ppTcpipInfo,
  841. IN WCHAR* wszAdapterName,
  842. IN BOOL fAdapterOnly
  843. )
  844. {
  845. HKEY hKeyTcpipParam = NULL;
  846. HKEY hKeyWinsParam = NULL;
  847. DWORD dwErr = ERROR_SUCCESS;
  848. RTASSERT(NULL != wszAdapterName);
  849. if (NULL == wszAdapterName)
  850. {
  851. dwErr = E_FAIL;
  852. TraceHlp("wszAdapterName is NULL");
  853. goto LDone;
  854. }
  855. *ppTcpipInfo = NULL;
  856. *ppTcpipInfo = LocalAlloc(LPTR, sizeof(TCPIP_INFO));
  857. if (NULL == *ppTcpipInfo)
  858. {
  859. dwErr = GetLastError();
  860. TraceHlp("LocalAlloc failed and returned %d", dwErr);
  861. goto LDone;
  862. }
  863. (*ppTcpipInfo)->wszAdapterName = LocalAlloc(
  864. LPTR, (wcslen(wszAdapterName) + 1) * sizeof(WCHAR));
  865. if (NULL == (*ppTcpipInfo)->wszAdapterName)
  866. {
  867. dwErr = GetLastError();
  868. TraceHlp("LocalAlloc failed and returned %d", dwErr);
  869. goto LDone;
  870. }
  871. wcscpy((*ppTcpipInfo)->wszAdapterName, wszAdapterName);
  872. if (fAdapterOnly)
  873. {
  874. goto LDone;
  875. }
  876. dwErr = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  877. REGKEY_TCPIP_PARAM_W,
  878. 0,
  879. KEY_READ,
  880. &hKeyTcpipParam);
  881. if (ERROR_SUCCESS != dwErr)
  882. {
  883. if (ERROR_FILE_NOT_FOUND == dwErr)
  884. {
  885. // Mask the error
  886. dwErr = ERROR_SUCCESS;
  887. }
  888. else
  889. {
  890. TraceHlp("RegOpenKeyEx(%ws) failed and returned %d",
  891. REGKEY_TCPIP_PARAM_W, dwErr);
  892. goto LDone;
  893. }
  894. }
  895. else
  896. {
  897. dwErr = LoadTcpipParam(hKeyTcpipParam, *ppTcpipInfo);
  898. if (ERROR_SUCCESS != dwErr)
  899. {
  900. goto LDone;
  901. }
  902. }
  903. // Open NETBT's parameters key
  904. dwErr = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  905. REGKEY_NETBT_PARAM_W,
  906. 0,
  907. KEY_READ,
  908. &hKeyWinsParam);
  909. if (ERROR_SUCCESS != dwErr)
  910. {
  911. if (ERROR_FILE_NOT_FOUND == dwErr)
  912. {
  913. // Mask the error
  914. dwErr = ERROR_SUCCESS;
  915. }
  916. else
  917. {
  918. TraceHlp("RegOpenKeyEx(%ws) failed and returned %d",
  919. REGKEY_NETBT_PARAM_W, dwErr);
  920. goto LDone;
  921. }
  922. }
  923. else
  924. {
  925. dwErr = LoadWinsParam(hKeyWinsParam, *ppTcpipInfo);
  926. if (ERROR_SUCCESS != dwErr)
  927. {
  928. goto LDone;
  929. }
  930. }
  931. LDone:
  932. if (NULL != hKeyTcpipParam)
  933. {
  934. RegCloseKey(hKeyTcpipParam);
  935. }
  936. if (NULL != hKeyWinsParam)
  937. {
  938. RegCloseKey(hKeyWinsParam);
  939. }
  940. if (ERROR_SUCCESS != dwErr)
  941. {
  942. FreeTcpipInfo(ppTcpipInfo);
  943. }
  944. return(dwErr);
  945. }
  946. /*
  947. Returns:
  948. Win32 error code
  949. Description:
  950. Saves NETBT information for the adapter pTcpipInfo->wszAdapterName to
  951. the registry.
  952. */
  953. DWORD
  954. SaveWinsParam(
  955. IN HKEY hKeyWinsParam,
  956. IN TCPIP_INFO* pTcpipInfo
  957. )
  958. {
  959. HKEY hKeyInterfaces = NULL;
  960. HKEY hKeyInterfaceParam = NULL;
  961. WCHAR* wszNetBtBindPath = NULL;
  962. DWORD dwStrLenTcpip_;
  963. DWORD dwStrLenAdapterName;
  964. WCHAR* mwszData = NULL;
  965. WCHAR mwszBlank[2];
  966. DWORD dw;
  967. DWORD dwErr = ERROR_SUCCESS;
  968. RTASSERT(NULL != pTcpipInfo);
  969. RTASSERT(NULL != pTcpipInfo->wszAdapterName);
  970. dwErr = RegOpenKeyExW(hKeyWinsParam,
  971. REGKEY_INTERFACES_W,
  972. 0,
  973. KEY_WRITE,
  974. &hKeyInterfaces);
  975. if (ERROR_SUCCESS != dwErr)
  976. {
  977. TraceHlp("RegOpenKeyEx(%ws) failed and returned %d",
  978. REGKEY_INTERFACES_W, dwErr);
  979. goto LDone;
  980. }
  981. dwStrLenTcpip_ = wcslen(WCH_TCPIP_);
  982. dwStrLenAdapterName = wcslen(pTcpipInfo->wszAdapterName);
  983. wszNetBtBindPath = LocalAlloc(
  984. LPTR, (dwStrLenTcpip_ + dwStrLenAdapterName + 1) * sizeof(WCHAR));
  985. if (NULL == wszNetBtBindPath)
  986. {
  987. dwErr = GetLastError();
  988. TraceHlp("LocalAlloc failed and returned %d", dwErr);
  989. goto LDone;
  990. }
  991. wcscpy(wszNetBtBindPath, WCH_TCPIP_);
  992. wcscat(wszNetBtBindPath, pTcpipInfo->wszAdapterName);
  993. dwErr = RegOpenKeyExW(hKeyInterfaces,
  994. wszNetBtBindPath,
  995. 0,
  996. KEY_WRITE,
  997. &hKeyInterfaceParam);
  998. if (ERROR_SUCCESS != dwErr)
  999. {
  1000. TraceHlp("RegOpenKeyEx(%ws) failed and returned %d",
  1001. wszNetBtBindPath, dwErr);
  1002. goto LDone;
  1003. }
  1004. if (pTcpipInfo->fDisableNetBIOSoverTcpip)
  1005. {
  1006. dw = REGVAL_DISABLE_NETBT;
  1007. dwErr = RegSetValueExW(hKeyInterfaceParam,
  1008. REGVAL_NETBIOSOPTIONS_W,
  1009. 0,
  1010. REG_DWORD,
  1011. (BYTE*)&dw,
  1012. sizeof(DWORD));
  1013. if (ERROR_SUCCESS != dwErr)
  1014. {
  1015. TraceHlp("RegSetValueEx(%ws) failed: %d",
  1016. REGVAL_NETBIOSOPTIONS_W, dwErr);
  1017. dwErr = NO_ERROR; // Ignore this error
  1018. }
  1019. }
  1020. else
  1021. {
  1022. dwErr = RegDeleteValueW(hKeyInterfaceParam, REGVAL_NETBIOSOPTIONS_W);
  1023. if (ERROR_SUCCESS != dwErr)
  1024. {
  1025. TraceHlp("RegDeleteValue(%ws) failed: %d",
  1026. REGVAL_NETBIOSOPTIONS_W, dwErr);
  1027. dwErr = NO_ERROR; // Ignore this error
  1028. }
  1029. }
  1030. if (NULL == pTcpipInfo->mwszNetBIOSNameServers)
  1031. {
  1032. ZeroMemory(mwszBlank, sizeof(mwszBlank));
  1033. mwszData = mwszBlank;
  1034. }
  1035. else
  1036. {
  1037. mwszData = pTcpipInfo->mwszNetBIOSNameServers;
  1038. }
  1039. dwErr = RegSetValueExW(hKeyInterfaceParam,
  1040. REGVAL_NAMESERVERLIST_W,
  1041. 0,
  1042. REG_MULTI_SZ,
  1043. (BYTE*)mwszData,
  1044. sizeof(WCHAR) * MwszLength(mwszData));
  1045. if (ERROR_SUCCESS != dwErr)
  1046. {
  1047. TraceHlp("RegSetValueEx(%ws) failed and returned %d",
  1048. REGVAL_NAMESERVERLIST_W, dwErr);
  1049. goto LDone;
  1050. }
  1051. LDone:
  1052. LocalFree(wszNetBtBindPath);
  1053. if (NULL != hKeyInterfaceParam)
  1054. {
  1055. RegCloseKey(hKeyInterfaceParam);
  1056. }
  1057. if (NULL != hKeyInterfaces)
  1058. {
  1059. RegCloseKey(hKeyInterfaces);
  1060. }
  1061. return(dwErr);
  1062. }
  1063. /*
  1064. Returns:
  1065. Win32 error code
  1066. Description:
  1067. Saves TCPIP information for the adapter pTcpipInfo->wszAdapterName to
  1068. the registry.
  1069. */
  1070. DWORD
  1071. SaveTcpipParam(
  1072. IN HKEY hKeyTcpipParam,
  1073. IN TCPIP_INFO* pTcpipInfo
  1074. )
  1075. {
  1076. HKEY hKeyInterfaces = NULL;
  1077. HKEY hKeyInterfaceParam = NULL;
  1078. DWORD dwLength;
  1079. WCHAR mwszZeroAddress[MAXIPSTRLEN + 1];
  1080. WCHAR* wszData = NULL;
  1081. WCHAR wszBlank[2];
  1082. DWORD dwErr = ERROR_SUCCESS;
  1083. RTASSERT(NULL != pTcpipInfo);
  1084. RTASSERT(NULL != pTcpipInfo->wszAdapterName);
  1085. _wcslwr(pTcpipInfo->wszAdapterName);
  1086. dwErr = RegOpenKeyExW(hKeyTcpipParam,
  1087. REGKEY_INTERFACES_W,
  1088. 0,
  1089. KEY_WRITE,
  1090. &hKeyInterfaces);
  1091. if (ERROR_SUCCESS != dwErr)
  1092. {
  1093. TraceHlp("RegOpenKeyEx(%ws) failed and returned %d",
  1094. REGKEY_INTERFACES_W, dwErr);
  1095. goto LDone;
  1096. }
  1097. // Open subkey for this adapter under "Interfaces"
  1098. dwErr = RegOpenKeyExW(hKeyInterfaces,
  1099. pTcpipInfo->wszAdapterName,
  1100. 0,
  1101. KEY_WRITE,
  1102. &hKeyInterfaceParam);
  1103. if (ERROR_SUCCESS != dwErr)
  1104. {
  1105. TraceHlp("RegOpenKeyEx(%ws) failed and returned %d",
  1106. pTcpipInfo->wszAdapterName, dwErr);
  1107. goto LDone;
  1108. }
  1109. // If fChanged is set
  1110. if (pTcpipInfo->fChanged == TRUE)
  1111. {
  1112. if ( 0 == pTcpipInfo->wszIPAddress[0]
  1113. || 0 == pTcpipInfo->wszSubnetMask[0])
  1114. {
  1115. RTASSERT(wcslen(WCH_ZEROADDRESS) <= MAXIPSTRLEN);
  1116. wcscpy(pTcpipInfo->wszIPAddress, WCH_ZEROADDRESS);
  1117. wcscpy(pTcpipInfo->wszSubnetMask, WCH_ZEROADDRESS);
  1118. }
  1119. dwErr = RegSetValueExW(hKeyInterfaceParam,
  1120. REGVAL_DHCPIPADDRESS_W,
  1121. 0,
  1122. REG_SZ,
  1123. (BYTE*)pTcpipInfo->wszIPAddress,
  1124. sizeof(WCHAR) * wcslen(pTcpipInfo->wszIPAddress));
  1125. if (ERROR_SUCCESS != dwErr)
  1126. {
  1127. TraceHlp("RegSetValueEx(%ws) failed and returned %d",
  1128. REGVAL_DHCPIPADDRESS_W, dwErr);
  1129. goto LDone;
  1130. }
  1131. dwErr = RegSetValueExW(hKeyInterfaceParam,
  1132. REGVAL_DHCPSUBNETMASK_W,
  1133. 0,
  1134. REG_SZ,
  1135. (BYTE*)pTcpipInfo->wszSubnetMask,
  1136. sizeof(WCHAR) *
  1137. wcslen(pTcpipInfo->wszSubnetMask));
  1138. if (ERROR_SUCCESS != dwErr)
  1139. {
  1140. TraceHlp("RegSetValueEx(%ws) failed and returned %d",
  1141. REGVAL_DHCPSUBNETMASK_W, dwErr);
  1142. goto LDone;
  1143. }
  1144. } // if fChanged = TRUE
  1145. ZeroMemory(wszBlank, sizeof(wszBlank));
  1146. if (NULL == pTcpipInfo->wszDNSDomainName)
  1147. {
  1148. wszData = wszBlank;
  1149. }
  1150. else
  1151. {
  1152. wszData = pTcpipInfo->wszDNSDomainName;
  1153. }
  1154. dwErr = RegSetValueExW(hKeyInterfaceParam,
  1155. REGVAL_DOMAIN_W,
  1156. 0,
  1157. REG_SZ,
  1158. (BYTE*)wszData,
  1159. sizeof(WCHAR) * (wcslen(wszData) + 1));
  1160. if (ERROR_SUCCESS != dwErr)
  1161. {
  1162. TraceHlp("RegSetValueEx(%ws) failed and returned %d",
  1163. REGVAL_DOMAIN_W, dwErr);
  1164. goto LDone;
  1165. }
  1166. if (NULL == pTcpipInfo->wszDNSNameServers)
  1167. {
  1168. wszData = wszBlank;
  1169. }
  1170. else
  1171. {
  1172. wszData = pTcpipInfo->wszDNSNameServers;
  1173. }
  1174. // Check whether the value starts with a space.
  1175. // If so, delete the key. Otherwise save the value.
  1176. if (WCH_SPACE != wszData[0])
  1177. {
  1178. dwErr = RegSetValueExW(hKeyInterfaceParam,
  1179. REGVAL_NAMESERVER_W,
  1180. 0,
  1181. REG_SZ,
  1182. (BYTE*)wszData,
  1183. sizeof(WCHAR) * (wcslen(wszData) + 1));
  1184. if (ERROR_SUCCESS != dwErr)
  1185. {
  1186. TraceHlp("RegSetValueEx(%ws) failed and returned %d",
  1187. REGVAL_NAMESERVER_W, dwErr);
  1188. goto LDone;
  1189. }
  1190. }
  1191. else
  1192. {
  1193. dwErr = RegDeleteValueW(hKeyInterfaceParam, REGVAL_NAMESERVER_W);
  1194. if (ERROR_SUCCESS != dwErr)
  1195. {
  1196. TraceHlp("RegDeleteValue(%ws) failed and returned %d",
  1197. REGVAL_NAMESERVER_W, dwErr);
  1198. goto LDone;
  1199. }
  1200. }
  1201. LDone:
  1202. if (NULL != hKeyInterfaceParam)
  1203. {
  1204. RegCloseKey(hKeyInterfaceParam);
  1205. }
  1206. if (NULL != hKeyInterfaces)
  1207. {
  1208. RegCloseKey(hKeyInterfaces);
  1209. }
  1210. return(dwErr);
  1211. }
  1212. /*
  1213. Returns:
  1214. Win32 error code
  1215. Description:
  1216. Saves NETBT and TCPIP information for the adapter
  1217. pTcpipInfo->wszAdapterName to the registry.
  1218. */
  1219. DWORD
  1220. SaveTcpipInfo(
  1221. IN TCPIP_INFO* pTcpipInfo
  1222. )
  1223. {
  1224. HKEY hKeyTcpipParam = NULL;
  1225. HKEY hKeyWinsParam = NULL;
  1226. DWORD dwErr = ERROR_SUCCESS;
  1227. RTASSERT(NULL != pTcpipInfo);
  1228. if ( (NULL == pTcpipInfo)
  1229. || (NULL == pTcpipInfo->wszAdapterName))
  1230. {
  1231. dwErr = E_FAIL;
  1232. TraceHlp("pTcpipInfo or wszAdapterName is NULL");
  1233. goto LDone;
  1234. }
  1235. dwErr = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  1236. REGKEY_TCPIP_PARAM_W,
  1237. 0,
  1238. KEY_WRITE,
  1239. &hKeyTcpipParam);
  1240. if (ERROR_SUCCESS != dwErr)
  1241. {
  1242. if (ERROR_FILE_NOT_FOUND == dwErr)
  1243. {
  1244. // Mask the error
  1245. dwErr = ERROR_SUCCESS;
  1246. }
  1247. else
  1248. {
  1249. TraceHlp("RegOpenKeyEx(%ws) failed and returned %d",
  1250. REGKEY_TCPIP_PARAM_W, dwErr);
  1251. goto LDone;
  1252. }
  1253. }
  1254. else
  1255. {
  1256. dwErr = SaveTcpipParam(hKeyTcpipParam, pTcpipInfo);
  1257. if (ERROR_SUCCESS != dwErr)
  1258. {
  1259. goto LDone;
  1260. }
  1261. }
  1262. // Open NETBT's parameters key
  1263. dwErr = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  1264. REGKEY_NETBT_PARAM_W,
  1265. 0,
  1266. KEY_WRITE,
  1267. &hKeyWinsParam);
  1268. if (ERROR_SUCCESS != dwErr)
  1269. {
  1270. if (ERROR_FILE_NOT_FOUND == dwErr)
  1271. {
  1272. // Mask the error
  1273. dwErr = ERROR_SUCCESS;
  1274. }
  1275. else
  1276. {
  1277. TraceHlp("RegOpenKeyEx(%ws) failed and returned %d",
  1278. REGKEY_NETBT_PARAM_W, dwErr);
  1279. goto LDone;
  1280. }
  1281. }
  1282. else
  1283. {
  1284. dwErr = SaveWinsParam(hKeyWinsParam, pTcpipInfo);
  1285. if (ERROR_SUCCESS != dwErr)
  1286. {
  1287. goto LDone;
  1288. }
  1289. }
  1290. LDone:
  1291. if (NULL != hKeyTcpipParam)
  1292. {
  1293. RegCloseKey(hKeyTcpipParam);
  1294. }
  1295. if (NULL != hKeyWinsParam)
  1296. {
  1297. RegCloseKey(hKeyWinsParam);
  1298. }
  1299. return(dwErr);
  1300. }
  1301. /*
  1302. Returns:
  1303. Win32 error code
  1304. Notes:
  1305. */
  1306. DWORD
  1307. GetAdapterInfo(
  1308. IN DWORD dwIndex,
  1309. OUT IPADDR* pnboIpAddress,
  1310. OUT IPADDR* pnboDNS1,
  1311. OUT IPADDR* pnboDNS2,
  1312. OUT IPADDR* pnboWINS1,
  1313. OUT IPADDR* pnboWINS2,
  1314. OUT IPADDR* pnboGateway,
  1315. OUT BYTE* pbAddress
  1316. )
  1317. {
  1318. IP_ADAPTER_INFO* pAdapterInfo = NULL;
  1319. IP_ADAPTER_INFO* pAdapter;
  1320. IP_PER_ADAPTER_INFO* pPerAdapterInfo = NULL;
  1321. DWORD dwSize;
  1322. DWORD dw;
  1323. IPADDR nboIpAddress = 0;
  1324. IPADDR nboDNS1 = 0;
  1325. IPADDR nboDNS2 = 0;
  1326. IPADDR nboWINS1 = 0;
  1327. IPADDR nboWINS2 = 0;
  1328. IPADDR nboGateway = 0;
  1329. BYTE bAddress[MAX_ADAPTER_ADDRESS_LENGTH];
  1330. DWORD dwErr = NO_ERROR;
  1331. TraceHlp("GetAdapterInfo");
  1332. dwSize = 0;
  1333. dwErr = PGetAdaptersInfo(NULL, &dwSize);
  1334. if (ERROR_BUFFER_OVERFLOW != dwErr && NO_ERROR != dwErr )
  1335. {
  1336. TraceHlp("GetAdaptersInfo failed and returned %d", dwErr);
  1337. goto LDone;
  1338. }
  1339. pAdapterInfo = LocalAlloc(LPTR, dwSize);
  1340. if (NULL == pAdapterInfo)
  1341. {
  1342. dwErr = GetLastError();
  1343. TraceHlp("LocalAlloc failed and returned %d", dwErr);
  1344. goto LDone;
  1345. }
  1346. dwErr = PGetAdaptersInfo(pAdapterInfo, &dwSize);
  1347. if (NO_ERROR != dwErr)
  1348. {
  1349. TraceHlp("GetAdaptersInfo failed and returned %d", dwErr);
  1350. goto LDone;
  1351. }
  1352. pAdapter = pAdapterInfo;
  1353. while (pAdapter)
  1354. {
  1355. if (pAdapter->Index != dwIndex)
  1356. {
  1357. pAdapter = pAdapter->Next;
  1358. continue;
  1359. }
  1360. break;
  1361. }
  1362. if (NULL == pAdapter)
  1363. {
  1364. TraceHlp("Couldn't get info for the adapter");
  1365. dwErr = ERROR_NOT_FOUND;
  1366. goto LDone;
  1367. }
  1368. nboIpAddress = inet_addr(pAdapter->IpAddressList.IpAddress.String);
  1369. nboGateway = inet_addr(pAdapter->GatewayList.IpAddress.String);
  1370. if (pAdapter->HaveWins)
  1371. {
  1372. nboWINS1 = inet_addr(pAdapter->PrimaryWinsServer.IpAddress.String);
  1373. nboWINS2 = inet_addr(pAdapter->SecondaryWinsServer.IpAddress.String);
  1374. }
  1375. //
  1376. // Check to see if the address is a loopback address and replace it
  1377. // with adapter's ip address if it is - bug. 377807 in .net server
  1378. // database.
  1379. //
  1380. if(nboWINS1 == RAS_LOOPBACK_ADDRESS)
  1381. {
  1382. TraceHlp("GetAdapterInfo: replacing WINS1 with"
  1383. " 0x%x since its loopback", nboIpAddress);
  1384. nboWINS1 = nboIpAddress;
  1385. }
  1386. if(nboWINS2 == RAS_LOOPBACK_ADDRESS)
  1387. {
  1388. TraceHlp("GetAdapterInfo: replacing WINS2 with"
  1389. " 0x%x since its loopback", nboIpAddress);
  1390. nboWINS2 = nboIpAddress;
  1391. }
  1392. for (dw = 0;
  1393. dw < pAdapter->AddressLength && dw < MAX_ADAPTER_ADDRESS_LENGTH;
  1394. dw++)
  1395. {
  1396. bAddress[dw] = pAdapter->Address[dw];
  1397. }
  1398. dwSize = 0;
  1399. dwErr = PGetPerAdapterInfo(dwIndex, NULL, &dwSize);
  1400. if (ERROR_BUFFER_OVERFLOW != dwErr)
  1401. {
  1402. TraceHlp("GetPerAdapterInfo failed and returned %d", dwErr);
  1403. goto LDone;
  1404. }
  1405. pPerAdapterInfo = LocalAlloc(LPTR, dwSize);
  1406. if (NULL == pPerAdapterInfo)
  1407. {
  1408. dwErr = GetLastError();
  1409. TraceHlp("LocalAlloc failed and returned %d", dwErr);
  1410. goto LDone;
  1411. }
  1412. dwErr = PGetPerAdapterInfo(dwIndex, pPerAdapterInfo, &dwSize);
  1413. if (NO_ERROR != dwErr)
  1414. {
  1415. TraceHlp("GetPerAdapterInfo failed and returned %d", dwErr);
  1416. goto LDone;
  1417. }
  1418. if (NULL == pPerAdapterInfo)
  1419. {
  1420. TraceHlp("Couldn't get per adapter info for the adapter");
  1421. dwErr = ERROR_NOT_FOUND;
  1422. goto LDone;
  1423. }
  1424. nboDNS1 = inet_addr(pPerAdapterInfo->DnsServerList.IpAddress.String);
  1425. //
  1426. // Check to see if the address is a loopback address and replace it
  1427. // with adapter's ip address if it is - bug. 377807 in .net server
  1428. // database.
  1429. //
  1430. if(nboDNS1 == RAS_LOOPBACK_ADDRESS)
  1431. {
  1432. TraceHlp("GetAdapterInfo: replacing DNS1 with"
  1433. " 0x%x since its loopback", nboIpAddress);
  1434. nboDNS1 = nboIpAddress;
  1435. }
  1436. if (NULL != pPerAdapterInfo->DnsServerList.Next)
  1437. {
  1438. nboDNS2 =
  1439. inet_addr(pPerAdapterInfo->DnsServerList.Next->IpAddress.String);
  1440. //
  1441. // If this is the loop back address, replace the address with
  1442. // the adapters ip address.
  1443. //
  1444. if(nboDNS2 == RAS_LOOPBACK_ADDRESS)
  1445. {
  1446. TraceHlp("GetAdapterInfo: replacing DNS2 with"
  1447. " 0x%x since its loopback", nboIpAddress);
  1448. nboDNS2 = nboIpAddress;
  1449. }
  1450. }
  1451. if ( (0 == nboIpAddress)
  1452. || (INADDR_NONE == nboIpAddress))
  1453. {
  1454. TraceHlp("Couldn't get IpAddress for the adapter");
  1455. dwErr = ERROR_NOT_FOUND;
  1456. goto LDone;
  1457. }
  1458. if(INADDR_NONE == nboGateway)
  1459. {
  1460. nboGateway = 0;
  1461. }
  1462. if (INADDR_NONE == nboDNS1)
  1463. {
  1464. nboDNS1 = 0;
  1465. }
  1466. if (INADDR_NONE == nboDNS2)
  1467. {
  1468. nboDNS2 = 0;
  1469. }
  1470. if (INADDR_NONE == nboWINS1)
  1471. {
  1472. nboWINS1 = 0;
  1473. }
  1474. if (INADDR_NONE == nboWINS2)
  1475. {
  1476. nboWINS2 = 0;
  1477. }
  1478. LDone:
  1479. if (NO_ERROR != dwErr)
  1480. {
  1481. nboIpAddress = nboGateway = nboDNS1 = nboDNS2
  1482. = nboWINS1 = nboWINS2 = 0;
  1483. ZeroMemory(bAddress, MAX_ADAPTER_ADDRESS_LENGTH);
  1484. }
  1485. if (pnboIpAddress)
  1486. {
  1487. *pnboIpAddress = nboIpAddress;
  1488. }
  1489. if (pnboDNS1)
  1490. {
  1491. *pnboDNS1 = nboDNS1;
  1492. }
  1493. if (pnboDNS2)
  1494. {
  1495. *pnboDNS2 = nboDNS2;
  1496. }
  1497. if (pnboWINS1)
  1498. {
  1499. *pnboWINS1 = nboWINS1;
  1500. }
  1501. if (pnboWINS2)
  1502. {
  1503. *pnboWINS2 = nboWINS2;
  1504. }
  1505. if (pbAddress)
  1506. {
  1507. CopyMemory(pbAddress, bAddress, MAX_ADAPTER_ADDRESS_LENGTH);
  1508. }
  1509. if(pnboGateway)
  1510. {
  1511. *pnboGateway = nboGateway;
  1512. }
  1513. LocalFree(pAdapterInfo);
  1514. LocalFree(pPerAdapterInfo);
  1515. return(dwErr);
  1516. }
  1517. /*
  1518. Returns:
  1519. Win32 error code
  1520. Description:
  1521. Don't cache these values because DHCP leases may have expired, etc
  1522. */
  1523. DWORD
  1524. GetPreferredAdapterInfo(
  1525. OUT IPADDR* pnboIpAddress,
  1526. OUT IPADDR* pnboDNS1,
  1527. OUT IPADDR* pnboDNS2,
  1528. OUT IPADDR* pnboWINS1,
  1529. OUT IPADDR* pnboWINS2,
  1530. OUT BYTE* pbAddress
  1531. )
  1532. {
  1533. HANDLE hHeap = NULL;
  1534. IP_INTERFACE_NAME_INFO* pTable = NULL;
  1535. DWORD dw;
  1536. DWORD dwCount;
  1537. DWORD dwIndex = (DWORD)-1;
  1538. DWORD dwErr = NO_ERROR;
  1539. TraceHlp("GetPreferredAdapterInfo");
  1540. hHeap = GetProcessHeap();
  1541. if (NULL == hHeap)
  1542. {
  1543. dwErr = GetLastError();
  1544. TraceHlp("GetProcessHeap failed and returned %d", dwErr);
  1545. goto LDone;
  1546. }
  1547. dwErr = PNhpAllocateAndGetInterfaceInfoFromStack(&pTable, &dwCount,
  1548. FALSE /* bOrder */, hHeap, LPTR);
  1549. if (NO_ERROR != dwErr)
  1550. {
  1551. TraceHlp("NhpAllocateAndGetInterfaceInfoFromStack failed and "
  1552. "returned %d", dwErr);
  1553. goto LDone;
  1554. }
  1555. for (dw = 0; dw < dwCount; dw++)
  1556. {
  1557. // Only interested in NICs
  1558. if (IF_CONNECTION_DEDICATED != pTable[dw].ConnectionType)
  1559. {
  1560. continue;
  1561. }
  1562. // If the admin wants to use a particular NIC
  1563. if ( HelperRegVal.fNICChosen
  1564. && (!IsEqualGUID(&(HelperRegVal.guidChosenNIC),
  1565. &(pTable[dw].DeviceGuid))))
  1566. {
  1567. continue;
  1568. }
  1569. dwIndex = pTable[dw].Index;
  1570. break;
  1571. }
  1572. if ((DWORD)-1 == dwIndex)
  1573. {
  1574. if (HelperRegVal.fNICChosen)
  1575. {
  1576. // The chosen NIC is not available. Let us choose another one.
  1577. for (dw = 0; dw < dwCount; dw++)
  1578. {
  1579. // Only interested in NICs
  1580. if (IF_CONNECTION_DEDICATED != pTable[dw].ConnectionType)
  1581. {
  1582. continue;
  1583. }
  1584. dwIndex = pTable[dw].Index;
  1585. break;
  1586. }
  1587. }
  1588. if ((DWORD)-1 == dwIndex)
  1589. {
  1590. TraceHlp("Couldn't find an appropriate NIC");
  1591. dwErr = ERROR_NOT_FOUND;
  1592. goto LDone;
  1593. }
  1594. HelperRegVal.fNICChosen = FALSE;
  1595. TraceHlp("The network adapter chosen by the administrator is not "
  1596. "available. Some other adapter will be used.");
  1597. }
  1598. dwErr = GetAdapterInfo(
  1599. dwIndex,
  1600. pnboIpAddress,
  1601. pnboDNS1, pnboDNS2,
  1602. pnboWINS1, pnboWINS2,
  1603. NULL,
  1604. pbAddress);
  1605. LDone:
  1606. if (NULL != pTable)
  1607. {
  1608. HeapFree(hHeap, 0, pTable);
  1609. }
  1610. return(dwErr);
  1611. }