Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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