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.

402 lines
8.2 KiB

  1. // Copyright (c) 1997-2001 Microsoft Corporation
  2. //
  3. // File: NetworkInterface.h
  4. //
  5. // Synopsis: Defines a NetworkInterface
  6. // This object has the knowledge of an
  7. // IP enabled network connection including
  8. // IP address, DHCP information, etc.
  9. //
  10. // History: 03/01/2001 JeffJon Created
  11. #include "pch.h"
  12. #include "NetworkInterface.h"
  13. #define CYS_WMIPROP_IPADDRESS L"IPAddress"
  14. #define CYS_WMIPROP_DHCPENABLED L"DHCPEnabled"
  15. #define CYS_WMIPROP_DESCRIPTION L"Description"
  16. NetworkInterface::NetworkInterface()
  17. : initialized(false),
  18. ipaddrCount(0),
  19. dhcpEnabled(false)
  20. {
  21. LOG_CTOR(NetworkInterface);
  22. }
  23. NetworkInterface::~NetworkInterface()
  24. {
  25. LOG_DTOR(NetworkInterface);
  26. if (!ipaddresses.empty())
  27. {
  28. ipaddresses.clear();
  29. }
  30. ipaddrCount = 0;
  31. }
  32. NetworkInterface::NetworkInterface(const NetworkInterface &nic)
  33. {
  34. LOG_CTOR2(NetworkInterface, L"Copy constructor");
  35. if (this == &nic)
  36. {
  37. return;
  38. }
  39. initialized = nic.initialized;
  40. ipaddrCount = nic.ipaddrCount;
  41. dhcpEnabled = nic.dhcpEnabled;
  42. wmiAdapterObject = nic.wmiAdapterObject;
  43. ipaddressString = nic.ipaddressString;
  44. // Make a copy of the ipaddress array
  45. ipaddresses = nic.ipaddresses;
  46. }
  47. NetworkInterface&
  48. NetworkInterface::operator=(const NetworkInterface& rhs)
  49. {
  50. LOG_FUNCTION(NetworkInterface::operator=);
  51. if (this == &rhs)
  52. {
  53. return *this;
  54. }
  55. initialized = rhs.initialized;
  56. ipaddrCount = rhs.ipaddrCount;
  57. dhcpEnabled = rhs.dhcpEnabled;
  58. wmiAdapterObject = rhs.wmiAdapterObject;
  59. ipaddressString = rhs.ipaddressString;
  60. // Make a copy of the ipaddress array
  61. ipaddresses = rhs.ipaddresses;
  62. return *this;
  63. }
  64. HRESULT
  65. NetworkInterface::Initialize(SmartInterface<IWbemClassObject>& adapterObject)
  66. {
  67. LOG_FUNCTION(NetworkInterface::Initialize);
  68. HRESULT hr = S_OK;
  69. if (initialized)
  70. {
  71. ASSERT(!initialized);
  72. hr = E_UNEXPECTED;
  73. }
  74. else
  75. {
  76. // Store the adapter interface pointer for later use
  77. wmiAdapterObject = adapterObject;
  78. // Get the needed info from the WMI object
  79. hr = GetIPAddressFromWMI();
  80. if (FAILED(hr))
  81. {
  82. LOG(String::format(
  83. L"Failed to retrieve IP Addresses: hr = 0x%1!x!",
  84. hr));
  85. }
  86. hr = GetDHCPEnabledFromWMI();
  87. if (FAILED(hr))
  88. {
  89. LOG(String::format(
  90. L"Failed to retrieve dhcpEnabled state: hr = 0x%1!x!",
  91. hr));
  92. }
  93. }
  94. // If we succeeded in retrieving the data we need,
  95. // mark the object initialized
  96. if (SUCCEEDED(hr))
  97. {
  98. initialized = true;
  99. }
  100. LOG_HRESULT(hr);
  101. return hr;
  102. }
  103. HRESULT
  104. NetworkInterface::GetIPAddressFromWMI()
  105. {
  106. LOG_FUNCTION(NetworkInterface::GetIPAddressFromWMI);
  107. HRESULT hr = S_OK;
  108. do
  109. {
  110. _variant_t var;
  111. hr = wmiAdapterObject->Get(
  112. CYS_WMIPROP_IPADDRESS,
  113. 0, // flags, reserved, must be zero
  114. &var,
  115. 0, // CIMTYPE
  116. 0); // origin of the property
  117. if (FAILED(hr))
  118. {
  119. LOG(String::format(
  120. L"Unable to retrieve the IPAddress property: hr = 0x%1!x!",
  121. hr));
  122. break;
  123. }
  124. // The IP addresses come as a SAFEARRAY of BSTRs. Convert that to a
  125. // StringList
  126. StringList iplist;
  127. hr = VariantArrayToStringList(&var, iplist);
  128. if (FAILED(hr))
  129. {
  130. LOG(String::format(
  131. L"Unable to convert variant to string list: hr = 0x%1!x!",
  132. hr));
  133. break;
  134. }
  135. hr = SetIPAddresses(iplist);
  136. if (FAILED(hr))
  137. {
  138. LOG(String::format(
  139. L"Failed to convert IP addresses from string: hr = 0x%1!x!",
  140. hr));
  141. break;
  142. }
  143. } while (false);
  144. LOG_HRESULT(hr);
  145. return hr;
  146. }
  147. HRESULT
  148. NetworkInterface::SetIPAddresses(const StringList& ipList)
  149. {
  150. LOG_FUNCTION(NetworkInterface::SetIPAddresses);
  151. HRESULT hr = S_OK;
  152. // if the list already contains some entries, delete them and start over
  153. ipaddressString.erase();
  154. if (!ipaddresses.empty())
  155. {
  156. ipaddresses.erase(ipaddresses.begin());
  157. }
  158. // Loop through the string list converting all string IP addresses
  159. // to DWORD IP addresses and add them to the ipaddresses array
  160. int addressesAdded = 0;
  161. for (
  162. StringList::iterator itr = ipList.begin();
  163. itr != ipList.end();
  164. ++itr)
  165. {
  166. String entry = *itr;
  167. // Add the ipaddress to the semicolon delimited string
  168. if (addressesAdded > 0)
  169. {
  170. ipaddressString += L";";
  171. }
  172. ipaddressString += entry;
  173. // Convert the string to ansi so that we can use inet_addr
  174. // to convert to an IP address DWORD
  175. AnsiString ansi;
  176. String::ConvertResult convertResult = entry.convert(ansi);
  177. if (String::CONVERT_SUCCESSFUL == convertResult)
  178. {
  179. // Convert and add the new address to the array
  180. DWORD newAddress = inet_addr(ansi.c_str());
  181. ASSERT(newAddress != INADDR_NONE);
  182. ipaddresses.push_back(newAddress);
  183. ++addressesAdded;
  184. }
  185. else
  186. {
  187. LOG(String::format(
  188. L"Failed to convert address: %1: hr = 0x%2!x!",
  189. entry.c_str(),
  190. hr));
  191. continue;
  192. }
  193. }
  194. ipaddrCount = addressesAdded;
  195. ASSERT(ipaddrCount <= ipList.size());
  196. LOG_HRESULT(hr);
  197. return hr;
  198. }
  199. DWORD
  200. NetworkInterface::GetIPAddress(DWORD addressIndex) const
  201. {
  202. LOG_FUNCTION2(
  203. NetworkInterface::GetIPAddress,
  204. String::format(
  205. L"%1!d!",
  206. addressIndex));
  207. ASSERT(initialized);
  208. ASSERT(addressIndex <= ipaddrCount);
  209. return ipaddresses[addressIndex];
  210. }
  211. String
  212. NetworkInterface::GetStringIPAddress() const
  213. {
  214. LOG_FUNCTION(NetworkInterface::GetStringIPAddress);
  215. return ipaddressString;
  216. }
  217. HRESULT
  218. NetworkInterface::GetDHCPEnabledFromWMI()
  219. {
  220. LOG_FUNCTION(NetworkInterface::GetDHCPEnabledFromWMI);
  221. HRESULT hr = S_OK;
  222. do
  223. {
  224. _variant_t var;
  225. hr = wmiAdapterObject->Get(
  226. CYS_WMIPROP_DHCPENABLED,
  227. 0, // flags, reserved, must be zero
  228. &var,
  229. 0, // CIMTYPE
  230. 0); // origin of the property
  231. if (FAILED(hr))
  232. {
  233. LOG(String::format(
  234. L"Unable to retrieve the IPAddress property: hr = 0x%1!x!",
  235. hr));
  236. break;
  237. }
  238. ASSERT(V_VT(&var) == (VT_BOOL));
  239. dhcpEnabled = (V_BOOL(&var) != 0);
  240. } while(false);
  241. LOG_HRESULT(hr);
  242. return hr;
  243. }
  244. bool
  245. NetworkInterface::RenewDHCPLease()
  246. {
  247. LOG_FUNCTION(NetworkInterface::RenewDHCPLease);
  248. bool found = false;
  249. do
  250. {
  251. for(DWORD i = 0; i < ipaddrCount; ++i)
  252. {
  253. found = (IsDHCPAvailableOnInterface(ipaddresses[i]) != 0);
  254. if (found)
  255. {
  256. LOG(String::format(
  257. L"Found DHCP server on: %1!x!",
  258. ipaddresses[i]));
  259. // Then we have to reload the IP addresses because they
  260. // may have been altered by renewing the lease
  261. // return value is ignored
  262. GetIPAddressFromWMI();
  263. break;
  264. }
  265. }
  266. } while(false);
  267. LOG(found ? L"true" : L"false");
  268. return found;
  269. }
  270. String
  271. NetworkInterface::GetDescription() const
  272. {
  273. LOG_FUNCTION(NetworkInterface::GetDescription);
  274. ASSERT(initialized);
  275. String description;
  276. do
  277. {
  278. _variant_t var;
  279. HRESULT hr = wmiAdapterObject->Get(
  280. CYS_WMIPROP_DESCRIPTION,
  281. 0, // flags, reserved, must be zero
  282. &var,
  283. 0, // CIMTYPE
  284. 0); // origin of the property
  285. if (FAILED(hr))
  286. {
  287. LOG(String::format(
  288. L"Unable to retrieve the Description property: hr = 0x%1!x!",
  289. hr));
  290. break;
  291. }
  292. ASSERT(V_VT(&var) == (VT_BSTR));
  293. description = V_BSTR(&var);
  294. } while (false);
  295. LOG(description);
  296. return description;
  297. }