Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1132 lines
31 KiB

  1. // Copyright (c) 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. // Finish page help
  15. extern PCWSTR CYS_DHCP_FINISH_PAGE_HELP = L"cys.chm::/dhcp_server_role.htm";
  16. static PCWSTR CYS_DHCP_MILESTONE_HELP = L"cys.chm::/dhcp_server_role.htm#dhcpsrvsummary";
  17. static PCWSTR CYS_DHCP_AFTER_FINISH_HELP = L"cys.chm::/dhcp_server_role.htm#dhcpsrvcompletion";
  18. DHCPInstallationUnit::DHCPInstallationUnit() :
  19. startIPAddress(0),
  20. endIPAddress(0),
  21. scopeCalculated(false),
  22. dhcpRoleResult(DHCP_SUCCESS),
  23. installedDescriptionID(IDS_DHCP_SERVER_DESCRIPTION_INSTALLED),
  24. ExpressPathInstallationUnitBase(
  25. IDS_DHCP_SERVER_TYPE,
  26. IDS_DHCP_SERVER_DESCRIPTION,
  27. IDS_DHCP_FINISH_TITLE,
  28. IDS_DHCP_FINISH_UNINSTALL_TITLE,
  29. IDS_DHCP_FINISH_MESSAGE,
  30. IDS_DHCP_INSTALL_FAILED,
  31. IDS_DHCP_UNINSTALL_MESSAGE,
  32. IDS_DHCP_UNINSTALL_FAILED,
  33. IDS_DHCP_UNINSTALL_WARNING,
  34. IDS_DHCP_UNINSTALL_CHECKBOX,
  35. CYS_DHCP_FINISH_PAGE_HELP,
  36. CYS_DHCP_MILESTONE_HELP,
  37. CYS_DHCP_AFTER_FINISH_HELP,
  38. DHCP_SERVER)
  39. {
  40. LOG_CTOR(DHCPInstallationUnit);
  41. }
  42. DHCPInstallationUnit::~DHCPInstallationUnit()
  43. {
  44. LOG_DTOR(DHCPInstallationUnit);
  45. }
  46. InstallationReturnType
  47. DHCPInstallationUnit::InstallService(HANDLE logfileHandle, HWND hwnd)
  48. {
  49. LOG_FUNCTION(DHCPInstallationUnit::InstallService);
  50. InstallationReturnType result = INSTALL_SUCCESS;
  51. if (IsExpressPathInstall())
  52. {
  53. // This is an express path install. It must be done special
  54. result = ExpressPathInstall(logfileHandle, hwnd);
  55. LOG_INSTALL_RETURN(result);
  56. return result;
  57. }
  58. dhcpRoleResult = DHCP_SUCCESS;
  59. // Log the DHCP header
  60. CYS_APPEND_LOG(String::load(IDS_LOG_DHCP_HEADER));
  61. UpdateInstallationProgressText(hwnd, IDS_DHCP_INSTALL_PROGRESS);
  62. String infFileText;
  63. String unattendFileText;
  64. CreateInfFileText(infFileText, IDS_DHCP_INF_WINDOW_TITLE);
  65. CreateUnattendFileText(unattendFileText, CYS_DHCP_SERVICE_NAME);
  66. // We are ignoring the ocmresult because it doesn't matter
  67. // with respect to whether the role is installed or not
  68. InstallServiceWithOcManager(infFileText, unattendFileText);
  69. if (IsServiceInstalled())
  70. {
  71. // Log the successful installation
  72. LOG(L"DHCP was installed successfully");
  73. CYS_APPEND_LOG(String::load(IDS_LOG_SERVER_START_DHCP));
  74. // Wait for the service to enter the running state
  75. NTService serviceObject(CYS_DHCP_SERVICE_NAME);
  76. HRESULT hr = serviceObject.WaitForServiceState(SERVICE_RUNNING);
  77. if (FAILED(hr))
  78. {
  79. // Remember where the failure happened
  80. dhcpRoleResult = DHCP_INSTALL_FAILURE;
  81. LOG(String::format(
  82. L"The DHCP service failed to start in a timely fashion: %1!x!",
  83. hr));
  84. CYS_APPEND_LOG(String::load(IDS_LOG_DHCP_WIZARD_ERROR));
  85. result = INSTALL_FAILURE;
  86. }
  87. else
  88. {
  89. // Run the DHCP Wizard
  90. String resultText;
  91. HRESULT unused = S_OK;
  92. UpdateInstallationProgressText(hwnd, IDS_DHCP_CONFIG_PROGRESS);
  93. if (ExecuteWizard(hwnd, CYS_DHCP_SERVICE_NAME, resultText, unused))
  94. {
  95. // Check to be sure the wizard finished completely
  96. String configWizardResults;
  97. bool regkeyResult = GetRegKeyValue(
  98. CYS_DHCP_DOMAIN_IP_REGKEY,
  99. CYS_DHCP_WIZARD_RESULT,
  100. configWizardResults,
  101. HKEY_CURRENT_USER);
  102. if (IsDhcpConfigured() &&
  103. (!regkeyResult ||
  104. configWizardResults.empty()))
  105. {
  106. // The New Scope Wizard completed successfully
  107. LOG(L"DHCP installed and the New Scope Wizard completed successfully");
  108. CYS_APPEND_LOG(String::load(IDS_LOG_DHCP_COMPLETED_SUCCESSFULLY));
  109. }
  110. else if(regkeyResult &&
  111. !configWizardResults.empty())
  112. {
  113. // Remember where the failure happened
  114. dhcpRoleResult = DHCP_CONFIG_FAILURE;
  115. LOG(L"DHCP was installed but the New Scope Wizard failed or was cancelled");
  116. // NTRAID#NTBUG9-704311-2002/09/16-artm
  117. // Don't include failure string in free builds b/c it is not localized.
  118. #if DBG == 1
  119. CYS_APPEND_LOG(
  120. String::format(
  121. IDS_LOG_DHCP_WIZARD_ERROR_FORMAT,
  122. configWizardResults.c_str()));
  123. #else
  124. CYS_APPEND_LOG(String::load(IDS_LOG_DHCP_WIZARD_ERROR));
  125. #endif
  126. result = INSTALL_FAILURE;
  127. }
  128. else
  129. {
  130. // The New Scope Wizard did not finish successfully
  131. // Remember where the failure happened
  132. dhcpRoleResult = DHCP_CONFIG_FAILURE;
  133. LOG(L"DHCP installed successfully, but a problem occurred during the New Scope Wizard");
  134. CYS_APPEND_LOG(String::load(IDS_LOG_DHCP_WIZARD_ERROR));
  135. result = INSTALL_FAILURE;
  136. }
  137. // reset the regkey to make sure that if someone runs this path
  138. // again we don't still think the wizard was cancelled.
  139. SetRegKeyValue(
  140. CYS_DHCP_DOMAIN_IP_REGKEY,
  141. CYS_DHCP_WIZARD_RESULT,
  142. L"",
  143. HKEY_CURRENT_USER);
  144. }
  145. else
  146. {
  147. // Remember where the failure happened
  148. dhcpRoleResult = DHCP_CONFIG_FAILURE;
  149. // Log an error
  150. LOG(L"DHCP could not be installed.");
  151. if (!resultText.empty())
  152. {
  153. CYS_APPEND_LOG(resultText);
  154. }
  155. result = INSTALL_FAILURE;
  156. }
  157. }
  158. }
  159. else
  160. {
  161. // Remember where the failure happened
  162. dhcpRoleResult = DHCP_INSTALL_FAILURE;
  163. // Log the failure
  164. LOG(L"DHCP failed to install");
  165. CYS_APPEND_LOG(String::load(IDS_LOG_DHCP_SERVER_FAILED));
  166. result = INSTALL_FAILURE;
  167. }
  168. LOG_INSTALL_RETURN(result);
  169. return result;
  170. }
  171. UnInstallReturnType
  172. DHCPInstallationUnit::UnInstallService(HANDLE logfileHandle, HWND hwnd)
  173. {
  174. LOG_FUNCTION(DHCPInstallationUnit::UnInstallService);
  175. UnInstallReturnType result = UNINSTALL_SUCCESS;
  176. // Log the DHCP header
  177. CYS_APPEND_LOG(String::load(IDS_LOG_UNINSTALL_DHCP_HEADER));
  178. UpdateInstallationProgressText(hwnd, IDS_UNINSTALL_DHCP_PROGRESS);
  179. String infFileText;
  180. String unattendFileText;
  181. CreateInfFileText(infFileText, IDS_DHCP_INF_WINDOW_TITLE);
  182. CreateUnattendFileText(unattendFileText, CYS_DHCP_SERVICE_NAME, false);
  183. // NTRAID#NTBUG9-736557-2002/11/13-JeffJon
  184. // Pass the /w switch to sysocmgr when uninstalling
  185. // so that if a situation occurs in which a reboot
  186. // is required, the user will be prompted.
  187. String additionalArgs = L"/w";
  188. // We are ignoring the ocmresult because it doesn't matter
  189. // with respect to whether the role is installed or not
  190. InstallServiceWithOcManager(
  191. infFileText,
  192. unattendFileText,
  193. additionalArgs);
  194. // Wait for the service to enter the stopped state
  195. NTService serviceObject(CYS_DHCP_SERVICE_NAME);
  196. // ignore the returned value. This is just to wait on the
  197. // service. Use the normal mechanism for determining success
  198. // or failure of the uninstall
  199. serviceObject.WaitForServiceState(SERVICE_STOPPED);
  200. if (IsServiceInstalled())
  201. {
  202. CYS_APPEND_LOG(String::load(IDS_LOG_UNINSTALL_DHCP_FAILED));
  203. result = UNINSTALL_FAILURE;
  204. }
  205. else
  206. {
  207. CYS_APPEND_LOG(String::load(IDS_LOG_UNINSTALL_DHCP_SUCCESS));
  208. }
  209. LOG_UNINSTALL_RETURN(result);
  210. return result;
  211. }
  212. InstallationReturnType
  213. DHCPInstallationUnit::ExpressPathInstall(HANDLE logfileHandle, HWND hwnd)
  214. {
  215. LOG_FUNCTION(DHCPInstallationUnit::ExpressPathInstall);
  216. InstallationReturnType result = INSTALL_SUCCESS;
  217. String infFileText;
  218. String unattendFileText;
  219. String commandline;
  220. String netshPath = GetNetshPath();
  221. do
  222. {
  223. // We ignore if the NIC is found or not because the function will return
  224. // the first NIC if the correct NIC is not found. We can then use this
  225. // to setup the network
  226. NetworkInterface* localNIC =
  227. State::GetInstance().GetLocalNIC();
  228. if (!localNIC)
  229. {
  230. result = INSTALL_FAILURE;
  231. LOG(L"Failed to get local NIC");
  232. InstallationUnitProvider::GetInstance().
  233. GetExpressInstallationUnit().SetExpressRoleResult(
  234. ExpressInstallationUnit::EXPRESS_DHCP_INSTALL_FAILURE);
  235. CYS_APPEND_LOG(String::load(IDS_DHCP_EXPRESS_LOG_FAILURE));
  236. break;
  237. }
  238. // In the case where the public interface has a static IP address
  239. // and the private interface has a DHCP server (whether the NIC
  240. // has a static or dynamic address doesn't matter), we don't want
  241. // to install another DHCP server. So we will just skip it.
  242. if (localNIC->IsDHCPAvailable())
  243. {
  244. LOG(L"DHCP is already on this NIC so don't install");
  245. if (!SetRegKeyValue(
  246. CYS_FIRST_DC_REGKEY,
  247. CYS_FIRST_DC_DHCP_SERVERED,
  248. CYS_DHCP_NOT_SERVERED_VALUE,
  249. HKEY_LOCAL_MACHINE,
  250. true))
  251. {
  252. LOG(L"Failed to set the DHCP installed regkey");
  253. }
  254. CYS_APPEND_LOG(String::load(IDS_DHCP_EXPRESS_LOG_NOT_REQUIRED));
  255. break;
  256. }
  257. UpdateInstallationProgressText(hwnd, IDS_DHCP_INSTALL_PROGRESS);
  258. CreateInfFileText(infFileText, IDS_DHCP_INF_WINDOW_TITLE);
  259. CreateUnattendFileTextForExpressPath(*localNIC, unattendFileText);
  260. bool ocmResult = InstallServiceWithOcManager(infFileText, unattendFileText);
  261. if (ocmResult &&
  262. !IsServiceInstalled())
  263. {
  264. result = INSTALL_FAILURE;
  265. LOG(L"DHCP installation failed");
  266. InstallationUnitProvider::GetInstance().
  267. GetExpressInstallationUnit().SetExpressRoleResult(
  268. ExpressInstallationUnit::EXPRESS_DHCP_INSTALL_FAILURE);
  269. CYS_APPEND_LOG(String::load(IDS_DHCP_EXPRESS_LOG_FAILURE));
  270. break;
  271. }
  272. else
  273. {
  274. if (!SetRegKeyValue(
  275. CYS_FIRST_DC_REGKEY,
  276. CYS_FIRST_DC_DHCP_SERVERED,
  277. CYS_DHCP_SERVERED_VALUE,
  278. HKEY_LOCAL_MACHINE,
  279. true))
  280. {
  281. LOG(L"Failed to set the DHCP installed regkey");
  282. }
  283. HRESULT hr = S_OK;
  284. // Wait for the service to enter the running state
  285. NTService serviceObject(CYS_DHCP_SERVICE_NAME);
  286. hr = serviceObject.WaitForServiceState(SERVICE_RUNNING);
  287. if (FAILED(hr))
  288. {
  289. LOG(String::format(
  290. L"The DHCP service failed to start in a timely fashion: %1!x!",
  291. hr));
  292. result = INSTALL_FAILURE;
  293. InstallationUnitProvider::GetInstance().
  294. GetExpressInstallationUnit().SetExpressRoleResult(
  295. ExpressInstallationUnit::EXPRESS_DHCP_INSTALL_FAILURE);
  296. CYS_APPEND_LOG(String::load(IDS_DHCP_EXPRESS_LOG_FAILURE));
  297. break;
  298. }
  299. CYS_APPEND_LOG(String::load(IDS_DHCP_EXPRESS_LOG_SUCCESS));
  300. UpdateInstallationProgressText(hwnd, IDS_DHCP_CONFIG_PROGRESS);
  301. DWORD exitCode = 0;
  302. String ipaddressString =
  303. localNIC->GetStringIPAddress(0);
  304. String subnetMaskString =
  305. localNIC->GetStringSubnetMask(0);
  306. do
  307. {
  308. commandline = L"dhcp server add optiondef 6 \"DNS Servers\" IPADDRESS 1";
  309. hr = CreateAndWaitForProcess(
  310. netshPath,
  311. commandline,
  312. exitCode,
  313. true);
  314. if (FAILED(hr))
  315. {
  316. LOG(String::format(
  317. L"Failed to run DHCP options: hr = %1!x!",
  318. hr));
  319. break;
  320. }
  321. if (exitCode != 1)
  322. {
  323. LOG(String::format(
  324. L"Failed to run DHCP options: exitCode = %1!x!",
  325. exitCode));
  326. // Don't break here. The most likely error is that the option already
  327. // exists. In which case continue to set the value
  328. }
  329. commandline = String::format(
  330. L"dhcp server set optionvalue 6 IPADDRESS %1",
  331. ipaddressString.c_str());
  332. exitCode = 0;
  333. hr = CreateAndWaitForProcess(
  334. netshPath,
  335. commandline,
  336. exitCode,
  337. true);
  338. if (FAILED(hr))
  339. {
  340. LOG(String::format(
  341. L"Failed to run DHCP server IP address: hr = %1!x!",
  342. hr));
  343. break;
  344. }
  345. if (exitCode != 1)
  346. {
  347. LOG(String::format(
  348. L"Failed to run DHCP server IP address: exitCode = %1!x!",
  349. exitCode));
  350. //break;
  351. }
  352. } while (false);
  353. // Set the subnet mask
  354. DWORD staticipaddress =
  355. localNIC->GetIPAddress(0);
  356. DWORD subnetMask =
  357. localNIC->GetSubnetMask(0);
  358. DWORD subnet = staticipaddress & subnetMask;
  359. String subnetString = IPAddressToString(subnet);
  360. commandline = String::format(
  361. L"dhcp server 127.0.0.1 add scope %1 %2 Scope1",
  362. subnetString.c_str(),
  363. subnetMaskString.c_str());
  364. exitCode = 0;
  365. hr = CreateAndWaitForProcess(
  366. netshPath,
  367. commandline,
  368. exitCode,
  369. true);
  370. if (FAILED(hr))
  371. {
  372. LOG(String::format(
  373. L"Failed to set DHCP address and subnet: hr = %1!x!",
  374. hr));
  375. break;
  376. }
  377. if (exitCode != 1)
  378. {
  379. LOG(String::format(
  380. L"Failed to create DHCP scope: exitCode = %1!x!",
  381. exitCode));
  382. //break;
  383. }
  384. // Set the DHCP scopes
  385. String start = GetStartIPAddressString(*localNIC);
  386. String end = GetEndIPAddressString(*localNIC);
  387. commandline = String::format(
  388. L"dhcp server 127.0.0.1 scope %1 add iprange %2 %3 both",
  389. subnetString.c_str(),
  390. start.c_str(),
  391. end.c_str());
  392. // Set the start and end of the scope in regkeys so that they can
  393. // be read after reboot
  394. if (!SetRegKeyValue(
  395. CYS_FIRST_DC_REGKEY,
  396. CYS_FIRST_DC_SCOPE_START,
  397. start.c_str(),
  398. HKEY_LOCAL_MACHINE,
  399. true))
  400. {
  401. LOG(String::format(
  402. L"Failed to set DHCP scope start regkey: hr = %1!x!",
  403. hr));
  404. }
  405. if (!SetRegKeyValue(
  406. CYS_FIRST_DC_REGKEY,
  407. CYS_FIRST_DC_SCOPE_END,
  408. end.c_str(),
  409. HKEY_LOCAL_MACHINE,
  410. true))
  411. {
  412. LOG(String::format(
  413. L"Failed to set DHCP scope end regkey: hr = %1!x!",
  414. hr));
  415. }
  416. exitCode = 0;
  417. hr = CreateAndWaitForProcess(
  418. netshPath,
  419. commandline,
  420. exitCode,
  421. true);
  422. if (FAILED(hr))
  423. {
  424. LOG(String::format(
  425. L"Failed to set DHCP scope iprange: hr = %1!x!",
  426. hr));
  427. break;
  428. }
  429. if (exitCode != 1)
  430. {
  431. LOG(String::format(
  432. L"Failed to set DHCP scope iprange: exitCode = %1!x!",
  433. exitCode));
  434. //break;
  435. }
  436. // Set an exception for the servers IP address if it falls within
  437. // the scope
  438. if (staticipaddress >= GetStartIPAddress(*localNIC) &&
  439. staticipaddress <= GetEndIPAddress(*localNIC))
  440. {
  441. commandline = String::format(
  442. L"dhcp server 127.0.0.1 scope %1 add excluderange %2 %2",
  443. subnetString.c_str(),
  444. ipaddressString.c_str());
  445. exitCode = 0;
  446. hr = CreateAndWaitForProcess(
  447. netshPath,
  448. commandline,
  449. exitCode,
  450. true);
  451. if (FAILED(hr))
  452. {
  453. LOG(String::format(
  454. L"Failed to set server exclusion for DHCP scopes: hr = 0x%1!x!",
  455. hr));
  456. break;
  457. }
  458. if (exitCode != 1)
  459. {
  460. LOG(String::format(
  461. L"Failed to set server exclusion for DHCP scopes: exitCode = 0x%1!x!",
  462. exitCode));
  463. //break;
  464. }
  465. }
  466. // Activate the scope
  467. commandline = String::format(
  468. L"dhcp server 127.0.0.1 scope %1 set state 1",
  469. subnetString.c_str());
  470. exitCode = 0;
  471. hr = CreateAndWaitForProcess(
  472. netshPath,
  473. commandline,
  474. exitCode,
  475. true);
  476. if (FAILED(hr))
  477. {
  478. LOG(String::format(
  479. L"Failed to activate scope: hr = 0x%1!x!",
  480. hr));
  481. }
  482. if (exitCode != 1)
  483. {
  484. LOG(String::format(
  485. L"Failed to activate scope: exitCode = 0x%1!x!",
  486. exitCode));
  487. }
  488. // Set the DHCP scope lease time
  489. commandline = L"dhcp server 127.0.0.1 add optiondef 51 \"Lease\" DWORD 0 comment=\"Client IP address lease time in seconds\" 0";
  490. exitCode = 0;
  491. hr = CreateAndWaitForProcess(
  492. netshPath,
  493. commandline,
  494. exitCode,
  495. true);
  496. if (FAILED(hr))
  497. {
  498. LOG(String::format(
  499. L"Failed to set DHCP scope lease time: hr = %1!x!",
  500. hr));
  501. break;
  502. }
  503. if (exitCode != 1)
  504. {
  505. LOG(String::format(
  506. L"Failed to set DHCP scope lease time: exitCode = %1!x!",
  507. exitCode));
  508. }
  509. // Set the DHCP scope lease time value
  510. commandline = String::format(
  511. L"dhcp server 127.0.0.1 scope %1 set optionvalue 51 dword 874800",
  512. subnetString.c_str());
  513. exitCode = 0;
  514. hr = CreateAndWaitForProcess(
  515. netshPath,
  516. commandline,
  517. exitCode,
  518. true);
  519. if (FAILED(hr))
  520. {
  521. LOG(String::format(
  522. L"Failed to set DHCP scope lease time value: hr = %1!x!",
  523. hr));
  524. break;
  525. }
  526. if (exitCode != 1)
  527. {
  528. LOG(String::format(
  529. L"Failed to set DHCP scope lease time value: exitCode = %1!x!",
  530. exitCode));
  531. //break;
  532. }
  533. // Set the default gateway to be handed out to clients. This will allow
  534. // for proper routing
  535. if (InstallationUnitProvider::GetInstance().GetRRASInstallationUnit().IsRoutingOn())
  536. {
  537. commandline =
  538. L"dhcp server 127.0.0.1 add optiondef 3 \"Router\" IPADDRESS "
  539. L"1 comment=\"Array of router addresses ordered by preference\" 0.0.0.0";
  540. exitCode = 0;
  541. hr = CreateAndWaitForProcess(
  542. netshPath,
  543. commandline,
  544. exitCode,
  545. true);
  546. // From CEdson - Ignore any failures because it probably just means that
  547. // the option already exists in which case we can continue on
  548. commandline =
  549. String::format(
  550. L"dhcp server 127.0.0.1 set optionvalue 3 IPADDRESS \"%1\"",
  551. ipaddressString.c_str());
  552. exitCode = 0;
  553. hr = CreateAndWaitForProcess(
  554. netshPath,
  555. commandline,
  556. exitCode,
  557. true);
  558. if (FAILED(hr))
  559. {
  560. LOG(String::format(
  561. L"Failed to set DHCP default gateway: hr = %1!x!",
  562. hr));
  563. break;
  564. }
  565. if (exitCode != 1)
  566. {
  567. LOG(String::format(
  568. L"Failed to set DHCP default gateway: exitCode = %1!x!",
  569. exitCode));
  570. //break;
  571. }
  572. }
  573. }
  574. } while (false);
  575. LOG_INSTALL_RETURN(result);
  576. return result;
  577. }
  578. void
  579. DHCPInstallationUnit::CreateUnattendFileTextForExpressPath(
  580. const NetworkInterface& nic,
  581. String& unattendFileText)
  582. {
  583. LOG_FUNCTION(DHCPInstallationUnit::CreateUnattendFileTextForExpressPath);
  584. // The DNS server IP
  585. DWORD staticipaddress = nic.GetIPAddress(0);
  586. DWORD subnetMask = nic.GetSubnetMask(0);
  587. DWORD subnet = staticipaddress & subnetMask;
  588. String subnetString = IPAddressToString(subnet);
  589. unattendFileText = L"[NetOptionalComponents]\r\n";
  590. unattendFileText += L"DHCPServer=1\r\n";
  591. unattendFileText += L"[dhcpserver]\r\n";
  592. unattendFileText += L"Subnets=";
  593. unattendFileText += subnetString;
  594. unattendFileText += L"\r\n";
  595. // Add the DHCP scope
  596. unattendFileText += L"StartIP=";
  597. unattendFileText += GetStartIPAddressString(nic);
  598. unattendFileText += L"\r\n";
  599. unattendFileText += L"EndIp=";
  600. unattendFileText += GetEndIPAddressString(nic);
  601. unattendFileText += L"\r\n";
  602. // Add subnet mask
  603. String subnetMaskString = nic.GetStringSubnetMask(0);
  604. unattendFileText += L"SubnetMask=";
  605. unattendFileText += subnetMaskString;
  606. unattendFileText += L"\r\n";
  607. unattendFileText += L"LeaseDuration=874800\r\n";
  608. unattendFileText += String::format(
  609. L"DnsServer=%1\r\n",
  610. IPAddressToString(staticipaddress).c_str());
  611. // The domain name
  612. unattendFileText += String::format(
  613. L"DomainName=%1\r\n",
  614. InstallationUnitProvider::GetInstance().GetADInstallationUnit().GetNewDomainDNSName().c_str());
  615. }
  616. bool
  617. DHCPInstallationUnit::GetMilestoneText(String& message)
  618. {
  619. LOG_FUNCTION(DHCPInstallationUnit::GetMilestoneText);
  620. if (IsExpressPathInstall())
  621. {
  622. }
  623. else
  624. {
  625. message = String::load(IDS_DHCP_FINISH_TEXT);
  626. }
  627. LOG_BOOL(true);
  628. return true;
  629. }
  630. bool
  631. DHCPInstallationUnit::GetUninstallMilestoneText(String& message)
  632. {
  633. LOG_FUNCTION(DHCPInstallationUnit::GetUninstallMilestoneText);
  634. message = String::load(IDS_DHCP_UNINSTALL_TEXT);
  635. LOG_BOOL(true);
  636. return true;
  637. }
  638. bool
  639. DHCPInstallationUnit::AuthorizeDHCPServer(const String& dnsName) const
  640. {
  641. LOG_FUNCTION(DHCPInstallationUnit::AuthorizeDHCPServer);
  642. bool result = true;
  643. do
  644. {
  645. // Read the local NIC GUID from the registry
  646. NetworkInterface* localNIC =
  647. State::GetInstance().GetLocalNICFromRegistry();
  648. if (!localNIC)
  649. {
  650. LOG(L"Failed to get the local NIC from registry");
  651. result = false;
  652. break;
  653. }
  654. // Authorize the DHCP scope
  655. String commandline;
  656. commandline = L"dhcp add server ";
  657. commandline += dnsName;
  658. commandline += L" ";
  659. commandline += localNIC->GetStringIPAddress(0);
  660. DWORD exitCode = 0;
  661. HRESULT hr =
  662. CreateAndWaitForProcess(
  663. GetNetshPath(),
  664. commandline,
  665. exitCode,
  666. true);
  667. if (FAILED(hr))
  668. {
  669. LOG(String::format(
  670. L"Failed to run DHCP authorization: hr = %1!x!",
  671. hr));
  672. result = false;
  673. break;
  674. }
  675. // Success code appears to be 0 for this one
  676. if (exitCode != 0)
  677. {
  678. result = false;
  679. break;
  680. }
  681. } while (false);
  682. LOG_BOOL(result);
  683. return result;
  684. }
  685. void
  686. DHCPInstallationUnit::SetStartIPAddress(DWORD ipaddress)
  687. {
  688. LOG_FUNCTION2(
  689. DHCPInstallationUnit::SetStartIPAddress,
  690. String::format(L"0x%1!x!", ipaddress));
  691. startIPAddress = ipaddress;
  692. // Scope is being set manually so lets not try to calculate it
  693. scopeCalculated = true;
  694. }
  695. void
  696. DHCPInstallationUnit::SetEndIPAddress(DWORD ipaddress)
  697. {
  698. LOG_FUNCTION2(
  699. DHCPInstallationUnit::SetEndIPAddress,
  700. String::format(L"0x%1!x!", ipaddress));
  701. endIPAddress = ipaddress;
  702. // Scope is being set manually so lets not try to calculate it
  703. scopeCalculated = true;
  704. }
  705. String
  706. DHCPInstallationUnit::GetStartIPAddressString(const NetworkInterface& nic)
  707. {
  708. LOG_FUNCTION(DHCPInstallationUnit::GetStartIPAddressString);
  709. CalculateScope(nic);
  710. String result = IPAddressToString(startIPAddress);
  711. LOG(result);
  712. return result;
  713. }
  714. String
  715. DHCPInstallationUnit::GetEndIPAddressString(const NetworkInterface& nic)
  716. {
  717. LOG_FUNCTION(DHCPInstallationUnit::GetEndIPAddressString);
  718. CalculateScope(nic);
  719. String result = IPAddressToString(endIPAddress);
  720. LOG(result);
  721. return result;
  722. }
  723. DWORD
  724. DHCPInstallationUnit::GetStartIPAddress(const NetworkInterface& nic)
  725. {
  726. LOG_FUNCTION(DHCPInstallationUnit::GetStartIPAddress);
  727. CalculateScope(nic);
  728. return startIPAddress;
  729. }
  730. DWORD
  731. DHCPInstallationUnit::GetEndIPAddress(const NetworkInterface& nic)
  732. {
  733. LOG_FUNCTION(DHCPInstallationUnit::GetEndIPAddress);
  734. CalculateScope(nic);
  735. return endIPAddress;
  736. }
  737. void
  738. DHCPInstallationUnit::CalculateScope(const NetworkInterface& nic)
  739. {
  740. LOG_FUNCTION(DHCPInstallationUnit::CalculateScope);
  741. if (!scopeCalculated)
  742. {
  743. DWORD staticIPAddress = nic.GetIPAddress(0);
  744. DWORD subnetMask = nic.GetSubnetMask(0);
  745. // We are allowing a buffer of 10 addresses that are not part of the scope
  746. // in case the user wants to add other machines (computers, routers, etc)
  747. // with static IP addresses
  748. startIPAddress = (subnetMask & staticIPAddress);
  749. endIPAddress = (subnetMask & staticIPAddress) | (~(subnetMask) - 1);
  750. if (startIPAddress + 10 < endIPAddress)
  751. {
  752. startIPAddress = startIPAddress + 10;
  753. }
  754. scopeCalculated = true;
  755. }
  756. LOG(String::format(
  757. L"Start: %1",
  758. IPAddressToString(startIPAddress).c_str()));
  759. LOG(String::format(
  760. L"End: %1",
  761. IPAddressToString(endIPAddress).c_str()));
  762. }
  763. String
  764. DHCPInstallationUnit::GetServiceDescription()
  765. {
  766. LOG_FUNCTION(DHCPInstallationUnit::GetServiceDescription);
  767. String result;
  768. unsigned int resultID = descriptionID;
  769. if (GetStatus() == STATUS_COMPLETED)
  770. {
  771. resultID = installedDescriptionID;
  772. }
  773. result = String::load(resultID);
  774. ASSERT(!result.empty());
  775. return result;
  776. }
  777. void
  778. DHCPInstallationUnit::ServerRoleLinkSelected(int linkIndex, HWND /*hwnd*/)
  779. {
  780. LOG_FUNCTION2(
  781. DHCPInstallationUnit::ServerRoleLinkSelected,
  782. String::format(
  783. L"linkIndex = %1!d!",
  784. linkIndex));
  785. if (IsServiceInstalled())
  786. {
  787. ASSERT(linkIndex == 0);
  788. LaunchMYS();
  789. }
  790. else
  791. {
  792. ASSERT(linkIndex == 0);
  793. LOG(L"Showing configuration help");
  794. ShowHelp(CYS_DHCP_FINISH_PAGE_HELP);
  795. }
  796. }
  797. void
  798. DHCPInstallationUnit::FinishLinkSelected(int linkIndex, HWND /*hwnd*/)
  799. {
  800. LOG_FUNCTION2(
  801. DHCPInstallationUnit::FinishLinkSelected,
  802. String::format(
  803. L"linkIndex = %1!d!",
  804. linkIndex));
  805. if (installing)
  806. {
  807. if (linkIndex == 0 &&
  808. IsServiceInstalled())
  809. {
  810. // Installation was successful. Check to see
  811. // if there was a failure in configuration
  812. if (dhcpRoleResult == DHCP_CONFIG_FAILURE)
  813. {
  814. // Since there was a config failure just
  815. // point them to the snapin
  816. LOG(L"Launching DHCP snapin");
  817. LaunchMMCConsole(L"dhcpmgmt.msc");
  818. }
  819. else
  820. {
  821. // Offer the next steps document
  822. LOG("Showing after checklist");
  823. ShowHelp(CYS_DHCP_AFTER_FINISH_HELP);
  824. }
  825. }
  826. else if (linkIndex == 0)
  827. {
  828. // There was a failure
  829. LOG(L"Showing configuration help");
  830. ShowHelp(CYS_DHCP_FINISH_PAGE_HELP);
  831. }
  832. }
  833. }
  834. String
  835. DHCPInstallationUnit::GetFinishText()
  836. {
  837. LOG_FUNCTION(DHCPInstallationUnit::GetFinishText);
  838. unsigned int messageID = finishMessageID;
  839. if (installing)
  840. {
  841. InstallationReturnType result = GetInstallResult();
  842. if (result != INSTALL_SUCCESS &&
  843. result != INSTALL_SUCCESS_REBOOT &&
  844. result != INSTALL_SUCCESS_PROMPT_REBOOT)
  845. {
  846. if (dhcpRoleResult == DHCP_INSTALL_FAILURE)
  847. {
  848. messageID = finishInstallFailedMessageID;
  849. }
  850. else
  851. {
  852. messageID = IDS_DHCP_CONFIG_FAILED;
  853. }
  854. }
  855. }
  856. else
  857. {
  858. messageID = finishUninstallMessageID;
  859. UnInstallReturnType result = GetUnInstallResult();
  860. if (result != UNINSTALL_SUCCESS &&
  861. result != UNINSTALL_SUCCESS_REBOOT &&
  862. result != UNINSTALL_SUCCESS_PROMPT_REBOOT)
  863. {
  864. messageID = finishUninstallFailedMessageID;
  865. }
  866. }
  867. return String::load(messageID);
  868. }