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.

2593 lines
76 KiB

  1. //=============================================================================
  2. // Copyright (c) 1999 Microsoft Corporation
  3. // File: ifip1.c
  4. // Abstract:
  5. // This module implements the helpers for if/ip apis
  6. //
  7. // Author: K.S.Lokesh (lokeshs@) 8-1-99
  8. //=============================================================================
  9. #include "precomp.h"
  10. #include <iphlpapi.h>
  11. #include <iptypes.h>
  12. #include <llinfo.h>
  13. #include "ifip.h"
  14. #include "ifstring.h"
  15. const WCHAR c_wszListSeparatorComma[] = L",";
  16. const WCHAR c_wListSeparatorComma = L',';
  17. const WCHAR c_wListSeparatorSC = L';';
  18. const WCHAR c_wszListSeparatorSC[] = L";";
  19. const WCHAR c_wcsDefGateway[] = L"DefGw=";
  20. const WCHAR c_wcsGwMetric[] = L"GwMetric=";
  21. const WCHAR c_wcsIfMetric[] = L"IfMetric=";
  22. const WCHAR c_wcsDns[] = L"DNS=";
  23. const WCHAR c_wcsDdns[] = L"DynamicUpdate=";
  24. const WCHAR c_wcsDdnsSuffix[] = L"NameRegistration=";
  25. const WCHAR c_wcsWins[] = L"WINS=";
  26. const WCHAR c_wEqual = L'=';
  27. BOOL g_fInitCom = TRUE;
  28. HRESULT
  29. HrUninitializeAndUnlockINetCfg (
  30. INetCfg* pnc
  31. )
  32. /*++
  33. Routine Description
  34. Uninitializes and unlocks the INetCfg object
  35. Arguments
  36. pnc [in] INetCfg to uninitialize and unlock
  37. Return Value
  38. S_OK if success, OLE or Win32 error otherwise
  39. Author: danielwe 13 Nov 1997
  40. --*/
  41. {
  42. HRESULT hr = S_OK;
  43. hr = pnc->lpVtbl->Uninitialize(pnc);
  44. if (SUCCEEDED(hr))
  45. {
  46. INetCfgLock * pnclock;
  47. // Get the locking interface
  48. hr = pnc->lpVtbl->QueryInterface(pnc, &IID_INetCfgLock,
  49. (LPVOID *)(&pnclock));
  50. if (SUCCEEDED(hr))
  51. {
  52. // Attempt to lock the INetCfg for read/write
  53. hr = pnclock->lpVtbl->ReleaseWriteLock(pnclock);
  54. if (pnclock)
  55. {
  56. pnclock->lpVtbl->Release(pnclock);
  57. }
  58. pnclock = NULL;
  59. }
  60. }
  61. // TraceResult("HrUninitializeAndUnlockINetCfg", hr);
  62. return hr;
  63. }
  64. //+---------------------------------------------------------------------------
  65. //
  66. // Function: HrUninitializeAndReleaseINetCfg
  67. //
  68. // Purpose: Unintialize and release an INetCfg object. This will
  69. // optionally uninitialize COM for the caller too.
  70. //
  71. // Arguments:
  72. // fUninitCom [in] TRUE to uninitialize COM after the INetCfg is
  73. // uninitialized and released.
  74. // pnc [in] The INetCfg object.
  75. // fHasLock [in] TRUE if the INetCfg was locked for write and
  76. // must be unlocked.
  77. //
  78. // Returns: S_OK or an error code.
  79. //
  80. // Author: shaunco 7 May 1997
  81. //
  82. // Notes: The return value is the value returned from
  83. // INetCfg::Uninitialize. Even if this fails, the INetCfg
  84. // is still released. Therefore, the return value is for
  85. // informational purposes only. You can't touch the INetCfg
  86. // object after this call returns.
  87. //
  88. HRESULT
  89. HrUninitializeAndReleaseINetCfg (
  90. BOOL fUninitCom,
  91. INetCfg* pnc,
  92. BOOL fHasLock
  93. )
  94. /*++
  95. Routine Description
  96. Arguments
  97. Return Value
  98. --*/
  99. {
  100. // Assert (pnc);
  101. HRESULT hr = S_OK;
  102. if (fHasLock)
  103. {
  104. hr = HrUninitializeAndUnlockINetCfg(pnc);
  105. }
  106. else
  107. {
  108. hr = pnc->lpVtbl->Uninitialize (pnc);
  109. }
  110. if (pnc)
  111. {
  112. pnc->lpVtbl->Release(pnc);
  113. }
  114. pnc = NULL;
  115. if (fUninitCom)
  116. {
  117. CoUninitialize ();
  118. }
  119. // TraceResult("HrUninitializeAndReleaseINetCfg", hr);
  120. return hr;
  121. }
  122. /*!--------------------------------------------------------------------------
  123. HrGetIpPrivateInterface
  124. -
  125. Author: TongLu, KennT
  126. ---------------------------------------------------------------------------*/
  127. HRESULT HrGetIpPrivateInterface(INetCfg* pNetCfg,
  128. ITcpipProperties **ppTcpProperties
  129. )
  130. /*++
  131. Routine Description
  132. Arguments
  133. Return Value
  134. --*/
  135. {
  136. HRESULT hr;
  137. INetCfgClass* pncclass = NULL;
  138. if ((pNetCfg == NULL) || (ppTcpProperties == NULL))
  139. return E_INVALIDARG;
  140. hr = pNetCfg->lpVtbl->QueryNetCfgClass (pNetCfg, &GUID_DEVCLASS_NETTRANS, &IID_INetCfgClass,
  141. (void**)(&pncclass));
  142. if (SUCCEEDED(hr))
  143. {
  144. INetCfgComponent * pnccItem = NULL;
  145. // Find the component.
  146. hr = pncclass->lpVtbl->FindComponent(pncclass, TEXT("MS_TCPIP"), &pnccItem);
  147. //AssertSz (SUCCEEDED(hr), "pncclass->Find failed.");
  148. if (S_OK == hr)
  149. {
  150. INetCfgComponentPrivate* pinccp = NULL;
  151. hr = pnccItem->lpVtbl->QueryInterface(pnccItem, &IID_INetCfgComponentPrivate,
  152. (void**)(&pinccp));
  153. if (SUCCEEDED(hr))
  154. {
  155. hr = pinccp->lpVtbl->QueryNotifyObject(pinccp, &IID_ITcpipProperties,
  156. (void**)(ppTcpProperties));
  157. pinccp->lpVtbl->Release(pinccp);
  158. }
  159. }
  160. if (pnccItem)
  161. pnccItem->lpVtbl->Release(pnccItem);
  162. }
  163. if (pncclass)
  164. pncclass->lpVtbl->Release(pncclass);
  165. // S_OK indicates success (interface returned)
  166. // S_FALSE indicates Ipx not installed
  167. // other values are errors
  168. // TraceResult("HrGetIpPrivateInterface", hr);
  169. return hr;
  170. }
  171. HRESULT
  172. HrCreateAndInitializeINetCfg (
  173. BOOL* pfInitCom,
  174. INetCfg** ppnc,
  175. BOOL fGetWriteLock,
  176. DWORD cmsTimeout,
  177. LPCWSTR szwClientDesc,
  178. LPWSTR * ppszwClientDesc
  179. )
  180. /*++
  181. Routine Description
  182. Cocreate and initialize the root INetCfg object. This will
  183. optionally initialize COM for the caller too.
  184. Arguments
  185. pfInitCom [in,out] TRUE to call CoInitialize before creating.
  186. returns TRUE if COM was successfully
  187. initialized FALSE if not. If NULL, means
  188. don't initialize COM.
  189. ppnc [out] The returned INetCfg object.
  190. fGetWriteLock [in] TRUE if a writable INetCfg is needed
  191. cmsTimeout [in] See INetCfg::LockForWrite
  192. szwClientDesc [in] See INetCfg::LockForWrite
  193. ppszwClientDesc [out] See INetCfg::LockForWrite
  194. Return Value
  195. S_OK or an error code.
  196. --*/
  197. {
  198. HRESULT hr;
  199. // Initialize the output parameter.
  200. *ppnc = NULL;
  201. if (ppszwClientDesc)
  202. *ppszwClientDesc = NULL;
  203. // Initialize COM if the caller requested.
  204. hr = S_OK;
  205. if (pfInitCom && *pfInitCom)
  206. {
  207. hr = CoInitializeEx( NULL,
  208. COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED );
  209. if (RPC_E_CHANGED_MODE == hr)
  210. {
  211. hr = S_OK;
  212. if (pfInitCom)
  213. {
  214. *pfInitCom = FALSE;
  215. }
  216. }
  217. }
  218. if (SUCCEEDED(hr))
  219. {
  220. // Create the object implementing INetCfg.
  221. //
  222. INetCfg* pnc;
  223. hr = CoCreateInstance(&CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER,
  224. &IID_INetCfg, (void**)(&pnc));
  225. // TraceResult("HrCreateAndInitializeINetCfg - CoCreateInstance(CLSID_CNetCfg)", hr);
  226. if (SUCCEEDED(hr))
  227. {
  228. INetCfgLock* pnclock = NULL;
  229. if (fGetWriteLock)
  230. {
  231. // Get the locking interface
  232. hr = pnc->lpVtbl->QueryInterface(pnc, &IID_INetCfgLock,
  233. (LPVOID *)(&pnclock));
  234. // TraceResult("HrCreateAndInitializeINetCfg - QueryInterface(IID_INetCfgLock", hr);
  235. if (SUCCEEDED(hr))
  236. {
  237. // Attempt to lock the INetCfg for read/write
  238. hr = pnclock->lpVtbl->AcquireWriteLock(pnclock, cmsTimeout, szwClientDesc,
  239. ppszwClientDesc);
  240. // TraceResult("HrCreateAndInitializeINetCfg - INetCfgLock::LockForWrite", hr);
  241. if (S_FALSE == hr)
  242. {
  243. // Couldn't acquire the lock
  244. hr = NETCFG_E_NO_WRITE_LOCK;
  245. }
  246. }
  247. }
  248. if (SUCCEEDED(hr))
  249. {
  250. // Initialize the INetCfg object.
  251. //
  252. hr = pnc->lpVtbl->Initialize (pnc, NULL);
  253. // TraceResult("HrCreateAndInitializeINetCfg - Initialize", hr);
  254. if (SUCCEEDED(hr))
  255. {
  256. *ppnc = pnc;
  257. if (pnc)
  258. pnc->lpVtbl->AddRef(pnc);
  259. }
  260. else
  261. {
  262. if (pnclock)
  263. {
  264. pnclock->lpVtbl->ReleaseWriteLock(pnclock);
  265. }
  266. }
  267. // Transfer reference to caller.
  268. }
  269. if (pnclock)
  270. {
  271. pnclock->lpVtbl->Release(pnclock);
  272. }
  273. pnclock = NULL;
  274. if (pnc)
  275. {
  276. pnc->lpVtbl->Release(pnc);
  277. }
  278. pnc = NULL;
  279. }
  280. // If we failed anything above, and we've initialized COM,
  281. // be sure an uninitialize it.
  282. //
  283. if (FAILED(hr) && pfInitCom && *pfInitCom)
  284. {
  285. CoUninitialize ();
  286. }
  287. }
  288. return hr;
  289. }
  290. DWORD
  291. GetTransportConfig(
  292. INetCfg ** pNetCfg,
  293. ITcpipProperties ** pTcpipProperties,
  294. REMOTE_IPINFO **pRemoteIpInfo,
  295. GUID *pGuid,
  296. LPCWSTR pwszIfFriendlyName
  297. )
  298. /*++
  299. Routine Description
  300. Arguments
  301. Return Value
  302. --*/
  303. {
  304. WCHAR wszDesc[] = L"Test of Change IP settings";
  305. HRESULT hr;
  306. // Create the INetCfg, we get the write lock because we need read and write
  307. hr = HrCreateAndInitializeINetCfg(&g_fInitCom, /* &g_fInitCom, */
  308. pNetCfg,
  309. TRUE /* fGetWriteLock */,
  310. 500 /* cmsTimeout */,
  311. wszDesc/* swzClientDesc */,
  312. NULL /* ppszwClientDesc */);
  313. if (hr == S_OK)
  314. {
  315. hr = HrGetIpPrivateInterface(*pNetCfg, pTcpipProperties);
  316. }
  317. if (hr == NETCFG_E_NO_WRITE_LOCK) {
  318. DisplayMessage( g_hModule, EMSG_NETCFG_WRITE_LOCK );
  319. return ERROR_SUPPRESS_OUTPUT;
  320. }
  321. if (hr == S_OK)
  322. {
  323. hr = (*pTcpipProperties)->lpVtbl->GetIpInfoForAdapter(*pTcpipProperties, pGuid, pRemoteIpInfo);
  324. if (hr != S_OK)
  325. {
  326. DisplayMessage(g_hModule, EMSG_PROPERTIES, pwszIfFriendlyName);
  327. hr = ERROR_SUPPRESS_OUTPUT;
  328. }
  329. }
  330. return (hr==S_OK) ? NO_ERROR : hr;
  331. }
  332. VOID
  333. UninitializeTransportConfig(
  334. INetCfg * pNetCfg,
  335. ITcpipProperties * pTcpipProperties,
  336. REMOTE_IPINFO *pRemoteIpInfo
  337. )
  338. /*++
  339. Routine Description
  340. Arguments
  341. Return Value
  342. --*/
  343. {
  344. if (pTcpipProperties)
  345. pTcpipProperties->lpVtbl->Release(pTcpipProperties);
  346. if (pNetCfg)
  347. {
  348. HrUninitializeAndReleaseINetCfg(FALSE,
  349. pNetCfg,
  350. TRUE /* fHasLock */);
  351. }
  352. if (pRemoteIpInfo) CoTaskMemFree(pRemoteIpInfo);
  353. return;
  354. }
  355. DWORD
  356. IfIpAddSetAddress(
  357. LPCWSTR pwszIfFriendlyName,
  358. GUID *pGuid,
  359. LPCWSTR wszIp,
  360. LPCWSTR wszMask,
  361. DWORD Flags
  362. )
  363. /*++
  364. Routine Description
  365. Arguments
  366. Return Value
  367. --*/
  368. {
  369. INetCfg * pNetCfg = NULL;
  370. ITcpipProperties * pTcpipProperties = NULL;
  371. DWORD dwNetwork;
  372. DWORD dwErr = NO_ERROR;
  373. REMOTE_IPINFO *pRemoteIpInfo = NULL;
  374. REMOTE_IPINFO newIPInfo;
  375. if (pGuid == NULL)
  376. return E_INVALIDARG;
  377. dwErr = HRESULT_CODE(GetTransportConfig(
  378. &pNetCfg,
  379. &pTcpipProperties,
  380. &pRemoteIpInfo,
  381. pGuid,
  382. pwszIfFriendlyName
  383. ));
  384. while (dwErr == NO_ERROR) { //breakout block
  385. PWCHAR ptrAddr, ptrMask;
  386. DWORD Found = FALSE;
  387. PWCHAR pszwRemoteIpAddrList=NULL, pszwRemoteIpSubnetMaskList=NULL,
  388. pszwRemoteOptionList=pRemoteIpInfo->pszwOptionList;//i copy options list
  389. PWCHAR IpAddrListEnd;
  390. ULONG Length = wcslen(wszIp);
  391. // currently in static mode
  392. if (pRemoteIpInfo->dwEnableDhcp == FALSE) {
  393. pszwRemoteIpAddrList = pRemoteIpInfo->pszwIpAddrList;
  394. pszwRemoteIpSubnetMaskList = pRemoteIpInfo->pszwSubnetMaskList;
  395. IpAddrListEnd = pszwRemoteIpAddrList + wcslen(pszwRemoteIpAddrList);
  396. }
  397. //
  398. // if adding ipaddr, check if the IpAddr and Mask is already present
  399. //
  400. if (Flags & ADD_FLAG) {
  401. //
  402. // make sure it is in static mode
  403. //
  404. if (pRemoteIpInfo->dwEnableDhcp == TRUE) {
  405. DisplayMessage(g_hModule,
  406. EMSG_ADD_IPADDR_DHCP);
  407. dwErr = ERROR_SUPPRESS_OUTPUT;
  408. break;
  409. }
  410. ptrAddr = pszwRemoteIpAddrList;
  411. ptrMask = pszwRemoteIpSubnetMaskList;
  412. while (ptrAddr && (ptrAddr + Length <= IpAddrListEnd) ){
  413. if (wcsncmp(ptrAddr, wszIp, Length) == 0) {
  414. if ( *(ptrAddr+Length)==0 || *(ptrAddr+Length)==c_wListSeparatorComma){
  415. Found = TRUE;
  416. break;
  417. }
  418. }
  419. ptrAddr = wcschr(ptrAddr, c_wListSeparatorComma);
  420. ptrMask = wcschr(ptrMask, c_wListSeparatorComma);
  421. if (ptrAddr){
  422. ptrAddr++;
  423. ptrMask++;
  424. }
  425. }
  426. if (Found) {
  427. PWCHAR MaskEnd;
  428. MaskEnd = wcschr(ptrMask, c_wListSeparatorComma);
  429. if (MaskEnd)
  430. *MaskEnd = 0;
  431. DisplayMessage(g_hModule,
  432. EMSG_IPADDR_PRESENT,
  433. wszIp, ptrMask);
  434. if (MaskEnd)
  435. *MaskEnd = c_wListSeparatorComma;
  436. dwErr = ERROR_SUPPRESS_OUTPUT;
  437. break;
  438. }
  439. }
  440. memcpy(&newIPInfo, pRemoteIpInfo, sizeof(newIPInfo));
  441. newIPInfo.dwEnableDhcp = FALSE;
  442. //
  443. // copy ip addr list
  444. //
  445. if (Flags & ADD_FLAG) {
  446. ULONG IpAddrListLength = 0;
  447. if (pszwRemoteIpAddrList)
  448. IpAddrListLength = wcslen(pszwRemoteIpAddrList);
  449. newIPInfo.pszwIpAddrList = IfutlAlloc (sizeof(WCHAR) *
  450. (IpAddrListLength +
  451. Length + 2), TRUE);
  452. if (!newIPInfo.pszwIpAddrList)
  453. return ERROR_NOT_ENOUGH_MEMORY;
  454. newIPInfo.pszwIpAddrList[0] = 0;
  455. if (pszwRemoteIpAddrList) {
  456. wcscat(newIPInfo.pszwIpAddrList, pszwRemoteIpAddrList);
  457. wcscat(newIPInfo.pszwIpAddrList, c_wszListSeparatorComma);
  458. }
  459. wcscat(newIPInfo.pszwIpAddrList, wszIp);
  460. }
  461. else {
  462. newIPInfo.pszwIpAddrList = IfutlAlloc (sizeof(WCHAR) *
  463. (Length + 1), FALSE);
  464. if (!newIPInfo.pszwIpAddrList)
  465. return ERROR_NOT_ENOUGH_MEMORY;
  466. wcscpy(newIPInfo.pszwIpAddrList, wszIp);
  467. }
  468. //
  469. // copy subnet mask list
  470. //
  471. if (Flags & ADD_FLAG) {
  472. ULONG RemoteIpSubnetMaskListLen = 0;
  473. if (pszwRemoteIpSubnetMaskList)
  474. RemoteIpSubnetMaskListLen = wcslen(pszwRemoteIpSubnetMaskList);
  475. newIPInfo.pszwSubnetMaskList = IfutlAlloc (sizeof(WCHAR) *
  476. (RemoteIpSubnetMaskListLen +
  477. wcslen(wszMask) + 2), TRUE);
  478. if (!newIPInfo.pszwSubnetMaskList)
  479. return ERROR_NOT_ENOUGH_MEMORY;
  480. newIPInfo.pszwSubnetMaskList[0]= 0;
  481. if (pszwRemoteIpSubnetMaskList) {
  482. wcscpy(newIPInfo.pszwSubnetMaskList, pszwRemoteIpSubnetMaskList);
  483. wcscat(newIPInfo.pszwSubnetMaskList, c_wszListSeparatorComma);
  484. }
  485. wcscat(newIPInfo.pszwSubnetMaskList, wszMask);
  486. }
  487. else {
  488. newIPInfo.pszwSubnetMaskList = IfutlAlloc (sizeof(WCHAR) *
  489. (wcslen(wszMask) + 1), FALSE);
  490. if (!newIPInfo.pszwSubnetMaskList)
  491. return ERROR_NOT_ENOUGH_MEMORY;
  492. wcscpy(newIPInfo.pszwSubnetMaskList, wszMask);
  493. }
  494. // copy old options list
  495. newIPInfo.pszwOptionList = _wcsdup(pszwRemoteOptionList);
  496. DEBUG_PRINT_CONFIG(&newIPInfo);
  497. //
  498. // set the ip address
  499. //
  500. dwErr = HRESULT_CODE(pTcpipProperties->lpVtbl->SetIpInfoForAdapter(
  501. pTcpipProperties, pGuid, &newIPInfo));
  502. if (dwErr == NO_ERROR)
  503. dwErr = HRESULT_CODE(pNetCfg->lpVtbl->Apply(pNetCfg));
  504. if (newIPInfo.pszwIpAddrList) IfutlFree(newIPInfo.pszwIpAddrList);
  505. if (newIPInfo.pszwSubnetMaskList) IfutlFree(newIPInfo.pszwSubnetMaskList);
  506. if (newIPInfo.pszwOptionList) free(newIPInfo.pszwOptionList);
  507. break; //breakout block
  508. } //breakout block
  509. UninitializeTransportConfig(
  510. pNetCfg,
  511. pTcpipProperties,
  512. pRemoteIpInfo
  513. );
  514. return dwErr;
  515. }
  516. VOID
  517. AppendDdnsOptions(
  518. PWCHAR ptrDstn,
  519. PWCHAR ptrOptionList,
  520. DWORD Flags,
  521. DWORD dwRegisterMode
  522. )
  523. /*++
  524. Routine Description
  525. Adds the appropriate "DynamicUpdate=...;NameRegistration=...;"
  526. string to a net config option list.
  527. Arguments
  528. ptrDstn [in] Buffer to which to append DDNS options.
  529. ptrOptionList [in] Old option list.
  530. Flags [in] Used to tell whether this is in a SET or ADD.
  531. dwRegisterMode [in] New mode to convert to options values.
  532. Return Value
  533. None.
  534. --*/
  535. {
  536. PWCHAR ptrBegin, ptrEnd;
  537. //
  538. // Insert DynamicUpdate=...;
  539. //
  540. wcscat(ptrDstn, c_wcsDdns);
  541. if ((Flags & SET_FLAG) && (dwRegisterMode != REGISTER_UNCHANGED)) {
  542. //
  543. // Insert the new value.
  544. //
  545. if (dwRegisterMode == REGISTER_NONE) {
  546. wcscat(ptrDstn, L"0");
  547. } else {
  548. wcscat(ptrDstn, L"1");
  549. }
  550. } else {
  551. //
  552. // Copy the previous value.
  553. //
  554. ptrBegin = wcsstr(ptrOptionList, c_wcsDdns) +
  555. wcslen(c_wcsDdns);
  556. ptrEnd = wcschr(ptrBegin, c_wListSeparatorSC);
  557. ptrDstn += wcslen(ptrDstn);
  558. wcsncpy(ptrDstn, ptrBegin, (DWORD)(ptrEnd - ptrBegin));
  559. ptrDstn += (ULONG)(ptrEnd - ptrBegin);
  560. *ptrDstn = 0;
  561. }
  562. wcscat(ptrDstn, c_wszListSeparatorSC);
  563. //
  564. // Insert NameRegistration=...;
  565. //
  566. wcscat(ptrDstn, c_wcsDdnsSuffix);
  567. if ((Flags & SET_FLAG) && (dwRegisterMode != REGISTER_UNCHANGED)) {
  568. //
  569. // Insert the new value.
  570. //
  571. if (dwRegisterMode == REGISTER_BOTH) {
  572. wcscat(ptrDstn, L"1");
  573. } else {
  574. wcscat(ptrDstn, L"0");
  575. }
  576. } else {
  577. //
  578. // Copy the previous value.
  579. //
  580. ptrBegin = wcsstr(ptrOptionList, c_wcsDdnsSuffix) +
  581. wcslen(c_wcsDdnsSuffix);
  582. ptrEnd = wcschr(ptrBegin, c_wListSeparatorSC);
  583. ptrDstn += wcslen(ptrDstn);
  584. wcsncpy(ptrDstn, ptrBegin, (DWORD)(ptrEnd - ptrBegin));
  585. ptrDstn += (ULONG)(ptrEnd - ptrBegin);
  586. *ptrDstn = 0;
  587. }
  588. wcscat(ptrDstn, c_wszListSeparatorSC);
  589. }
  590. DWORD
  591. IfIpSetDhcpModeMany(
  592. LPCWSTR pwszIfFriendlyName,
  593. GUID *pGuid,
  594. DWORD dwRegisterMode,
  595. DISPLAY_TYPE Type
  596. )
  597. /*++
  598. Routine Description
  599. Arguments
  600. Return Value
  601. --*/
  602. {
  603. INetCfg * pNetCfg = NULL;
  604. ITcpipProperties * pTcpipProperties = NULL;
  605. DWORD dwNetwork;
  606. HRESULT hr = S_OK;
  607. REMOTE_IPINFO *pRemoteIpInfo = NULL;
  608. REMOTE_IPINFO newIPInfo;
  609. if (pGuid == NULL)
  610. return E_INVALIDARG;
  611. hr = GetTransportConfig(
  612. &pNetCfg,
  613. &pTcpipProperties,
  614. &pRemoteIpInfo,
  615. pGuid,
  616. pwszIfFriendlyName
  617. );
  618. while (hr == NO_ERROR) { //breakout block
  619. PWCHAR pszwBuffer;
  620. PWCHAR ptr, newPtr;
  621. PWCHAR pszwRemoteOptionList=pRemoteIpInfo->pszwOptionList;
  622. try {
  623. #pragma prefast(suppress:263, "This is a breakout block, not while loop")
  624. pszwBuffer = (PWCHAR) _alloca(sizeof(WCHAR) *
  625. (wcslen(pszwRemoteOptionList) + 100)) ;
  626. } except (EXCEPTION_EXECUTE_HANDLER) {
  627. return ERROR_NOT_ENOUGH_MEMORY;
  628. }
  629. // if setting ipaddr, check if dhcp already enabled. return.
  630. if (Type==TYPE_IPADDR && pRemoteIpInfo->dwEnableDhcp) {
  631. DisplayMessage(g_hModule,
  632. EMSG_DHCP_MODE);
  633. hr = ERROR_SUPPRESS_OUTPUT;
  634. break;
  635. }
  636. memcpy(&newIPInfo, pRemoteIpInfo, sizeof(REMOTE_IPINFO));
  637. newIPInfo.dwEnableDhcp = pRemoteIpInfo->dwEnableDhcp;
  638. newIPInfo.pszwOptionList = pszwBuffer;
  639. pszwBuffer[0] = 0;
  640. switch(Type) {
  641. case TYPE_DNS:
  642. wcscpy(pszwBuffer, c_wcsDns);
  643. wcscat(pszwBuffer, c_wszListSeparatorSC);
  644. AppendDdnsOptions(pszwBuffer + wcslen(pszwBuffer),
  645. pRemoteIpInfo->pszwOptionList,
  646. SET_FLAG, dwRegisterMode);
  647. break;
  648. case TYPE_WINS:
  649. wcscpy(pszwBuffer, c_wcsWins);
  650. wcscat(pszwBuffer, c_wszListSeparatorSC);
  651. break;
  652. case TYPE_IPADDR:
  653. newIPInfo.dwEnableDhcp = TRUE;
  654. newIPInfo.pszwIpAddrList = NULL;
  655. newIPInfo.pszwSubnetMaskList = NULL;
  656. wcscpy(pszwBuffer, c_wcsDefGateway);
  657. wcscat(pszwBuffer, c_wszListSeparatorSC);
  658. wcscat(pszwBuffer, c_wcsGwMetric);
  659. wcscat(pszwBuffer, c_wszListSeparatorSC);
  660. break;
  661. }
  662. DEBUG_PRINT_CONFIG(&newIPInfo);
  663. //
  664. // set the ip address
  665. //
  666. hr = pTcpipProperties->lpVtbl->SetIpInfoForAdapter(pTcpipProperties, pGuid, &newIPInfo);
  667. if (hr == S_OK)
  668. hr = pNetCfg->lpVtbl->Apply(pNetCfg);
  669. break;
  670. } //breakout block
  671. UninitializeTransportConfig(
  672. pNetCfg,
  673. pTcpipProperties,
  674. pRemoteIpInfo
  675. );
  676. return (hr == S_OK) ? NO_ERROR : hr;
  677. }
  678. DWORD
  679. IfIpAddSetDelMany(
  680. PWCHAR wszIfFriendlyName,
  681. GUID *pGuid,
  682. PWCHAR pwszAddress,
  683. DWORD dwIndex,
  684. DWORD dwRegisterMode,
  685. DISPLAY_TYPE Type,
  686. DWORD Flags
  687. )
  688. /*++
  689. Routine Description
  690. Arguments
  691. Return Value
  692. --*/
  693. {
  694. INetCfg * pNetCfg = NULL;
  695. ITcpipProperties * pTcpipProperties = NULL;
  696. DWORD dwNetwork;
  697. HRESULT hr = S_OK;
  698. REMOTE_IPINFO * pRemoteIpInfo = NULL;
  699. REMOTE_IPINFO newIPInfo;
  700. if (pGuid == NULL)
  701. return E_INVALIDARG;
  702. hr = GetTransportConfig(
  703. &pNetCfg,
  704. &pTcpipProperties,
  705. &pRemoteIpInfo,
  706. pGuid,
  707. wszIfFriendlyName
  708. );
  709. while (hr==NO_ERROR) { //breakout block
  710. PWCHAR ptrBegin, ptrEnd, ptrTmp, ptrDstn, ptrDel=NULL;
  711. const WCHAR * Token;
  712. switch (Type) {
  713. case TYPE_DNS:
  714. Token = c_wcsDns;
  715. break;
  716. case TYPE_WINS:
  717. Token = c_wcsWins;
  718. break;
  719. }
  720. ptrBegin = wcsstr(pRemoteIpInfo->pszwOptionList, Token) + wcslen(Token);
  721. ptrEnd = wcschr(ptrBegin, c_wListSeparatorSC);
  722. //
  723. // check if the address is already present
  724. //
  725. if ( (Flags & (ADD_FLAG | DEL_FLAG)) && (pwszAddress)) {
  726. ULONG Length = wcslen(pwszAddress), Found = FALSE;
  727. ptrTmp = ptrBegin;
  728. while (ptrTmp && (ptrTmp+Length <= ptrEnd) ){
  729. if (ptrTmp = wcsstr(ptrTmp, pwszAddress)) {
  730. if ( ((*(ptrTmp+Length)==c_wListSeparatorComma)
  731. || (*(ptrTmp+Length)==c_wListSeparatorSC) )
  732. && ( (*(ptrTmp-1)==c_wListSeparatorComma)
  733. || (*(ptrTmp-1)==c_wEqual)) )
  734. {
  735. Found = TRUE;
  736. ptrDel = ptrTmp;
  737. break;
  738. }
  739. else {
  740. ptrTmp = wcschr(ptrTmp, c_wListSeparatorComma);
  741. }
  742. }
  743. }
  744. if (Found && (Flags & ADD_FLAG)) {
  745. DisplayMessage(g_hModule,
  746. EMSG_SERVER_PRESENT,
  747. pwszAddress);
  748. hr = ERROR_SUPPRESS_OUTPUT;
  749. break; //from breakout block
  750. }
  751. else if (!Found && (Flags & DEL_FLAG)) {
  752. DisplayMessage(g_hModule,
  753. EMSG_SERVER_ABSENT,
  754. pwszAddress);
  755. hr = ERROR_SUPPRESS_OUTPUT;
  756. break; //from breakout block
  757. }
  758. } // breakout block
  759. memcpy(&newIPInfo, pRemoteIpInfo, sizeof(newIPInfo));
  760. // copy ip addr list
  761. {
  762. newIPInfo.pszwIpAddrList = pRemoteIpInfo->pszwIpAddrList;
  763. }
  764. // copy subnet mask list
  765. {
  766. newIPInfo.pszwSubnetMaskList = pRemoteIpInfo->pszwSubnetMaskList;
  767. }
  768. try {
  769. #pragma prefast(suppress:263, "This is a breakout block, not while loop")
  770. newIPInfo.pszwOptionList =
  771. (PWCHAR) _alloca(sizeof(PWCHAR) *
  772. (wcslen(pRemoteIpInfo->pszwOptionList)+
  773. (pwszAddress?wcslen(pwszAddress):0) + 1));
  774. } except (EXCEPTION_EXECUTE_HANDLER) {
  775. return ERROR_NOT_ENOUGH_MEMORY;
  776. }
  777. // copy token in all cases
  778. ptrDstn = newIPInfo.pszwOptionList;
  779. ptrDstn[0] = 0;
  780. wcscpy(ptrDstn, Token);
  781. ptrDstn += wcslen(Token);
  782. if (Flags & ADD_FLAG) {
  783. DWORD i;
  784. ptrTmp = ptrBegin;
  785. for (i=0; i<dwIndex-1 && ptrTmp && ptrTmp<ptrEnd; i++) {
  786. ptrTmp = wcschr(ptrTmp, c_wListSeparatorComma);
  787. if (ptrTmp) ptrTmp++;
  788. }
  789. if (!ptrTmp || (ptrTmp > ptrEnd)) {
  790. ptrTmp = ptrEnd;
  791. }
  792. if (*(ptrTmp-1) == c_wListSeparatorComma)
  793. ptrTmp--;
  794. // copy addresses before index
  795. if (ptrTmp>ptrBegin) {
  796. wcsncpy(ptrDstn, ptrBegin, (DWORD)(ptrTmp-ptrBegin));
  797. ptrDstn += (ULONG) (ptrTmp - ptrBegin);
  798. ptrTmp++;
  799. *ptrDstn++ = c_wListSeparatorComma;
  800. *ptrDstn = 0;
  801. }
  802. }
  803. // copy new address
  804. if (Flags & (ADD_FLAG|SET_FLAG) ) {
  805. if (pwszAddress) {
  806. wcscat(ptrDstn, pwszAddress);
  807. ptrDstn += wcslen(pwszAddress);
  808. }
  809. }
  810. // copy addresses after index
  811. if (Flags & ADD_FLAG) {
  812. if (ptrTmp < ptrEnd) {
  813. *ptrDstn++ = c_wListSeparatorComma;
  814. *ptrDstn = 0;
  815. wcsncpy(ptrDstn, ptrTmp, (DWORD)(ptrEnd - ptrTmp));
  816. ptrDstn += (ULONG)(ptrEnd - ptrTmp);
  817. *ptrDstn = 0;
  818. }
  819. }
  820. if (Flags & (ADD_FLAG|SET_FLAG) ) {
  821. wcscat(ptrDstn, c_wszListSeparatorSC);
  822. }
  823. if (Flags & DEL_FLAG) {
  824. if (pwszAddress && ptrDel) {//ptrDel to make prefast happy
  825. //if ptrDel not set, then I would have
  826. //got out of breakout block.
  827. BOOL AddrPrepend = FALSE;
  828. if (ptrDel > ptrBegin) {
  829. wcsncat(ptrDstn, ptrBegin, (DWORD)(ptrDel-ptrBegin));
  830. ptrDstn += (ULONG)(ptrDel-ptrBegin);
  831. AddrPrepend = TRUE;
  832. if ( *(ptrDstn-1) == c_wListSeparatorComma) {
  833. *(--ptrDstn) = 0;
  834. }
  835. }
  836. ptrTmp = ptrDel + wcslen(pwszAddress);
  837. if (*ptrTmp == c_wListSeparatorComma)
  838. ptrTmp++;
  839. if (AddrPrepend && *ptrTmp!=c_wListSeparatorSC)
  840. *ptrDstn++ = c_wListSeparatorComma;
  841. wcsncat(ptrDstn, ptrTmp, (DWORD)(ptrEnd - ptrTmp));
  842. ptrDstn += (ULONG)(ptrEnd - ptrTmp);
  843. *ptrDstn = 0;
  844. }
  845. wcscat(ptrDstn, c_wszListSeparatorSC);
  846. }
  847. if (Type == TYPE_DNS) {
  848. AppendDdnsOptions(ptrDstn, pRemoteIpInfo->pszwOptionList,
  849. Flags, dwRegisterMode);
  850. }
  851. DEBUG_PRINT_CONFIG(&newIPInfo);
  852. //
  853. // set the ip address
  854. //
  855. hr = pTcpipProperties->lpVtbl->SetIpInfoForAdapter(pTcpipProperties, pGuid, &newIPInfo);
  856. if (hr == S_OK)
  857. hr = pNetCfg->lpVtbl->Apply(pNetCfg);
  858. break;
  859. } //breakout block
  860. UninitializeTransportConfig(
  861. pNetCfg,
  862. pTcpipProperties,
  863. pRemoteIpInfo
  864. );
  865. return (hr == S_OK) ? NO_ERROR : hr;
  866. }
  867. DWORD
  868. IfIpAddSetGateway(
  869. LPCWSTR pwszIfFriendlyName,
  870. GUID *pGuid,
  871. LPCWSTR pwszGateway,
  872. LPCWSTR pwszGwMetric,
  873. DWORD Flags
  874. )
  875. /*++
  876. Routine Description
  877. Arguments
  878. Return Value
  879. --*/
  880. {
  881. INetCfg * pNetCfg = NULL;
  882. ITcpipProperties * pTcpipProperties = NULL;
  883. DWORD dwNetwork;
  884. HRESULT hr = S_OK;
  885. REMOTE_IPINFO *pRemoteIpInfo = NULL;
  886. REMOTE_IPINFO newIPInfo;
  887. PWCHAR Gateways, GatewaysEnd, GwMetrics, GwMetricsEnd;
  888. if (pGuid == NULL)
  889. return E_INVALIDARG;
  890. hr = GetTransportConfig(
  891. &pNetCfg,
  892. &pTcpipProperties,
  893. &pRemoteIpInfo,
  894. pGuid,
  895. pwszIfFriendlyName
  896. );
  897. while (hr==NO_ERROR) { //breakout block
  898. PWCHAR ptrAddr, ptrMask;
  899. DWORD bFound = FALSE;
  900. PWCHAR pszwRemoteIpAddrList=NULL, pszwRemoteIpSubnetMaskList=NULL,
  901. pszwRemoteOptionList=NULL;
  902. pszwRemoteIpAddrList = pRemoteIpInfo->pszwIpAddrList;
  903. pszwRemoteIpSubnetMaskList = pRemoteIpInfo->pszwSubnetMaskList;
  904. pszwRemoteOptionList = pRemoteIpInfo->pszwOptionList;
  905. Gateways = wcsstr(pszwRemoteOptionList, c_wcsDefGateway) + wcslen(c_wcsDefGateway);
  906. GatewaysEnd = wcschr(Gateways, c_wListSeparatorSC);
  907. GwMetrics = wcsstr(pszwRemoteOptionList, c_wcsGwMetric) + wcslen(c_wcsGwMetric);
  908. GwMetricsEnd = wcschr(GwMetrics, c_wListSeparatorSC);
  909. //
  910. // check if the gateway is already present
  911. //
  912. if (Flags & ADD_FLAG) {
  913. ULONG Length = wcslen(pwszGateway), Found = FALSE;
  914. PWCHAR TmpPtr;
  915. TmpPtr = Gateways;
  916. while (TmpPtr && (TmpPtr+Length <= GatewaysEnd) ){
  917. if (TmpPtr = wcsstr(TmpPtr, pwszGateway)) {
  918. if ( ((*(TmpPtr+Length)==c_wListSeparatorComma)
  919. || (*(TmpPtr+Length)==c_wListSeparatorSC) )
  920. && ( (*(TmpPtr-1)==c_wListSeparatorComma)
  921. || (*(TmpPtr-1)==c_wEqual)) )
  922. {
  923. Found = TRUE;
  924. break;
  925. }
  926. else {
  927. TmpPtr = wcschr(TmpPtr, c_wListSeparatorComma);
  928. }
  929. }
  930. }
  931. if (Found) {
  932. DisplayMessage(g_hModule,
  933. EMSG_DEFGATEWAY_PRESENT,
  934. pwszGateway);
  935. hr = ERROR_SUPPRESS_OUTPUT;
  936. break; //from breakout block
  937. }
  938. }
  939. memcpy(&newIPInfo, pRemoteIpInfo, sizeof(newIPInfo));
  940. // copy ip addr list
  941. newIPInfo.pszwIpAddrList = pRemoteIpInfo->pszwIpAddrList;
  942. // copy subnet mask list
  943. newIPInfo.pszwSubnetMaskList = pRemoteIpInfo->pszwSubnetMaskList;
  944. // copy old options list
  945. if (Flags & ADD_FLAG) {
  946. newIPInfo.pszwOptionList = IfutlAlloc (sizeof(WCHAR) *
  947. (wcslen(pszwRemoteOptionList) +
  948. wcslen(pwszGateway) +
  949. wcslen(pwszGwMetric) +
  950. 3), TRUE);
  951. if (!newIPInfo.pszwOptionList) {
  952. hr = ERROR_NOT_ENOUGH_MEMORY;
  953. break; //from breakout block
  954. }
  955. wcsncpy(newIPInfo.pszwOptionList, pszwRemoteOptionList,
  956. (DWORD)(GatewaysEnd - pszwRemoteOptionList));
  957. *(newIPInfo.pszwOptionList + (GatewaysEnd - pszwRemoteOptionList)) = 0;
  958. if (*(GatewaysEnd-1) != c_wEqual) {
  959. wcscat(newIPInfo.pszwOptionList, c_wszListSeparatorComma);
  960. }
  961. wcscat(newIPInfo.pszwOptionList, pwszGateway);
  962. wcscat(newIPInfo.pszwOptionList, c_wszListSeparatorSC);
  963. {
  964. ULONG Length;
  965. Length = wcslen(newIPInfo.pszwOptionList);
  966. wcsncat(newIPInfo.pszwOptionList, GatewaysEnd+1,
  967. (DWORD)(GwMetricsEnd - (GatewaysEnd+1)));
  968. Length += (DWORD) (GwMetricsEnd - (GatewaysEnd+1));
  969. newIPInfo.pszwOptionList[Length] = 0;
  970. }
  971. if (*(GwMetricsEnd-1) != c_wEqual) {
  972. wcscat(newIPInfo.pszwOptionList, c_wszListSeparatorComma);
  973. }
  974. wcscat(newIPInfo.pszwOptionList, pwszGwMetric);
  975. wcscat(newIPInfo.pszwOptionList, c_wszListSeparatorSC);
  976. wcscat(newIPInfo.pszwOptionList, GwMetricsEnd+1);
  977. }
  978. else {
  979. ULONG Length;
  980. Length = sizeof(WCHAR) * (wcslen(c_wcsDefGateway) + wcslen(c_wcsGwMetric) + 3);
  981. if (pwszGateway)
  982. Length += sizeof(WCHAR) * (wcslen(pwszGateway) + wcslen(pwszGwMetric));
  983. newIPInfo.pszwOptionList = (PWCHAR) IfutlAlloc (Length, FALSE);
  984. if (newIPInfo.pszwOptionList == NULL) {
  985. hr = ERROR_NOT_ENOUGH_MEMORY;
  986. break; //from breakout block
  987. }
  988. newIPInfo.pszwOptionList[0] = 0;
  989. // cat gateway
  990. wcscat(newIPInfo.pszwOptionList, c_wcsDefGateway);
  991. if (pwszGateway)
  992. wcscat(newIPInfo.pszwOptionList, pwszGateway);
  993. wcscat(newIPInfo.pszwOptionList, c_wszListSeparatorSC);
  994. // cat gwmetric
  995. wcscat(newIPInfo.pszwOptionList, c_wcsGwMetric);
  996. if (pwszGateway)
  997. wcscat(newIPInfo.pszwOptionList, pwszGwMetric);
  998. wcscat(newIPInfo.pszwOptionList, c_wszListSeparatorSC);
  999. }
  1000. DEBUG_PRINT_CONFIG(&newIPInfo);
  1001. //
  1002. // set the ip address
  1003. //
  1004. hr = pTcpipProperties->lpVtbl->SetIpInfoForAdapter(pTcpipProperties, pGuid, &newIPInfo);
  1005. if (hr == S_OK)
  1006. hr = pNetCfg->lpVtbl->Apply(pNetCfg);
  1007. if (newIPInfo.pszwOptionList) IfutlFree(newIPInfo.pszwOptionList);
  1008. break;
  1009. } //breakout block
  1010. UninitializeTransportConfig(
  1011. pNetCfg,
  1012. pTcpipProperties,
  1013. pRemoteIpInfo
  1014. );
  1015. return (hr == S_OK) ? NO_ERROR : hr;
  1016. }
  1017. //
  1018. // Display an IP address in Unicode form. If First is false,
  1019. // a string of spaces will first be printed so that the list lines up.
  1020. // For the first address, the caller is responsible for printing the
  1021. // header before calling this function.
  1022. //
  1023. VOID
  1024. ShowUnicodeAddress(
  1025. BOOL *pFirst,
  1026. PWCHAR pwszAddress)
  1027. {
  1028. if (*pFirst) {
  1029. *pFirst = FALSE;
  1030. } else {
  1031. DisplayMessage(g_hModule, MSG_ADDR2);
  1032. }
  1033. DisplayMessage(g_hModule, MSG_ADDR1, pwszAddress);
  1034. }
  1035. // Same as ShowUnicodeAddress, except that the address is passed
  1036. // in multibyte form, such as is used by IPHLPAPI
  1037. VOID
  1038. ShowCharAddress(
  1039. BOOL *pFirst,
  1040. char *chAddress)
  1041. {
  1042. WCHAR pwszBuffer[16];
  1043. if (!chAddress[0]) {
  1044. return;
  1045. }
  1046. MultiByteToWideChar(GetConsoleOutputCP(), 0, chAddress, strlen(chAddress)+1,
  1047. pwszBuffer, 16);
  1048. ShowUnicodeAddress(pFirst, pwszBuffer);
  1049. }
  1050. DWORD
  1051. IfIpShowManyExEx(
  1052. LPCWSTR pwszMachineName,
  1053. ULONG IfIndex,
  1054. PWCHAR pFriendlyIfName,
  1055. GUID *pGuid,
  1056. ULONG Flags,
  1057. HANDLE hFile
  1058. )
  1059. /*++
  1060. Routine Description
  1061. Arguments
  1062. Return Value
  1063. --*/
  1064. {
  1065. INetCfg * pNetCfg = NULL;
  1066. ITcpipProperties * pTcpipProperties = NULL;
  1067. DWORD dwNetwork, dwSize = 0, dwErr;
  1068. HRESULT hr = S_OK;
  1069. REMOTE_IPINFO *pRemoteIpInfo = NULL;
  1070. REMOTE_IPINFO newIPInfo;
  1071. PWCHAR pQuotedFriendlyIfName = NULL;
  1072. PIP_PER_ADAPTER_INFO pPerAdapterInfo = NULL;
  1073. PIP_ADAPTER_INFO pAdaptersInfo = NULL, pAdapterInfo = NULL;
  1074. DWORD dwRegisterMode;
  1075. if (pGuid == NULL)
  1076. return E_INVALIDARG;
  1077. if (hFile && pwszMachineName) {
  1078. // not currently remotable
  1079. return NO_ERROR;
  1080. }
  1081. if (!hFile && !pwszMachineName) {
  1082. //
  1083. // If we're not doing a "dump", and we're looking at the local
  1084. // machine, then get active per-adapter information such as the
  1085. // current DNS and WINS server addresses
  1086. //
  1087. GetPerAdapterInfo(IfIndex, NULL, &dwSize);
  1088. pPerAdapterInfo = (PIP_PER_ADAPTER_INFO)IfutlAlloc(dwSize,FALSE);
  1089. if (!pPerAdapterInfo) {
  1090. return ERROR_NOT_ENOUGH_MEMORY;
  1091. }
  1092. dwErr = GetPerAdapterInfo(IfIndex, pPerAdapterInfo, &dwSize);
  1093. if (dwErr != NO_ERROR) {
  1094. IfutlFree(pPerAdapterInfo);
  1095. pPerAdapterInfo = NULL;
  1096. }
  1097. dwSize = 0;
  1098. GetAdaptersInfo(NULL, &dwSize);
  1099. pAdaptersInfo = (PIP_ADAPTER_INFO)IfutlAlloc(dwSize,FALSE);
  1100. if (!pAdaptersInfo) {
  1101. IfutlFree(pPerAdapterInfo);
  1102. return ERROR_NOT_ENOUGH_MEMORY;
  1103. }
  1104. dwErr = GetAdaptersInfo(pAdaptersInfo, &dwSize);
  1105. if (dwErr != NO_ERROR) {
  1106. IfutlFree(pAdaptersInfo);
  1107. pAdaptersInfo = NULL;
  1108. }
  1109. if (pAdaptersInfo) {
  1110. for (pAdapterInfo = pAdaptersInfo;
  1111. pAdapterInfo && pAdapterInfo->Index != IfIndex;
  1112. pAdapterInfo = pAdapterInfo->Next);
  1113. }
  1114. }
  1115. hr = GetTransportConfig(
  1116. &pNetCfg,
  1117. &pTcpipProperties,
  1118. &pRemoteIpInfo,
  1119. pGuid,
  1120. pFriendlyIfName
  1121. );
  1122. while (hr==NO_ERROR) { //breakout block
  1123. PWCHAR ptrAddr, ptrMask, ptrAddrNew, ptrMaskNew;
  1124. if (hr != NO_ERROR)
  1125. break;
  1126. pQuotedFriendlyIfName = MakeQuotedString( pFriendlyIfName );
  1127. if ( pQuotedFriendlyIfName == NULL ) {
  1128. hr = ERROR_NOT_ENOUGH_MEMORY;
  1129. break;
  1130. }
  1131. DEBUG_PRINT_CONFIG(pRemoteIpInfo);
  1132. if (hFile) {
  1133. DisplayMessage(g_hModule,
  1134. DMP_IFIP_INTERFACE_HEADER,
  1135. pQuotedFriendlyIfName);
  1136. }
  1137. else {
  1138. DisplayMessage(g_hModule,
  1139. MSG_IFIP_HEADER,
  1140. pQuotedFriendlyIfName);
  1141. }
  1142. //
  1143. // display ipaddress list
  1144. //
  1145. if (Flags & TYPE_IPADDR) {
  1146. if (hFile) {
  1147. DisplayMessageT(
  1148. (pRemoteIpInfo->dwEnableDhcp) ? DMP_DHCP : DMP_STATIC,
  1149. pQuotedFriendlyIfName
  1150. );
  1151. }
  1152. else {
  1153. DisplayMessage(g_hModule,
  1154. (pRemoteIpInfo->dwEnableDhcp) ? MSG_DHCP : MSG_STATIC);
  1155. }
  1156. if (!pRemoteIpInfo->dwEnableDhcp) {
  1157. ptrAddr = pRemoteIpInfo->pszwIpAddrList;
  1158. ptrMask = pRemoteIpInfo->pszwSubnetMaskList;
  1159. } else if (!pwszMachineName) {
  1160. // If on the local machine, get the active list
  1161. ptrAddr = NULL;
  1162. ptrMask = NULL;
  1163. }
  1164. if (ptrAddr && ptrMask) {
  1165. DWORD First = TRUE;
  1166. while (ptrAddr && ptrMask && *ptrAddr!=0 && *ptrMask != 0) {
  1167. ptrAddrNew = wcschr(ptrAddr, c_wListSeparatorComma);
  1168. ptrMaskNew = wcschr(ptrMask, c_wListSeparatorComma);
  1169. if (ptrAddrNew)
  1170. *ptrAddrNew = 0;
  1171. if (ptrMaskNew)
  1172. *ptrMaskNew = 0;
  1173. if (hFile) {
  1174. if (First) {
  1175. DisplayMessageT(
  1176. DMP_IPADDR1,
  1177. ptrAddr, ptrMask
  1178. );
  1179. First = FALSE;
  1180. }
  1181. else {
  1182. DisplayMessageT(
  1183. DMP_IPADDR2,
  1184. pQuotedFriendlyIfName,
  1185. ptrAddr, ptrMask
  1186. );
  1187. }
  1188. }
  1189. else {
  1190. DisplayMessage(g_hModule,
  1191. MSG_IPADDR_LIST1,
  1192. ptrAddr, ptrMask);
  1193. }
  1194. ptrAddr = ptrAddrNew ? ++ptrAddrNew : NULL;
  1195. ptrMask = ptrMaskNew ? ++ptrMaskNew : NULL;
  1196. }
  1197. }
  1198. } // end display ipaddr
  1199. //
  1200. // display options list
  1201. //
  1202. {
  1203. PWCHAR IfMetric1, Gateways1, GwMetrics1, Dns1, Wins1,
  1204. Ptr1, Ptr2, Equal, SemiColon, Ddns1, DdnsSuffix1,
  1205. End1;
  1206. if (hr != NO_ERROR)
  1207. break;
  1208. Ptr1 = pRemoteIpInfo->pszwOptionList;
  1209. IfMetric1 = wcsstr(Ptr1, c_wcsIfMetric);
  1210. Gateways1 = wcsstr(Ptr1, c_wcsDefGateway);
  1211. GwMetrics1 = wcsstr(Ptr1, c_wcsGwMetric);
  1212. Dns1 = wcsstr(Ptr1, c_wcsDns);
  1213. Wins1 = wcsstr(Ptr1, c_wcsWins);
  1214. Ddns1 = wcsstr(Ptr1, c_wcsDdns);
  1215. DdnsSuffix1 = wcsstr(Ptr1, c_wcsDdnsSuffix);
  1216. while (*Ptr1) {
  1217. Equal = wcschr(Ptr1, c_wEqual);
  1218. SemiColon = wcschr(Ptr1, c_wListSeparatorSC);
  1219. if (!Equal || !SemiColon)
  1220. break;
  1221. Ptr2 = Ptr1;
  1222. Ptr1 = SemiColon + 1;
  1223. *SemiColon = 0;
  1224. // display IfMetric
  1225. if (Ptr2 == IfMetric1) {
  1226. if (! (Flags & TYPE_IPADDR))
  1227. continue;
  1228. if (hFile) {
  1229. }
  1230. else {
  1231. DisplayMessage(g_hModule,
  1232. MSG_IFMETRIC,
  1233. Equal+1);
  1234. }
  1235. }
  1236. // display Gateways
  1237. else if (Ptr2 == Gateways1) {
  1238. PWCHAR Gateway, GwMetric, GatewayEnd, GwMetricEnd,
  1239. Comma1, Comma2;
  1240. BOOL First = TRUE;
  1241. if (! (Flags & TYPE_IPADDR))
  1242. continue;
  1243. // gateways list null
  1244. if (SemiColon == (Ptr2 + wcslen(c_wcsDefGateway)))
  1245. continue;
  1246. Gateway = Equal + 1;
  1247. GatewayEnd = SemiColon;
  1248. GwMetric = wcschr(GwMetrics1, c_wEqual) + 1;
  1249. GwMetricEnd = wcschr(GwMetrics1, c_wListSeparatorSC);
  1250. *GwMetricEnd = 0;
  1251. do {
  1252. Comma1 = wcschr(Gateway, c_wListSeparatorComma);
  1253. if (Comma1) *Comma1 = 0;
  1254. Comma2 = wcschr(GwMetric, c_wListSeparatorComma);
  1255. if (Comma2) *Comma2 = 0;
  1256. if (hFile) {
  1257. if (First) {
  1258. DisplayMessageT(
  1259. DMP_GATEWAY2,
  1260. pQuotedFriendlyIfName,
  1261. Gateway, GwMetric
  1262. );
  1263. First = FALSE;
  1264. }
  1265. else {
  1266. DisplayMessageT(
  1267. DMP_GATEWAY3,
  1268. pQuotedFriendlyIfName,
  1269. Gateway, GwMetric
  1270. );
  1271. }
  1272. }
  1273. else {
  1274. DisplayMessage(g_hModule,
  1275. MSG_GATEWAY,
  1276. Gateway, GwMetric);
  1277. }
  1278. if (Comma1) *Comma1 = c_wListSeparatorComma;
  1279. if (Comma2) *Comma2 = c_wListSeparatorComma;
  1280. Gateway = Comma1 + 1;
  1281. GwMetric = Comma2 + 1;
  1282. } while (Comma1 && Gateway<GatewayEnd);
  1283. if (hFile && First) {
  1284. DisplayMessageT(
  1285. DMP_GATEWAY1,
  1286. pQuotedFriendlyIfName
  1287. );
  1288. }
  1289. *GwMetricEnd = c_wListSeparatorSC;
  1290. }
  1291. else if (Ptr2 == GwMetrics1) {
  1292. }
  1293. // display wins and dns
  1294. else if ( (Ptr2 == Dns1) || (Ptr2==Wins1)) {
  1295. PWCHAR BeginPtr, EndPtr;
  1296. BOOL bDns = Ptr2==Dns1;
  1297. if (Ptr2==Dns1) {
  1298. if (! (Flags & TYPE_DNS))
  1299. continue;
  1300. }
  1301. else {
  1302. if (! (Flags & TYPE_WINS))
  1303. continue;
  1304. }
  1305. BeginPtr = Equal + 1;
  1306. EndPtr = SemiColon;
  1307. // empty list
  1308. if (BeginPtr==EndPtr) {
  1309. if (hFile) {
  1310. DisplayMessageT(
  1311. pRemoteIpInfo->dwEnableDhcp
  1312. ? (bDns?DMP_DNS_DHCP:DMP_WINS_DHCP)
  1313. : (bDns?DMP_DNS_STATIC_NONE:DMP_WINS_STATIC_NONE),
  1314. pQuotedFriendlyIfName
  1315. );
  1316. if (bDns) {
  1317. //
  1318. // When generating a DNS (not WINS) line,
  1319. // also include the REGISTER=... argument.
  1320. // We need to look ahead in the option list
  1321. // since the DDNS info may occur after the
  1322. // WINS info, but we have to output it before.
  1323. //
  1324. if (!wcstol(Ddns1+wcslen(c_wcsDdns), &End1, 10)) {
  1325. DisplayMessageT(DMP_STRING_ARG,
  1326. TOKEN_REGISTER, TOKEN_VALUE_NONE);
  1327. } else if (!wcstol(DdnsSuffix1+wcslen(
  1328. c_wcsDdnsSuffix), &End1, 10)) {
  1329. DisplayMessageT(DMP_STRING_ARG,
  1330. TOKEN_REGISTER, TOKEN_VALUE_PRIMARY);
  1331. } else {
  1332. DisplayMessageT(DMP_STRING_ARG,
  1333. TOKEN_REGISTER, TOKEN_VALUE_BOTH);
  1334. }
  1335. }
  1336. }
  1337. else {
  1338. if (pRemoteIpInfo->dwEnableDhcp) {
  1339. IP_ADDR_STRING *pAddr;
  1340. BOOL First = TRUE;
  1341. if (!pwszMachineName) {
  1342. DisplayMessage(g_hModule,
  1343. (bDns?MSG_DNS_DHCP_HDR:MSG_WINS_DHCP_HDR)
  1344. );
  1345. // Display active list
  1346. if (bDns && pPerAdapterInfo) {
  1347. for (pAddr = &pPerAdapterInfo->DnsServerList;
  1348. pAddr;
  1349. pAddr = pAddr->Next)
  1350. {
  1351. ShowCharAddress(&First, pAddr->IpAddress.String);
  1352. }
  1353. } else if (!bDns && pAdapterInfo) {
  1354. if (strcmp(pAdapterInfo->PrimaryWinsServer.IpAddress.String, "0.0.0.0")) {
  1355. ShowCharAddress(&First, pAdapterInfo->PrimaryWinsServer.IpAddress.String);
  1356. }
  1357. if (strcmp(pAdapterInfo->SecondaryWinsServer.IpAddress.String, "0.0.0.0")) {
  1358. ShowCharAddress(&First, pAdapterInfo->SecondaryWinsServer.IpAddress.String);
  1359. }
  1360. }
  1361. if (First) {
  1362. DisplayMessage(g_hModule, MSG_NONE);
  1363. }
  1364. } else {
  1365. DisplayMessage(g_hModule,
  1366. (bDns?MSG_DNS_DHCP:MSG_WINS_DHCP)
  1367. );
  1368. }
  1369. }
  1370. else {
  1371. DisplayMessage(g_hModule,
  1372. bDns?MSG_DNS_HDR:MSG_WINS_HDR);
  1373. DisplayMessage(g_hModule,
  1374. MSG_NONE);
  1375. }
  1376. //
  1377. // For show commands, we output either DNS or WINS
  1378. // information but not both, so we can wait until
  1379. // we process the DDNS information normally,
  1380. // before outputting the DDNS state.
  1381. //
  1382. }
  1383. continue;
  1384. }
  1385. {
  1386. PWCHAR Comma1;
  1387. BOOL First = TRUE;
  1388. DWORD Index = 0;
  1389. if (!hFile) {
  1390. DisplayMessage(g_hModule,
  1391. bDns?MSG_DNS_HDR:MSG_WINS_HDR);
  1392. }
  1393. do {
  1394. Index++;
  1395. Comma1 = wcschr(BeginPtr, c_wListSeparatorComma);
  1396. if (Comma1) *Comma1 = 0;
  1397. if (hFile) {
  1398. DisplayMessageT(
  1399. First
  1400. ? (First=FALSE,(bDns?DMP_DNS_STATIC_ADDR1:DMP_WINS_STATIC_ADDR1))
  1401. : (bDns?DMP_DNS_STATIC_ADDR2:DMP_WINS_STATIC_ADDR2),
  1402. pQuotedFriendlyIfName,
  1403. BeginPtr);
  1404. if (bDns && (Index == 1)) {
  1405. //
  1406. // When generating a DNS (not WINS) line,
  1407. // also include the REGISTER=... argument.
  1408. // We need to look ahead in the option list
  1409. // since the DDNS info may occur after the
  1410. // WINS info, but we have to output it
  1411. // before.
  1412. //
  1413. if (!wcstol(Ddns1+wcslen(c_wcsDdns), &End1, 10)) {
  1414. DisplayMessageT(DMP_STRING_ARG,
  1415. TOKEN_REGISTER, TOKEN_VALUE_NONE);
  1416. } else if (!wcstol(DdnsSuffix1+wcslen(
  1417. c_wcsDdnsSuffix), &End1, 10)) {
  1418. DisplayMessageT(DMP_STRING_ARG,
  1419. TOKEN_REGISTER, TOKEN_VALUE_PRIMARY);
  1420. } else {
  1421. DisplayMessageT(DMP_STRING_ARG,
  1422. TOKEN_REGISTER, TOKEN_VALUE_BOTH);
  1423. }
  1424. } else if (Index > 1) {
  1425. DisplayMessageT(DMP_INTEGER_ARG,
  1426. TOKEN_INDEX, Index);
  1427. }
  1428. } else {
  1429. ShowUnicodeAddress(&First, BeginPtr);
  1430. }
  1431. if (Comma1) *Comma1 = c_wListSeparatorComma;
  1432. BeginPtr = Comma1 + 1;
  1433. } while (Comma1 && BeginPtr<EndPtr);
  1434. }
  1435. }
  1436. else if (Ptr2 == Ddns1) {
  1437. if (! (Flags & TYPE_DNS))
  1438. continue;
  1439. //
  1440. // When we see DynamicUpdate=..., save the value.
  1441. // We won't know the complete register mode until
  1442. // we see the subsequent NameRegistration=... value.
  1443. // NetConfig guarantees that DynamicUpdate will occur
  1444. // first.
  1445. //
  1446. dwRegisterMode = wcstol(Equal+1, &End1, 10)? REGISTER_PRIMARY : REGISTER_NONE;
  1447. }
  1448. else if (Ptr2 == DdnsSuffix1) {
  1449. if (! (Flags & TYPE_DNS))
  1450. continue;
  1451. if (hFile) {
  1452. //
  1453. // If this is a dump, we've already looked at
  1454. // this value, when we processed the DNS=... option.
  1455. //
  1456. } else {
  1457. PWCHAR pwszValue;
  1458. //
  1459. // Now that we've seen NameRegistration=...,
  1460. // we know the complete register mode and can
  1461. // output it accordingly.
  1462. //
  1463. if ((dwRegisterMode == REGISTER_PRIMARY) &&
  1464. wcstol(Equal+1, &End1, 10)) {
  1465. pwszValue = MakeString(g_hModule, STRING_BOTH);
  1466. } else if (dwRegisterMode == REGISTER_PRIMARY) {
  1467. pwszValue = MakeString(g_hModule, STRING_PRIMARY);
  1468. } else {
  1469. pwszValue = MakeString(g_hModule, STRING_NONE);
  1470. }
  1471. DisplayMessage(g_hModule, MSG_DDNS_SUFFIX, pwszValue);
  1472. FreeString(pwszValue);
  1473. }
  1474. }
  1475. // any other option
  1476. else {
  1477. *Equal = 0;
  1478. if (!hFile) {
  1479. DisplayMessage(g_hModule,
  1480. MSG_OPTION,
  1481. Ptr2, Equal+1);
  1482. }
  1483. }
  1484. }
  1485. } //end options list
  1486. break;
  1487. } // breakout block
  1488. if ( pQuotedFriendlyIfName ) {
  1489. FreeQuotedString( pQuotedFriendlyIfName );
  1490. }
  1491. UninitializeTransportConfig(
  1492. pNetCfg,
  1493. pTcpipProperties,
  1494. pRemoteIpInfo
  1495. );
  1496. IfutlFree(pPerAdapterInfo);
  1497. IfutlFree(pAdaptersInfo);
  1498. return (hr == S_OK) ? NO_ERROR : hr;
  1499. }
  1500. DWORD
  1501. IfIpHandleDelIpaddrEx(
  1502. LPCWSTR pwszIfFriendlyName,
  1503. GUID *pGuid,
  1504. LPCWSTR pwszIpAddr,
  1505. LPCWSTR pwszGateway,
  1506. ULONG Flags
  1507. )
  1508. /*++
  1509. Routine Description
  1510. Arguments
  1511. Return Value
  1512. --*/
  1513. {
  1514. INetCfg * pNetCfg = NULL;
  1515. ITcpipProperties * pTcpipProperties = NULL;
  1516. DWORD dwNetwork;
  1517. HRESULT hr = S_OK;
  1518. REMOTE_IPINFO *pRemoteIpInfo = NULL;
  1519. if (pGuid == NULL)
  1520. return E_INVALIDARG;
  1521. hr = GetTransportConfig(
  1522. &pNetCfg,
  1523. &pTcpipProperties,
  1524. &pRemoteIpInfo,
  1525. pGuid,
  1526. pwszIfFriendlyName
  1527. );
  1528. while (hr==NO_ERROR) { //breakout block
  1529. if (Flags & TYPE_ADDR) {
  1530. PWCHAR IpAddr, IpAddrEnd;
  1531. PWCHAR Mask, MaskEnd;
  1532. PWCHAR pszwRemoteIpAddrList = pRemoteIpInfo->pszwIpAddrList;
  1533. PWCHAR pszwRemoteSubnetMaskList = pRemoteIpInfo->pszwSubnetMaskList;
  1534. PWCHAR EndIpAddrList = pszwRemoteIpAddrList + wcslen(pszwRemoteIpAddrList);
  1535. BOOL Found = FALSE;
  1536. ULONG Length = wcslen(pwszIpAddr);
  1537. IpAddr = pszwRemoteIpAddrList;
  1538. Mask = pszwRemoteSubnetMaskList;
  1539. while (IpAddr && (IpAddr + Length <= EndIpAddrList) ){
  1540. if (wcsncmp(IpAddr, pwszIpAddr, Length) == 0) {
  1541. if ( *(IpAddr+Length)==0 || *(IpAddr+Length)==c_wListSeparatorComma){
  1542. Found = TRUE;
  1543. break;
  1544. }
  1545. }
  1546. IpAddr = wcschr(IpAddr, c_wListSeparatorComma);
  1547. Mask = wcschr(Mask, c_wListSeparatorComma);
  1548. if (IpAddr){
  1549. IpAddr++;
  1550. Mask++;
  1551. }
  1552. }
  1553. // IpAddr not present
  1554. if (!Found) {
  1555. DisplayMessage(g_hModule,
  1556. EMSG_ADDRESS_NOT_PRESENT);
  1557. hr = ERROR_SUPPRESS_OUTPUT;
  1558. break;
  1559. }
  1560. // cannot delete addr in dhcp mode
  1561. if (pRemoteIpInfo->dwEnableDhcp == TRUE) {
  1562. DisplayMessage(g_hModule,
  1563. EMSG_DHCP_DELETEADDR);
  1564. hr = ERROR_SUPPRESS_OUTPUT;
  1565. break;
  1566. }
  1567. IpAddrEnd = wcschr(IpAddr, c_wListSeparatorComma);
  1568. MaskEnd = wcschr(Mask, c_wListSeparatorComma);
  1569. if (*(IpAddr-1) == c_wListSeparatorComma) {
  1570. IpAddr --;
  1571. Mask --;
  1572. }
  1573. else if (IpAddrEnd) {
  1574. IpAddrEnd++;
  1575. MaskEnd++;
  1576. }
  1577. pszwRemoteIpAddrList[IpAddr - pszwRemoteIpAddrList] = 0;
  1578. pszwRemoteSubnetMaskList[Mask - pszwRemoteSubnetMaskList] = 0;
  1579. if (IpAddrEnd) {
  1580. wcscat(pszwRemoteIpAddrList, IpAddrEnd);
  1581. wcscat(pszwRemoteSubnetMaskList, MaskEnd);
  1582. }
  1583. // should have at least one addr in static mode
  1584. if (wcslen(pszwRemoteIpAddrList)==0 &&
  1585. pRemoteIpInfo->dwEnableDhcp == FALSE)
  1586. {
  1587. DisplayMessage(g_hModule,
  1588. EMSG_MIN_ONE_ADDR);
  1589. hr = ERROR_SUPPRESS_OUTPUT;
  1590. break;
  1591. }
  1592. } //end delete ipaddr
  1593. if (Flags & TYPE_GATEWAY) {
  1594. PWCHAR pszwRemoteOptionList = pRemoteIpInfo->pszwOptionList;
  1595. PWCHAR Gateways, GatewaysEnd, GwMetrics, GwMetricsEnd, GwMetrics1;
  1596. BOOL Found = FALSE;
  1597. Gateways = wcsstr(pszwRemoteOptionList, c_wcsDefGateway)
  1598. + wcslen(c_wcsDefGateway);
  1599. GwMetrics1 = GwMetrics = wcsstr(pszwRemoteOptionList, c_wcsGwMetric)
  1600. + wcslen(c_wcsGwMetric);
  1601. GatewaysEnd = wcschr(Gateways, c_wListSeparatorSC);
  1602. // check if the gateway is present
  1603. if (pwszGateway) {
  1604. ULONG Length = wcslen(pwszGateway);
  1605. while ((Gateways+Length) <= GatewaysEnd) {
  1606. if ( (wcsncmp(pwszGateway, Gateways, Length)==0)
  1607. && ( (*(Gateways+Length)==c_wListSeparatorComma)
  1608. || (*(Gateways+Length)==c_wListSeparatorSC)) )
  1609. {
  1610. Found = TRUE;
  1611. break;
  1612. }
  1613. else {
  1614. if (Gateways = wcschr(Gateways, c_wListSeparatorComma)) {
  1615. Gateways++;
  1616. GwMetrics = wcschr(GwMetrics, c_wListSeparatorComma) + 1;
  1617. }
  1618. else {
  1619. break;
  1620. }
  1621. }
  1622. }
  1623. if (!Found) {
  1624. DisplayMessage(g_hModule,
  1625. EMSG_GATEWAY_NOT_PRESENT);
  1626. hr = ERROR_SUPPRESS_OUTPUT;
  1627. break; //from breakout block
  1628. }
  1629. }
  1630. if (!pwszGateway) {
  1631. wcscpy(pszwRemoteOptionList, c_wcsDefGateway);
  1632. wcscat(pszwRemoteOptionList, c_wszListSeparatorSC);
  1633. wcscat(pszwRemoteOptionList, c_wcsGwMetric);
  1634. wcscat(pszwRemoteOptionList, c_wszListSeparatorSC);
  1635. }
  1636. else {
  1637. PWCHAR GatewaysListEnd, GwMetricsListEnd, TmpPtr;
  1638. GatewaysListEnd = wcschr(Gateways, c_wListSeparatorSC);
  1639. GwMetricsListEnd = wcschr(GwMetrics, c_wListSeparatorSC);
  1640. GatewaysEnd = Gateways + wcslen(pwszGateway);
  1641. GwMetricsEnd = wcschr(GwMetrics, c_wListSeparatorComma);
  1642. if (!GwMetricsEnd || GwMetricsEnd>GwMetricsListEnd)
  1643. GwMetricsEnd = wcschr(GwMetrics, c_wListSeparatorSC);
  1644. if (*(Gateways-1)==c_wListSeparatorComma) {
  1645. Gateways--;
  1646. GwMetrics--;
  1647. } else if (*GatewaysEnd==c_wListSeparatorComma) {
  1648. GatewaysEnd++;
  1649. GwMetricsEnd++;
  1650. }
  1651. wcsncpy(Gateways, GatewaysEnd, (DWORD)(GwMetrics - GatewaysEnd));
  1652. TmpPtr = Gateways + (GwMetrics - GatewaysEnd);
  1653. *TmpPtr = 0;
  1654. wcscat(TmpPtr, GwMetricsEnd);
  1655. }
  1656. } //end delete gateway
  1657. //
  1658. // set the config
  1659. //
  1660. if (hr == S_OK)
  1661. hr = pTcpipProperties->lpVtbl->SetIpInfoForAdapter(pTcpipProperties, pGuid, pRemoteIpInfo);
  1662. if (hr == S_OK)
  1663. hr = pNetCfg->lpVtbl->Apply(pNetCfg);
  1664. break;
  1665. }//end breakout block
  1666. UninitializeTransportConfig(
  1667. pNetCfg,
  1668. pTcpipProperties,
  1669. pRemoteIpInfo
  1670. );
  1671. return (hr == S_OK) ? NO_ERROR : hr;
  1672. }
  1673. DWORD
  1674. OpenDriver(
  1675. HANDLE *Handle,
  1676. LPWSTR DriverName
  1677. )
  1678. /*++
  1679. Routine Description:
  1680. This function opens a specified IO drivers.
  1681. Arguments:
  1682. Handle - pointer to location where the opened drivers handle is
  1683. returned.
  1684. DriverName - name of the driver to be opened.
  1685. Return Value:
  1686. Windows Error Code.
  1687. Notes: copied from net\sockets\tcpcmd\ipcfgapi\ipcfgapi.c
  1688. --*/
  1689. {
  1690. OBJECT_ATTRIBUTES objectAttributes;
  1691. IO_STATUS_BLOCK ioStatusBlock;
  1692. UNICODE_STRING nameString;
  1693. NTSTATUS status;
  1694. *Handle = NULL;
  1695. //
  1696. // Open a Handle to the IP driver.
  1697. //
  1698. RtlInitUnicodeString(&nameString, DriverName);
  1699. InitializeObjectAttributes(
  1700. &objectAttributes,
  1701. &nameString,
  1702. OBJ_CASE_INSENSITIVE,
  1703. (HANDLE) NULL,
  1704. (PSECURITY_DESCRIPTOR) NULL
  1705. );
  1706. status = NtCreateFile(
  1707. Handle,
  1708. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  1709. &objectAttributes,
  1710. &ioStatusBlock,
  1711. NULL,
  1712. FILE_ATTRIBUTE_NORMAL,
  1713. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1714. FILE_OPEN_IF,
  1715. 0,
  1716. NULL,
  1717. 0
  1718. );
  1719. return( RtlNtStatusToDosError( status ) );
  1720. }
  1721. NTSTATUS
  1722. DoIoctl(
  1723. HANDLE Handle,
  1724. DWORD IoctlCode,
  1725. PVOID Request,
  1726. DWORD RequestSize,
  1727. PVOID Response,
  1728. PDWORD ResponseSize
  1729. )
  1730. /*++
  1731. Routine Description:
  1732. Utility routine used to issue a filtering ioctl to the tcpip driver.
  1733. Arguments:
  1734. Handle - An open file handle on which to issue the request.
  1735. IoctlCode - The IOCTL opcode.
  1736. Request - A pointer to the input buffer.
  1737. RequestSize - Size of the input buffer.
  1738. Response - A pointer to the output buffer.
  1739. ResponseSize - On input, the size in bytes of the output buffer.
  1740. On output, the number of bytes returned in the output
  1741. buffer.
  1742. Return Value:
  1743. NT Status Code.
  1744. Notes: copied from net\sockets\tcpcmd\ipcfgapi\ipcfgapi.c
  1745. --*/
  1746. {
  1747. IO_STATUS_BLOCK ioStatusBlock;
  1748. NTSTATUS status;
  1749. ioStatusBlock.Information = 0;
  1750. status = NtDeviceIoControlFile(
  1751. Handle, // Driver handle
  1752. NULL, // Event
  1753. NULL, // APC Routine
  1754. NULL, // APC context
  1755. &ioStatusBlock, // Status block
  1756. IoctlCode, // Control code
  1757. Request, // Input buffer
  1758. RequestSize, // Input buffer size
  1759. Response, // Output buffer
  1760. *ResponseSize // Output buffer size
  1761. );
  1762. if (status == STATUS_PENDING) {
  1763. status = NtWaitForSingleObject(
  1764. Handle,
  1765. TRUE,
  1766. NULL
  1767. );
  1768. }
  1769. if (status == STATUS_SUCCESS) {
  1770. status = ioStatusBlock.Status;
  1771. *ResponseSize = (ULONG)ioStatusBlock.Information;
  1772. }
  1773. else {
  1774. *ResponseSize = 0;
  1775. }
  1776. return(status);
  1777. }
  1778. DWORD
  1779. IfIpGetInfoOffload(
  1780. ULONG IfIndex,
  1781. IFOffloadCapability* IFOC
  1782. )
  1783. /*++
  1784. Routine Description
  1785. Arguments
  1786. Return Value
  1787. --*/
  1788. {
  1789. NTSTATUS Status;
  1790. HANDLE Handle;
  1791. ULONG ResponseBufferSize = sizeof(*IFOC);
  1792. Status = OpenDriver(&Handle, L"\\Device\\Ip");
  1793. if (!NT_SUCCESS(Status)) {
  1794. return(RtlNtStatusToDosError(Status));
  1795. }
  1796. Status = DoIoctl(
  1797. Handle,
  1798. IOCTL_IP_GET_OFFLOAD_CAPABILITY,
  1799. &IfIndex,
  1800. sizeof(IfIndex),
  1801. IFOC,
  1802. &ResponseBufferSize
  1803. );
  1804. CloseHandle(Handle);
  1805. if (!NT_SUCCESS(Status)) {
  1806. return(RtlNtStatusToDosError(Status));
  1807. }
  1808. return NO_ERROR;
  1809. }
  1810. DWORD
  1811. IfIpShowManyEx(
  1812. LPCWSTR pwszMachineName,
  1813. ULONG IfIndex,
  1814. PWCHAR wszIfFriendlyName,
  1815. GUID *guid,
  1816. DISPLAY_TYPE dtType,
  1817. HANDLE hFile
  1818. )
  1819. /*++
  1820. Routine Description
  1821. Arguments
  1822. Return Value
  1823. --*/
  1824. {
  1825. switch (dtType) {
  1826. case TYPE_IPADDR:
  1827. case TYPE_DNS:
  1828. case TYPE_WINS:
  1829. case TYPE_IP_ALL:
  1830. return IfIpShowManyExEx(pwszMachineName, IfIndex, wszIfFriendlyName, guid, dtType, hFile);
  1831. case TYPE_OFFLOAD:
  1832. return IfIpShowInfoOffload(IfIndex, wszIfFriendlyName);
  1833. }
  1834. return NO_ERROR;
  1835. }
  1836. DWORD
  1837. IfIpShowInfoOffload(
  1838. ULONG IfIndex,
  1839. PWCHAR wszIfFriendlyName
  1840. )
  1841. /*++
  1842. Routine Description
  1843. Arguments
  1844. Return Value
  1845. --*/
  1846. {
  1847. IFOffloadCapability IFOC;
  1848. DWORD dwErr;
  1849. PWCHAR pQuotedFriendlyIfName = NULL;
  1850. pQuotedFriendlyIfName = MakeQuotedString( wszIfFriendlyName );
  1851. if ( pQuotedFriendlyIfName == NULL ) {
  1852. return ERROR_NOT_ENOUGH_MEMORY;
  1853. }
  1854. dwErr = IfIpGetInfoOffload(IfIndex, &IFOC);
  1855. if (dwErr != NO_ERROR)
  1856. return dwErr;
  1857. DisplayMessage(g_hModule,
  1858. MSG_OFFLOAD_HDR, pQuotedFriendlyIfName, IfIndex);
  1859. if (IFOC.ifoc_OffloadFlags & TCP_XMT_CHECKSUM_OFFLOAD) {
  1860. DisplayMessage(g_hModule,
  1861. MSG_TCP_XMT_CHECKSUM_OFFLOAD);
  1862. }
  1863. if (IFOC.ifoc_OffloadFlags & IP_XMT_CHECKSUM_OFFLOAD) {
  1864. DisplayMessage(g_hModule,
  1865. MSG_IP_XMT_CHECKSUM_OFFLOAD);
  1866. }
  1867. if (IFOC.ifoc_OffloadFlags & TCP_RCV_CHECKSUM_OFFLOAD) {
  1868. DisplayMessage(g_hModule,
  1869. MSG_TCP_RCV_CHECKSUM_OFFLOAD);
  1870. }
  1871. if (IFOC.ifoc_OffloadFlags & IP_RCV_CHECKSUM_OFFLOAD) {
  1872. DisplayMessage(g_hModule,
  1873. MSG_IP_RCV_CHECKSUM_OFFLOAD);
  1874. }
  1875. if (IFOC.ifoc_OffloadFlags & TCP_LARGE_SEND_OFFLOAD) {
  1876. DisplayMessage(g_hModule,
  1877. MSG_TCP_LARGE_SEND_OFFLOAD);
  1878. }
  1879. if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_CRYPTO_ONLY) {
  1880. DisplayMessage(g_hModule,
  1881. MSG_IPSEC_OFFLOAD_CRYPTO_ONLY);
  1882. }
  1883. if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_ESP) {
  1884. DisplayMessage(g_hModule,
  1885. MSG_IPSEC_OFFLOAD_AH_ESP);
  1886. }
  1887. if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_TPT_TUNNEL) {
  1888. DisplayMessage(g_hModule,
  1889. MSG_IPSEC_OFFLOAD_TPT_TUNNEL);
  1890. }
  1891. if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_V4_OPTIONS) {
  1892. DisplayMessage(g_hModule,
  1893. MSG_IPSEC_OFFLOAD_V4_OPTIONS);
  1894. }
  1895. if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_QUERY_SPI) {
  1896. DisplayMessage(g_hModule,
  1897. MSG_IPSEC_OFFLOAD_QUERY_SPI);
  1898. }
  1899. if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_XMT) {
  1900. DisplayMessage(g_hModule,
  1901. MSG_IPSEC_OFFLOAD_AH_XMT);
  1902. }
  1903. if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_RCV) {
  1904. DisplayMessage(g_hModule,
  1905. MSG_IPSEC_OFFLOAD_AH_RCV);
  1906. }
  1907. if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_TPT) {
  1908. DisplayMessage(g_hModule,
  1909. MSG_IPSEC_OFFLOAD_AH_TPT);
  1910. }
  1911. if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_TUNNEL) {
  1912. DisplayMessage(g_hModule,
  1913. MSG_IPSEC_OFFLOAD_AH_TUNNEL);
  1914. }
  1915. if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_MD5) {
  1916. DisplayMessage(g_hModule,
  1917. MSG_IPSEC_OFFLOAD_AH_MD5);
  1918. }
  1919. if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_AH_SHA_1) {
  1920. DisplayMessage(g_hModule,
  1921. MSG_IPSEC_OFFLOAD_AH_SHA_1);
  1922. }
  1923. if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_XMT) {
  1924. DisplayMessage(g_hModule,
  1925. MSG_IPSEC_OFFLOAD_ESP_XMT);
  1926. }
  1927. if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_RCV) {
  1928. DisplayMessage(g_hModule,
  1929. MSG_IPSEC_OFFLOAD_ESP_RCV);
  1930. }
  1931. if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_TPT) {
  1932. DisplayMessage(g_hModule,
  1933. MSG_IPSEC_OFFLOAD_ESP_TPT);
  1934. }
  1935. if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_TUNNEL) {
  1936. DisplayMessage(g_hModule,
  1937. MSG_IPSEC_OFFLOAD_ESP_TUNNEL);
  1938. }
  1939. if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_DES) {
  1940. DisplayMessage(g_hModule,
  1941. MSG_IPSEC_OFFLOAD_ESP_DES);
  1942. }
  1943. if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_DES_40) {
  1944. DisplayMessage(g_hModule,
  1945. MSG_IPSEC_OFFLOAD_ESP_DES_40);
  1946. }
  1947. if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_3_DES) {
  1948. DisplayMessage(g_hModule,
  1949. MSG_IPSEC_OFFLOAD_ESP_3_DES);
  1950. }
  1951. if (IFOC.ifoc_IPSecOffloadFlags & IPSEC_OFFLOAD_ESP_NONE) {
  1952. DisplayMessage(g_hModule,
  1953. MSG_IPSEC_OFFLOAD_ESP_NONE);
  1954. }
  1955. if ( pQuotedFriendlyIfName ) {
  1956. FreeQuotedString( pQuotedFriendlyIfName );
  1957. }
  1958. return dwErr;
  1959. }