NetConfig.cpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. #include "StdAfx.h"
  2. #include "NetConfigCommon.h"
  3. #include "NetConfig.h"
  4. #pragma comment(lib, "wbemuuid.lib")
  5. #pragma comment(lib, "comsuppw.lib")
  6. //#pragma execution_character_set("utf-8")
  7. using namespace std;
  8. NetConfig::~NetConfig()
  9. {
  10. clear();
  11. }
  12. bool NetConfig::enable_dhcp()
  13. {
  14. bool rt = false;
  15. if (!init())
  16. return rt;
  17. return exec_method(L"EnableDHCP", NULL);
  18. }
  19. bool NetConfig::set_ip_config(const std::string& ip, const std::string& mask, const std::string& gateway)
  20. {
  21. if (set_ip_config(ip, mask)) {
  22. return set_gateway(gateway);
  23. }
  24. return false;
  25. }
  26. bool NetConfig::set_ip_config(const std::string& ip, const std::string& mask)
  27. {
  28. bool rt = false;
  29. if (!init())
  30. return rt;
  31. IWbemClassObject* params = NULL;
  32. IWbemClassObject* paramsInst = NULL;
  33. p_config->GetMethod(_bstr_t("EnableStatic"), 0, &params, NULL);
  34. params->SpawnInstance(0, &paramsInst);
  35. std::vector<std::string> args;
  36. args.push_back(ip);
  37. auto p1 = create_SAFEARRAY(args);
  38. ; //auto p1 = create_SAFEARRAY({ ip });
  39. VARIANT paramVt;
  40. paramVt.vt = VT_ARRAY | VT_BSTR;
  41. paramVt.parray = p1.get();
  42. paramsInst->Put(L"IPAddress", 0, &paramVt, NULL);
  43. args.clear();
  44. args.push_back(mask);
  45. p1 = create_SAFEARRAY(args);
  46. //p1 = create_SAFEARRAY({ mask });
  47. paramVt.parray = p1.get();
  48. paramsInst->Put(L"SubnetMask", 0, &paramVt, NULL);
  49. rt = exec_method(L"EnableStatic", paramsInst);
  50. if (params) {
  51. params->Release();
  52. }
  53. return rt;
  54. }
  55. bool NetConfig::set_dns(const std::string& default_dns, const std::string& backup_dns)
  56. {
  57. return set_dns_base(false, default_dns, backup_dns);
  58. }
  59. bool NetConfig::set_auto_dns()
  60. {
  61. return set_dns_base(true, "", "");
  62. }
  63. bool NetConfig::set_gateway(const std::string& gateway)
  64. {
  65. bool rt = false;
  66. if (!init())
  67. return rt;
  68. IWbemClassObject* params = NULL;
  69. IWbemClassObject* paramsInst = NULL;
  70. p_config->GetMethod(_bstr_t("SetGateways"), 0, &params, NULL);
  71. params->SpawnInstance(0, &paramsInst);
  72. std::vector<std::string> args;
  73. args.push_back(gateway);
  74. auto p1 = create_SAFEARRAY(args);
  75. //auto p1 = create_SAFEARRAY({ gateway });
  76. VARIANT paramVt;
  77. paramVt.vt = VT_ARRAY | VT_BSTR;
  78. paramVt.parray = p1.get();
  79. paramsInst->Put(L"DefaultIPGateway", 0, &paramVt, NULL);
  80. paramVt.vt = VT_UINT;
  81. paramVt.uintVal = 1;
  82. paramsInst->Put(L"GatewayCostMetric", 0, &paramVt, NULL);
  83. rt = exec_method(L"SetGateways", paramsInst);
  84. if (params) {
  85. params->Release();
  86. }
  87. return rt;
  88. }
  89. void NetConfig::clear()
  90. {
  91. if (p_config) {
  92. p_config->Release();
  93. p_config = nullptr;
  94. }
  95. if (p_obj_) {
  96. p_obj_->Release();
  97. p_obj_ = nullptr;
  98. }
  99. if (p_enum_) {
  100. p_enum_->Release();
  101. p_enum_ = nullptr;
  102. }
  103. if (p_service_) {
  104. p_service_->Release();
  105. p_service_ = nullptr;
  106. }
  107. if (p_instance_) {
  108. p_instance_->Release();
  109. p_instance_ = nullptr;
  110. }
  111. if (is_init_) {
  112. CoUninitialize();
  113. }
  114. is_init_ = false;
  115. }
  116. bool NetConfig::init()
  117. {
  118. if (is_init_) {
  119. return true;
  120. }
  121. // Step 1: Initialize COM.
  122. HRESULT hres = CoInitializeEx(0, COINIT_MULTITHREADED);
  123. if (FAILED(hres)) {
  124. #ifdef _DEBUG
  125. cout << "CoInitializeEx failed: " << hres << endl;
  126. #endif
  127. return false;
  128. }
  129. // Step 3: Obtain the initial locator to WMI
  130. hres = CoCreateInstance(
  131. CLSID_WbemLocator,
  132. 0,
  133. CLSCTX_INPROC_SERVER,
  134. IID_IWbemLocator,
  135. (LPVOID*)&p_instance_);
  136. //ASSERT_THROW(SUCCEEDED(hres), "CoCreateInstance failed");
  137. if (FAILED(hres)) {
  138. #ifdef _DEBUG
  139. cout << "CoCreateInstance failed: " << hres << endl;
  140. #endif
  141. return false;
  142. }
  143. // Step 4: Connect to the local root\cimv2 namespace and obtain pointer pSvc to make IWbemServices calls.
  144. hres = p_instance_->ConnectServer(
  145. _bstr_t(L"ROOT\\CIMV2"),
  146. NULL,
  147. NULL,
  148. 0,
  149. NULL,
  150. 0,
  151. 0,
  152. &p_service_
  153. );
  154. //ASSERT_THROW(SUCCEEDED(hres), "ConnectServer failed");
  155. if (FAILED(hres)) {
  156. #ifdef _DEBUG
  157. cout << "ConnectServer failed: " << hres << endl;
  158. #endif
  159. return false;
  160. }
  161. // Step 5: Set security levels for the proxy
  162. hres = CoSetProxyBlanket(
  163. p_service_, // Indicates the proxy to set
  164. RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
  165. RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
  166. NULL, // Server principal name
  167. RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
  168. RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
  169. NULL, // client identity
  170. EOAC_NONE // proxy capabilities
  171. );
  172. //ASSERT_THROW(SUCCEEDED(hres), "CoSetProxyBlanket failed");
  173. if (FAILED(hres)) {
  174. #ifdef _DEBUG
  175. cout << "CoSetProxyBlanket failed: " << hres << endl;
  176. #endif
  177. return false;
  178. }
  179. // 通过适配器名称来找到指定的适配器对象.
  180. CComBSTR TheQuery = L"SELECT * FROM Win32_NetworkAdapterConfiguration WHERE SettingID = \"";
  181. std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> conversion;
  182. TheQuery += conversion.from_bytes(key_).c_str();
  183. TheQuery += L"\"";
  184. // const BSTR lang = L"WQL";
  185. hres = p_service_->ExecQuery(
  186. SysAllocString(L"WQL"),
  187. // L"WQL",
  188. TheQuery,
  189. WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
  190. NULL,
  191. &p_enum_);
  192. //ASSERT_THROW(SUCCEEDED(hres), "ExecQuery failed");
  193. if (FAILED(hres)) {
  194. #ifdef _DEBUG
  195. cout << "ExecQuery failed: " << hres << endl;
  196. #endif
  197. return false;
  198. }
  199. // Get the adapter object.
  200. ULONG num = 0;
  201. hres = p_enum_->Next(WBEM_INFINITE, 1, &p_obj_, &num);
  202. //ASSERT_THROW(SUCCEEDED(hres), "Next failed");
  203. if (FAILED(hres)) {
  204. #ifdef _DEBUG
  205. cout << "Next failed: " << hres << endl;
  206. #endif
  207. return false;
  208. }
  209. //ASSERT_THROW(0 < num, "Next failed");
  210. if (num < 1) {
  211. #ifdef _DEBUG
  212. cout << "Next failed num < 1" << endl;
  213. #endif
  214. return false;
  215. }
  216. VariantInit(&path_);
  217. hres = p_obj_->Get(L"__PATH", 0, &path_, NULL, NULL);
  218. //ASSERT_THROW(SUCCEEDED(hres), "Get path failed");
  219. if (FAILED(hres)) {
  220. #ifdef _DEBUG
  221. cout << "Get failed: " << hres << endl;
  222. #endif
  223. return false;
  224. }
  225. hres = p_service_->GetObject(_bstr_t(L"Win32_NetworkAdapterConfiguration"), 0, NULL, &p_config, NULL);
  226. //ASSERT_THROW(SUCCEEDED(hres), "GetObject Win32_NetworkAdapterConfiguration failed");
  227. if (FAILED(hres)) {
  228. #ifdef _DEBUG
  229. cout << "GetObject failed: " << hres << endl;
  230. #endif
  231. return false;
  232. }
  233. is_init_ = true;
  234. return true;
  235. }
  236. std::shared_ptr<SAFEARRAY> NetConfig::create_SAFEARRAY(const std::vector<std::string>& args)
  237. {
  238. SAFEARRAY* psa = SafeArrayCreateVector(VT_BSTR, 0, args.size());
  239. long idx[] = { 0 };
  240. for (int i = 0; i < args.size(); i++) {
  241. std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> conversion;
  242. BSTR ip = SysAllocString(conversion.from_bytes(args[i]).c_str());
  243. idx[0] = i;
  244. if (FAILED(SafeArrayPutElement(psa, idx, ip))) {
  245. return (false);
  246. }
  247. SysFreeString(ip);
  248. }
  249. return shared_ptr<SAFEARRAY>(psa, [](SAFEARRAY* psa) {SafeArrayDestroy(psa); });
  250. }
  251. bool NetConfig::set_dns_base(bool is_auto, const std::string& default_dns, const std::string& backup_dns)
  252. {
  253. bool rt = false;
  254. if (!init())
  255. return rt;
  256. IWbemClassObject* params = NULL;
  257. IWbemClassObject* paramsInst = NULL;
  258. p_config->GetMethod(_bstr_t("SetDNSServerSearchOrder"), 0, &params, NULL);
  259. params->SpawnInstance(0, &paramsInst);
  260. shared_ptr<SAFEARRAY> p1;
  261. if (is_auto) {
  262. paramsInst->Put(L"DNSServerSearchOrder", 0, NULL, NULL);
  263. }
  264. else {
  265. std::vector<std::string> args;
  266. if (backup_dns.size()) {
  267. args.push_back(default_dns);
  268. args.push_back(backup_dns);
  269. p1 = create_SAFEARRAY(args);
  270. //p1 = create_SAFEARRAY({ default_dns, backup_dns });
  271. }
  272. else {
  273. args.push_back(default_dns);
  274. p1 = create_SAFEARRAY(args);
  275. //p1 = create_SAFEARRAY({ default_dns });
  276. }
  277. VARIANT paramVt;
  278. paramVt.vt = VT_ARRAY | VT_BSTR;
  279. paramVt.parray = p1.get();
  280. paramsInst->Put(L"DNSServerSearchOrder", 0, &paramVt, NULL);
  281. }
  282. rt = exec_method(L"SetDNSServerSearchOrder", paramsInst);
  283. if (params) {
  284. params->Release();
  285. }
  286. return rt;
  287. }
  288. bool NetConfig::exec_method(const wchar_t* method, IWbemClassObject* params_instance)
  289. {
  290. bool rt = false;
  291. IWbemClassObject* results = NULL;
  292. auto res = p_service_->ExecMethod(path_.bstrVal, _bstr_t(method), 0, NULL, params_instance, &results, NULL);
  293. if (SUCCEEDED(res)) {
  294. VARIANT vtRet;
  295. VariantInit(&vtRet);
  296. if (!FAILED(results->Get(L"ReturnValue", 0, &vtRet, NULL, 0))) {
  297. if (vtRet.uintVal == 0 || vtRet.uintVal == 1) {
  298. rt = true;
  299. }
  300. else {
  301. last_error_code_ = vtRet.uintVal;
  302. #ifdef _DEBUG
  303. wcout << method << " failed, result: " << last_error_code_ << endl;
  304. #endif
  305. }
  306. }
  307. #ifdef _DEBUG
  308. else {
  309. cout << "ExecMethod Get ReturnValue failed: " << res << endl;
  310. }
  311. #endif
  312. VariantClear(&vtRet);
  313. results->Release();
  314. }
  315. #ifdef _DEBUG
  316. else {
  317. cout << "ExecMethod failed: " << res << endl;
  318. }
  319. #endif
  320. if (params_instance) {
  321. params_instance->Release();
  322. }
  323. return rt;
  324. }