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.

530 lines
13 KiB

  1. // Copyright (c) 1997-2001 Microsoft Corporation
  2. //
  3. // File: DHCPInstallationUnit.cpp
  4. //
  5. // Synopsis: Defines a DHCPInstallationUnit
  6. // This object has the knowledge for installing the
  7. // DHCP service
  8. //
  9. // History: 02/05/2001 JeffJon Created
  10. #include "pch.h"
  11. #include "resource.h"
  12. #include "DHCPInstallationUnit.h"
  13. #include "InstallationUnitProvider.h"
  14. DHCPInstallationUnit::DHCPInstallationUnit() :
  15. isExpressPathInstall(false),
  16. startIPAddress(0),
  17. endIPAddress(0),
  18. NetworkServiceInstallationBase(
  19. IDS_DHCP_SERVER_TYPE,
  20. IDS_DHCP_SERVER_DESCRIPTION,
  21. IDS_DHCP_SERVER_DESCRIPTION_INSTALLED,
  22. DHCP_INSTALL)
  23. {
  24. LOG_CTOR(DHCPInstallationUnit);
  25. }
  26. DHCPInstallationUnit::~DHCPInstallationUnit()
  27. {
  28. LOG_DTOR(DHCPInstallationUnit);
  29. }
  30. InstallationReturnType
  31. DHCPInstallationUnit::InstallService(HANDLE logfileHandle, HWND hwnd)
  32. {
  33. LOG_FUNCTION(DHCPInstallationUnit::InstallService);
  34. InstallationReturnType result = INSTALL_SUCCESS;
  35. if (IsExpressPathInstall())
  36. {
  37. // This is an express path install. It must be done special
  38. result = ExpressPathInstall(logfileHandle, hwnd);
  39. LOG_INSTALL_RETURN(result);
  40. return result;
  41. }
  42. String infFileText;
  43. String unattendFileText;
  44. CreateInfFileText(infFileText, IDS_DHCP_INF_WINDOW_TITLE);
  45. CreateUnattendFileText(unattendFileText, CYS_DHCP_SERVICE_NAME);
  46. bool ocmResult = InstallServiceWithOcManager(infFileText, unattendFileText);
  47. if (ocmResult &&
  48. IsServiceInstalled())
  49. {
  50. // Log the successful installation
  51. LOG(L"DHCP was installed successfully");
  52. CYS_APPEND_LOG(String::load(IDS_LOG_INSTALL_START_DHCP));
  53. // Run the DHCP Wizard
  54. String resultText;
  55. if (ExecuteWizard(CYS_DHCP_SERVICE_NAME, resultText))
  56. {
  57. // Check to be sure the wizard finished completely
  58. String configWizardResults;
  59. if (IsDhcpConfigured())
  60. {
  61. // The New Scope Wizard completed successfully
  62. LOG(L"DHCP installed and the New Scope Wizard completed successfully");
  63. CYS_APPEND_LOG(String::load(IDS_LOG_DHCP_COMPLETED_SUCCESSFULLY));
  64. }
  65. else
  66. {
  67. // The New Scope Wizard did not finish successfully
  68. LOG(L"DHCP installed successfully, but a problem occurred during the New Scope Wizard");
  69. CYS_APPEND_LOG(String::load(IDS_LOG_DHCP_WIZARD_ERROR));
  70. }
  71. }
  72. else
  73. {
  74. // Log an error
  75. LOG(L"DHCP could not be installed.");
  76. if (!resultText.empty())
  77. {
  78. CYS_APPEND_LOG(resultText);
  79. }
  80. }
  81. }
  82. else
  83. {
  84. // Log the failure
  85. LOG(L"DHCP failed to install");
  86. CYS_APPEND_LOG(String::load(IDS_LOG_DHCP_INSTALL_FAILED));
  87. result = INSTALL_FAILURE;
  88. }
  89. LOG_INSTALL_RETURN(result);
  90. return result;
  91. }
  92. InstallationReturnType
  93. DHCPInstallationUnit::ExpressPathInstall(HANDLE /*logfileHandle*/, HWND /*hwnd*/)
  94. {
  95. LOG_FUNCTION(DHCPInstallationUnit::ExpressPathInstall);
  96. InstallationReturnType result = INSTALL_SUCCESS;
  97. String infFileText;
  98. String unattendFileText;
  99. String commandline;
  100. CreateInfFileText(infFileText, IDS_DHCP_INF_WINDOW_TITLE);
  101. CreateUnattendFileTextForExpressPath(unattendFileText);
  102. do
  103. {
  104. bool ocmResult = InstallServiceWithOcManager(infFileText, unattendFileText);
  105. if (ocmResult &&
  106. !IsServiceInstalled())
  107. {
  108. result = INSTALL_FAILURE;
  109. LOG(L"DHCP installation failed");
  110. break;
  111. }
  112. else
  113. {
  114. HRESULT hr = S_OK;
  115. DWORD exitCode = 0;
  116. String ipaddressString =
  117. InstallationUnitProvider::GetInstance().GetDNSInstallationUnit().GetStaticIPAddressString();
  118. String subnetMaskString =
  119. InstallationUnitProvider::GetInstance().GetDNSInstallationUnit().GetSubnetMaskString();
  120. do
  121. {
  122. commandline = L"netsh dhcp server add optiondef 6 \"DNS Servers\" IPADDRESS 1";
  123. hr = CreateAndWaitForProcess(commandline, exitCode);
  124. if (FAILED(hr))
  125. {
  126. LOG(String::format(
  127. L"Failed to run DHCP options: hr = %1!x!",
  128. hr));
  129. break;
  130. }
  131. if (exitCode != 1)
  132. {
  133. LOG(String::format(
  134. L"Failed to run DHCP options: exitCode = %1!x!",
  135. exitCode));
  136. break;
  137. }
  138. commandline.format(
  139. L"netsh dhcp server set optionvalue 6 IPADDRESS %1",
  140. ipaddressString);
  141. exitCode = 0;
  142. hr = CreateAndWaitForProcess(commandline, exitCode);
  143. if (FAILED(hr))
  144. {
  145. LOG(String::format(
  146. L"Failed to run DHCP server IP address: hr = %1!x!",
  147. hr));
  148. break;
  149. }
  150. if (exitCode != 1)
  151. {
  152. LOG(String::format(
  153. L"Failed to run DHCP server IP address: exitCode = %1!x!",
  154. exitCode));
  155. break;
  156. }
  157. } while (false);
  158. // Set the subnet mask
  159. DWORD staticipaddress =
  160. InstallationUnitProvider::GetInstance().GetDNSInstallationUnit().GetStaticIPAddress();
  161. DWORD subnetMask =
  162. InstallationUnitProvider::GetInstance().GetDNSInstallationUnit().GetSubnetMask();
  163. DWORD subnet = staticipaddress & subnetMask;
  164. String subnetString = String::format(
  165. L"%1!d!.%2!d!.%3!d!.%4!d!",
  166. FIRST_IPADDRESS(subnet),
  167. SECOND_IPADDRESS(subnet),
  168. THIRD_IPADDRESS(subnet),
  169. FOURTH_IPADDRESS(subnet));
  170. commandline.format(
  171. L"netsh dhcp server 127.0.0.1 add scope %1 %2 Scope1",
  172. subnetString.c_str(),
  173. subnetMaskString.c_str());
  174. exitCode = 0;
  175. hr = CreateAndWaitForProcess(commandline, exitCode);
  176. if (FAILED(hr))
  177. {
  178. LOG(String::format(
  179. L"Failed to set DHCP address and subnet: hr = %1!x!",
  180. hr));
  181. break;
  182. }
  183. if (exitCode != 1)
  184. {
  185. LOG(String::format(
  186. L"Failed to set DHCP address and subnet: exitCode = %1!x!",
  187. exitCode));
  188. break;
  189. }
  190. // Set the DHCP scopes
  191. commandline.format(
  192. L"netsh dhcp server 127.0.0.1 add scope %1 add iprange %2 %3 both",
  193. subnetString.c_str(),
  194. GetStartIPAddressString().c_str(),
  195. GetEndIPAddressString().c_str());
  196. exitCode = 0;
  197. hr = CreateAndWaitForProcess(commandline, exitCode);
  198. if (FAILED(hr))
  199. {
  200. LOG(String::format(
  201. L"Failed to set DHCP scopes: hr = %1!x!",
  202. hr));
  203. break;
  204. }
  205. if (exitCode != 1)
  206. {
  207. LOG(String::format(
  208. L"Failed to set DHCP scopes: exitCode = %1!x!",
  209. exitCode));
  210. break;
  211. }
  212. // Set the DHCP scope lease time
  213. commandline = L"netsh dhcp server 127.0.0.1 add optiondef 51 LeaseTime DWORD";
  214. exitCode = 0;
  215. hr = CreateAndWaitForProcess(commandline, exitCode);
  216. if (FAILED(hr))
  217. {
  218. LOG(String::format(
  219. L"Failed to set DHCP scope lease time: hr = %1!x!",
  220. hr));
  221. break;
  222. }
  223. if (exitCode != 1)
  224. {
  225. LOG(String::format(
  226. L"Failed to set DHCP scope lease time: exitCode = %1!x!",
  227. exitCode));
  228. break;
  229. }
  230. // Set the DHCP scope lease time value
  231. commandline.format(
  232. L"netsh dhcp server 127.0.0.1 scope %1 set optionvalue 51 dword 874800",
  233. subnetString.c_str());
  234. exitCode = 0;
  235. hr = CreateAndWaitForProcess(commandline, exitCode);
  236. if (FAILED(hr))
  237. {
  238. LOG(String::format(
  239. L"Failed to set DHCP scope lease time value: hr = %1!x!",
  240. hr));
  241. break;
  242. }
  243. if (exitCode != 1)
  244. {
  245. LOG(String::format(
  246. L"Failed to set DHCP scope lease time value: exitCode = %1!x!",
  247. exitCode));
  248. break;
  249. }
  250. }
  251. } while (false);
  252. LOG_INSTALL_RETURN(result);
  253. return result;
  254. }
  255. void
  256. DHCPInstallationUnit::CreateUnattendFileTextForExpressPath(
  257. String& unattendFileText)
  258. {
  259. LOG_FUNCTION(DHCPInstallationUnit::CreateUnattendFileText);
  260. unattendFileText = L"[NetOptionalComponents]\n";
  261. unattendFileText += L"DHCPServer=1\n";
  262. unattendFileText += L"[dhcpserver]\n";
  263. unattendFileText += L"Subnets=192.168.16.2\n";
  264. // Add the DHCP scope
  265. unattendFileText += L"StartIP=";
  266. unattendFileText += GetStartIPAddressString();
  267. unattendFileText += L"EndIp=";
  268. unattendFileText += GetEndIPAddressString();
  269. // Add subnet mask
  270. unattendFileText += L"SubnetMask=255.255.255.0\n";
  271. unattendFileText += L"LeaseDuration=874800\n";
  272. // The DNS server IP
  273. String dnsIPString = InstallationUnitProvider::GetInstance().GetDNSInstallationUnit().GetStaticIPAddressString();
  274. unattendFileText += String::format(
  275. L"DnsServer=%1",
  276. dnsIPString.c_str());
  277. // The domain name
  278. unattendFileText += String::format(
  279. L"DomainName=%1\n",
  280. InstallationUnitProvider::GetInstance().GetADInstallationUnit().GetNewDomainDNSName());
  281. }
  282. bool
  283. DHCPInstallationUnit::IsServiceInstalled()
  284. {
  285. LOG_FUNCTION(DHCPInstallationUnit::IsServiceInstalled);
  286. bool result = IsServiceInstalledHelper(CYS_DHCP_SERVICE_NAME);
  287. LOG_BOOL(result);
  288. return result;
  289. }
  290. bool
  291. DHCPInstallationUnit::IsConfigured()
  292. {
  293. LOG_FUNCTION(DHCPInstallationUnit::IsConfigured);
  294. return IsDhcpConfigured();
  295. }
  296. bool
  297. DHCPInstallationUnit::GetFinishText(String& message)
  298. {
  299. LOG_FUNCTION(DHCPInstallationUnit::GetFinishText);
  300. if (IsExpressPathInstall())
  301. {
  302. }
  303. else
  304. {
  305. message = String::load(IDS_DHCP_FINISH_TEXT);
  306. }
  307. LOG_BOOL(true);
  308. return true;
  309. }
  310. bool
  311. DHCPInstallationUnit::AuthorizeDHCPScope(const String& dnsName) const
  312. {
  313. LOG_FUNCTION(DHCPInstallationUnit::AuthorizeDHCPScope);
  314. bool result = true;
  315. do
  316. {
  317. String domainDNSIP;
  318. result = GetRegKeyValue(
  319. CYS_DHCP_DOMAIN_IP_REGKEY,
  320. CYS_DHCP_DOMAIN_IP_VALUE,
  321. domainDNSIP);
  322. if (!result)
  323. {
  324. LOG(L"Failed to read domain DNS IP from registry");
  325. break;
  326. }
  327. // Authorize the DHCP scope
  328. String commandline;
  329. commandline = L"netsh dhcp add server ";
  330. commandline += dnsName;
  331. commandline += L" ";
  332. commandline += domainDNSIP;
  333. DWORD exitCode = 0;
  334. HRESULT hr = CreateAndWaitForProcess(commandline, exitCode);
  335. if (FAILED(hr))
  336. {
  337. LOG(String::format(
  338. L"Failed to run DHCP authorization: hr = %1!x!",
  339. hr));
  340. result = false;
  341. break;
  342. }
  343. if (exitCode != 1)
  344. {
  345. result = false;
  346. break;
  347. }
  348. } while (false);
  349. LOG_BOOL(result);
  350. return result;
  351. }
  352. void
  353. DHCPInstallationUnit::SetExpressPathInstall(bool isExpressPath)
  354. {
  355. LOG_FUNCTION2(
  356. DHCPInstallationUnit::SetExpressPathInstall,
  357. (isExpressPath) ? L"true" : L"false");
  358. isExpressPathInstall = isExpressPath;
  359. }
  360. bool
  361. DHCPInstallationUnit::IsExpressPathInstall() const
  362. {
  363. LOG_FUNCTION(DHCPInstallationUnit::IsExpressPathInstall);
  364. return isExpressPathInstall;
  365. }
  366. void
  367. DHCPInstallationUnit::SetStartIPAddress(DWORD ipaddress)
  368. {
  369. LOG_FUNCTION2(
  370. DHCPInstallationUnit::SetStartIPAddress,
  371. String::format(L"0x%1!x!", ipaddress));
  372. startIPAddress = ipaddress;
  373. }
  374. void
  375. DHCPInstallationUnit::SetEndIPAddress(DWORD ipaddress)
  376. {
  377. LOG_FUNCTION2(
  378. DHCPInstallationUnit::SetEndIPAddress,
  379. String::format(L"0x%1!x!", ipaddress));
  380. endIPAddress = ipaddress;
  381. }
  382. String
  383. DHCPInstallationUnit::GetStartIPAddressString() const
  384. {
  385. LOG_FUNCTION(DHCPInstallationUnit::GetStartIPAddressString);
  386. String result = String::format(
  387. L"%1!d!.%2!d!.%3!d!.%4!d!",
  388. FIRST_IPADDRESS(startIPAddress),
  389. SECOND_IPADDRESS(startIPAddress),
  390. THIRD_IPADDRESS(startIPAddress),
  391. FOURTH_IPADDRESS(startIPAddress));
  392. LOG(result);
  393. return result;
  394. }
  395. String
  396. DHCPInstallationUnit::GetEndIPAddressString() const
  397. {
  398. LOG_FUNCTION(DHCPInstallationUnit::GetEndIPAddressString);
  399. String result = String::format(
  400. L"%1!d!.%2!d!.%3!d!.%4!d!",
  401. FIRST_IPADDRESS(endIPAddress),
  402. SECOND_IPADDRESS(endIPAddress),
  403. THIRD_IPADDRESS(endIPAddress),
  404. FOURTH_IPADDRESS(endIPAddress));
  405. LOG(result);
  406. return result;
  407. }