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.

886 lines
29 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: D H C P S O B J . C P P
  7. //
  8. // Contents: Implementation of the CDHCPServer notify object
  9. //
  10. // Notes:
  11. //
  12. // Author: jeffspr 31 May 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "dhcpsobj.h"
  18. #include "ncerror.h"
  19. #include "ncperms.h"
  20. #include "ncreg.h"
  21. #include "ncsetup.h"
  22. #include "ncnetcfg.h"
  23. #include "ncipaddr.h"
  24. #include <dhcpapi.h>
  25. extern const WCHAR c_szInfId_MS_DHCPServer[];
  26. extern const WCHAR c_szAfDhcpServerConfiguration[];
  27. extern const WCHAR c_szAfDhcpServerParameters[];
  28. //---[ Constants ]------------------------------------------------------------
  29. static const WCHAR c_szDHCPServerServicePath[] = L"System\\CurrentControlSet\\Services\\DHCPServer";
  30. static const WCHAR c_szDHCPServerParamPath[] = L"System\\CurrentControlSet\\Services\\DHCPServer\\Parameters";
  31. static const WCHAR c_szDHCPServerConfigPath[] = L"System\\CurrentControlSet\\Services\\DHCPServer\\Configuration";
  32. static const WCHAR c_szOptionInfo[] = L"OptionInfo";
  33. static const WCHAR c_szSubnets[] = L"Subnets";
  34. static const WCHAR c_szIpRanges[] = L"IpRanges";
  35. static const WCHAR c_szSubnetOptions[] = L"SubnetOptions";
  36. static const WCHAR c_szDHCPServerUnattendRegSection[] = L"DHCPServer_Unattend";
  37. const WCHAR c_szStartIp[] = L"StartIp";
  38. const WCHAR c_szEndIp[] = L"EndIp";
  39. const WCHAR c_szSubnetMask[] = L"SubnetMask";
  40. const WCHAR c_szLeaseDuration[] = L"LeaseDuration";
  41. const WCHAR c_szDnsServer[] = L"DnsServer";
  42. const WCHAR c_szDomainName[] = L"DomainName";
  43. // Destructor
  44. //
  45. CDHCPServer::CDHCPServer()
  46. {
  47. // Initialize member variables.
  48. m_pnc = NULL;
  49. m_pncc = NULL;
  50. m_eInstallAction = eActUnknown;
  51. m_fUpgrade = FALSE;
  52. m_fUnattend = FALSE;
  53. }
  54. CDHCPServer::~CDHCPServer()
  55. {
  56. ReleaseObj(m_pncc);
  57. ReleaseObj(m_pnc);
  58. // Release KEY handles here.
  59. }
  60. //
  61. // INetCfgNotify
  62. //
  63. STDMETHODIMP CDHCPServer::Initialize( INetCfgComponent * pnccItem,
  64. INetCfg * pnc,
  65. BOOL fInstalling)
  66. {
  67. Validate_INetCfgNotify_Initialize(pnccItem, pnc, fInstalling);
  68. m_pncc = pnccItem;
  69. m_pnc = pnc;
  70. AssertSz(m_pncc, "m_pncc NULL in CDHCPServer::Initialize");
  71. AssertSz(m_pnc, "m_pnc NULL in CDHCPServer::Initialize");
  72. // Addref the config objects
  73. //
  74. AddRefObj(m_pncc);
  75. AddRefObj(m_pnc);
  76. return S_OK;
  77. }
  78. //+---------------------------------------------------------------------------
  79. //
  80. // Function: HrRestoreRegistrySz
  81. //
  82. // Purpose: Restore a subkey from the specified file
  83. //
  84. // Arguments:
  85. // hkeyBase [in] handle of basekey
  86. // pszSubKey [in] subkey to restore
  87. // pszRegFile [in] name of file to restore from
  88. //
  89. // Returns: S_OK on success, otherwise an error code
  90. //
  91. // Author: kumarp 16-September-98
  92. //
  93. // Notes: This should be moved to common code
  94. //
  95. HRESULT
  96. HrRestoreRegistrySz (
  97. IN HKEY hkeyBase,
  98. IN PCWSTR pszSubKey,
  99. IN PCWSTR pszRegFile)
  100. {
  101. Assert(hkeyBase);
  102. AssertValidReadPtr(pszSubKey);
  103. AssertValidReadPtr(pszRegFile);
  104. HRESULT hr;
  105. HKEY hkey = NULL;
  106. DWORD dwDisp;
  107. TraceTag(ttidDHCPServer, "restoring subkey '%S' from file '%S'",
  108. pszSubKey, pszRegFile);
  109. hr = HrEnablePrivilege (SE_RESTORE_NAME);
  110. if (S_OK == hr)
  111. {
  112. // Ensure key is there by creating it
  113. //
  114. hr = HrRegCreateKeyEx (hkeyBase, pszSubKey, REG_OPTION_NON_VOLATILE,
  115. KEY_READ_WRITE_DELETE, NULL, &hkey, &dwDisp);
  116. if (S_OK == hr)
  117. {
  118. // Restore the old settings
  119. //
  120. hr = HrRegRestoreKey (hkey, pszRegFile, 0);
  121. RegCloseKey (hkey);
  122. }
  123. }
  124. TraceError ("HrRestoreRegistrySz", hr);
  125. return hr;
  126. }
  127. //+---------------------------------------------------------------------------
  128. //
  129. // Member: CDHCPServer::HrRestoreRegistry
  130. //
  131. // Purpose: Restores the contents of the registry for this component
  132. //
  133. // Arguments:
  134. // (none)
  135. //
  136. // Returns: Win32 error if failed, otherwise S_OK
  137. //
  138. // Author: jeffspr 13 Aug 1997
  139. //
  140. // Notes:
  141. //
  142. HRESULT CDHCPServer::HrRestoreRegistry()
  143. {
  144. HRESULT hr = S_OK;
  145. TraceTag(ttidDHCPServer, "CDHCPServer::HrRestoreRegistry()");
  146. // If we have a "configuration" key restore file
  147. //
  148. if (!m_strConfigRestoreFile.empty())
  149. {
  150. // We always want to continue, so ignore the return code
  151. //
  152. (void) HrRestoreRegistrySz(HKEY_LOCAL_MACHINE,
  153. c_szDHCPServerConfigPath,
  154. m_strConfigRestoreFile.c_str());
  155. }
  156. else
  157. {
  158. TraceTag(ttidDHCPServer, "DHCP Server Params restore file doesn't exist");
  159. }
  160. // If we have a params restore file
  161. //
  162. if (!m_strParamsRestoreFile.empty())
  163. {
  164. // We always want to continue, so ignore the return code
  165. //
  166. (void) HrRestoreRegistrySz(HKEY_LOCAL_MACHINE,
  167. c_szDHCPServerParamPath,
  168. m_strParamsRestoreFile.c_str());
  169. }
  170. else
  171. {
  172. TraceTag(ttidDHCPServer, "DHCP Server Params restore file doesn't exist");
  173. }
  174. TraceHr(ttidDHCPServer, FAL, hr, FALSE, "CDHCPServer::HrRestoreRegistry");
  175. return hr;
  176. }
  177. HRESULT CDHCPServer::HrWriteUnattendedKeys()
  178. {
  179. HRESULT hr = S_OK;
  180. HKEY hkeyService = NULL;
  181. const COMPONENT_INFO * pci = NULL;
  182. Assert(m_fUnattend);
  183. hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE,
  184. c_szDHCPServerServicePath,
  185. KEY_READ_WRITE_DELETE,
  186. &hkeyService);
  187. if (SUCCEEDED(hr))
  188. {
  189. Assert(hkeyService);
  190. pci = PComponentInfoFromComponentId(c_szInfId_MS_DHCPServer);
  191. if (pci)
  192. {
  193. CSetupInfFile csif;
  194. // Open the answer file.
  195. hr = csif.HrOpen(pci->pszInfFile, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
  196. if (SUCCEEDED(hr))
  197. {
  198. // Install the unattend params
  199. //
  200. hr = HrSetupInstallFromInfSection (
  201. NULL,
  202. csif.Hinf(),
  203. c_szDHCPServerUnattendRegSection,
  204. SPINST_REGISTRY,
  205. hkeyService,
  206. NULL,
  207. NULL,
  208. NULL,
  209. NULL,
  210. NULL,
  211. NULL);
  212. }
  213. }
  214. RegCloseKey(hkeyService);
  215. }
  216. TraceHr(ttidDHCPServer, FAL, hr, FALSE, "CDHCPServer::HrWriteUnattendedKeys");
  217. return hr;
  218. }
  219. //+---------------------------------------------------------------------------
  220. //
  221. // Member: CDHCPServer::HrWriteDhcpOptionInfo
  222. //
  223. // Purpose: Write to the registry the Dhcp OptionInfo data.
  224. //
  225. // Arguments:
  226. // hkeyConfig
  227. //
  228. // Returns: S_OK if successful, Reg API error otherwise.
  229. //
  230. // Notes:
  231. //
  232. HRESULT CDHCPServer::HrWriteDhcpOptionInfo(HKEY hkeyConfig)
  233. {
  234. HRESULT hr;
  235. DWORD dwDisposition;
  236. HKEY hkeyOptionInfo = NULL;
  237. typedef struct
  238. {
  239. const WCHAR * pcszOptionKeyName;
  240. const WCHAR * pcszOptionName;
  241. const WCHAR * pcszOptionComment;
  242. DWORD dwOptionType;
  243. DWORD dwOptionId;
  244. DWORD cbBinData;
  245. DWORD * pdwBinData;
  246. } OIDATA;
  247. OIDATA OiData[2];
  248. DWORD BinData006[] = {0x14, 0x4, 0x1, 0x0, 0x0};
  249. DWORD BinData015[] = {0x18, 0x5, 0x1, 0x0, 0x2, 0x0};
  250. OiData[0].pcszOptionKeyName = L"006";
  251. OiData[0].pcszOptionName = SzLoadIds(IDS_DHCP_OPTION_006_NAME); // DNS Servers
  252. OiData[0].pcszOptionComment = SzLoadIds(IDS_DHCP_OPTION_006_COMMENT); // Array of DNS Servers, by preference
  253. OiData[0].dwOptionType = 0x1;
  254. OiData[0].dwOptionId = 0x6;
  255. OiData[0].cbBinData = celems(BinData006) * sizeof(BinData006[0]);
  256. OiData[0].pdwBinData = BinData006;
  257. OiData[1].pcszOptionKeyName = L"015";
  258. OiData[1].pcszOptionName = SzLoadIds(IDS_DHCP_OPTION_015_NAME); // DNS Domain Name
  259. OiData[1].pcszOptionComment = SzLoadIds(IDS_DHCP_OPTION_015_COMMENT); // Domainname for client resolutions
  260. OiData[1].dwOptionType = 0x0;
  261. OiData[1].dwOptionId = 0xf;
  262. OiData[1].cbBinData = celems(BinData015) * sizeof(BinData015[0]);
  263. OiData[1].pdwBinData = BinData015;
  264. hr = ::HrRegCreateKeyEx(hkeyConfig, c_szOptionInfo,
  265. REG_OPTION_NON_VOLATILE,
  266. KEY_READ, NULL,
  267. &hkeyOptionInfo, &dwDisposition);
  268. if (SUCCEEDED(hr))
  269. {
  270. for (UINT idx=0;
  271. (idx<celems(OiData)) && SUCCEEDED(hr);
  272. idx++)
  273. {
  274. HKEY hkey = NULL;
  275. hr = ::HrRegCreateKeyEx(hkeyOptionInfo, OiData[idx].pcszOptionKeyName,
  276. REG_OPTION_NON_VOLATILE,
  277. KEY_READ_WRITE, NULL,
  278. &hkey, &dwDisposition);
  279. if (SUCCEEDED(hr))
  280. {
  281. (VOID)::HrRegSetString(hkey, L"OptionName",
  282. OiData[idx].pcszOptionName);
  283. (VOID)::HrRegSetString(hkey, L"OptionComment",
  284. OiData[idx].pcszOptionComment);
  285. (VOID)::HrRegSetDword(hkey, L"OptionType",
  286. OiData[idx].dwOptionType);
  287. (VOID)::HrRegSetDword(hkey, L"OptionId",
  288. OiData[idx].dwOptionId);
  289. (VOID)::HrRegSetBinary(hkey, L"OptionValue",
  290. (const BYTE *)OiData[idx].pdwBinData,
  291. OiData[idx].cbBinData);
  292. RegCloseKey(hkey);
  293. }
  294. }
  295. RegCloseKey(hkeyOptionInfo);
  296. }
  297. TraceError("HrWriteDhcpOptionInfo", hr);
  298. return hr;
  299. }
  300. //+---------------------------------------------------------------------------
  301. //
  302. // Member: CDHCPServer::HrWriteDhcpSubnets
  303. //
  304. // Purpose: Write to the registry the Dhcp Subnet data.
  305. //
  306. // Arguments:
  307. // hkeyDhcpCfg
  308. // pszSubnet
  309. // pszStartIp
  310. // dwEndIp
  311. // dwSubnetMask
  312. // dwLeaseDuration
  313. // dwDnsServer
  314. // pszDomainName
  315. //
  316. // Returns: S_OK if successful, Reg API error otherwise.
  317. //
  318. // Notes:
  319. //
  320. HRESULT
  321. CDHCPServer::HrWriteDhcpSubnets (
  322. HKEY hkeyDhcpCfg,
  323. PCWSTR pszSubnet,
  324. PCWSTR pszStartIp,
  325. DWORD dwEndIp,
  326. DWORD dwSubnetMask,
  327. DWORD dwLeaseDuration,
  328. DWORD dwDnsServer,
  329. PCWSTR pszDomainName)
  330. {
  331. DWORD dwDisposition;
  332. HRESULT hr;
  333. HKEY hkeySubnets = NULL;
  334. hr = HrRegCreateKeyEx(hkeyDhcpCfg, c_szSubnets, REG_OPTION_NON_VOLATILE,
  335. KEY_READ, NULL, &hkeySubnets, &dwDisposition);
  336. if (S_OK == hr)
  337. {
  338. HKEY hkey10Dot = NULL;
  339. hr = HrRegCreateKeyEx(hkeySubnets, pszSubnet, REG_OPTION_NON_VOLATILE,
  340. KEY_READ_WRITE, NULL, &hkey10Dot, &dwDisposition);
  341. if (S_OK == hr)
  342. {
  343. HKEY hkeySubnetOptions = NULL;
  344. HKEY hkeyIpRanges = NULL;
  345. (VOID)HrRegSetString(hkey10Dot, L"SubnetName",
  346. SzLoadIds(IDS_DHCP_SUBNET_NAME)); // DHCP Server Scope
  347. (VOID)HrRegSetString(hkey10Dot, L"SubnetComment",
  348. SzLoadIds(IDS_DHCP_SUBNET_COMMENT)); // Scope used to offer clients address
  349. (VOID)HrRegSetDword(hkey10Dot, L"SubnetState", 0x0);
  350. (VOID)HrRegSetDword(hkey10Dot, L"SubnetAddress",
  351. IpPszToHostAddr(pszSubnet));
  352. (VOID)HrRegSetDword(hkey10Dot, L"SubnetMask", dwSubnetMask);
  353. hr = HrRegCreateKeyEx(hkey10Dot, c_szIpRanges,
  354. REG_OPTION_NON_VOLATILE,
  355. KEY_READ, NULL,
  356. &hkeyIpRanges, &dwDisposition);
  357. if (S_OK == hr)
  358. {
  359. HKEY hkeyStartIp = NULL;
  360. hr = HrRegCreateKeyEx(hkeyIpRanges, pszStartIp,
  361. REG_OPTION_NON_VOLATILE,
  362. KEY_READ_WRITE, NULL,
  363. &hkeyStartIp, &dwDisposition);
  364. if (S_OK == hr)
  365. {
  366. (VOID)HrRegSetDword(hkeyStartIp, L"RangeFlags", 0x1);
  367. (VOID)HrRegSetDword(hkeyStartIp, L"StartAddress",
  368. IpPszToHostAddr(pszStartIp));
  369. (VOID)HrRegSetDword(hkeyStartIp, L"EndAddress",
  370. dwEndIp);
  371. RegCloseKey(hkeyStartIp);
  372. }
  373. RegCloseKey(hkeyIpRanges);
  374. }
  375. // Create subnets options key
  376. //
  377. hr = HrRegCreateKeyEx(hkey10Dot, c_szSubnetOptions,
  378. REG_OPTION_NON_VOLATILE,
  379. KEY_READ_WRITE, NULL,
  380. &hkeySubnetOptions, &dwDisposition);
  381. if (S_OK == hr)
  382. {
  383. HKEY hkey051 = NULL;
  384. hr = HrRegCreateKeyEx(hkeySubnetOptions, L"051",
  385. REG_OPTION_NON_VOLATILE,
  386. KEY_READ_WRITE, NULL,
  387. &hkey051, &dwDisposition);
  388. if (S_OK == hr)
  389. {
  390. (VOID)HrRegSetDword(hkey051, L"OptionId", 0x33);
  391. DWORD rgdwLease[] = {0x14, 0x2, 0x1, 0x0, 0x0};
  392. rgdwLease[celems(rgdwLease) - 1] = dwLeaseDuration;
  393. (VOID)HrRegSetBinary(hkey051,
  394. L"OptionValue",
  395. (const BYTE *)rgdwLease,
  396. sizeof(rgdwLease));
  397. RegCloseKey(hkey051);
  398. }
  399. HKEY hkey006 = NULL;
  400. hr = HrRegCreateKeyEx(hkeySubnetOptions, L"006",
  401. REG_OPTION_NON_VOLATILE,
  402. KEY_READ_WRITE, NULL,
  403. &hkey006, &dwDisposition);
  404. if (S_OK == hr)
  405. {
  406. (VOID)HrRegSetDword(hkey006, L"OptionId", 0x6);
  407. DWORD rgdwDnsServer[] = {0x14, 0x4, 0x1, 0x0, 0x0};
  408. rgdwDnsServer[celems(rgdwDnsServer) - 1] = dwDnsServer;
  409. (VOID)::HrRegSetBinary(hkey006,
  410. L"OptionValue",
  411. (const BYTE *)rgdwDnsServer,
  412. sizeof(rgdwDnsServer));
  413. RegCloseKey(hkey006);
  414. }
  415. HKEY hkey015 = NULL;
  416. hr = HrRegCreateKeyEx(hkeySubnetOptions, L"015",
  417. REG_OPTION_NON_VOLATILE,
  418. KEY_READ_WRITE, NULL,
  419. &hkey015, &dwDisposition);
  420. if (S_OK == hr)
  421. {
  422. (VOID)HrRegSetDword(hkey015, L"OptionId", 0xf);
  423. UINT uLen = 0x18 + 2 * lstrlenW(pszDomainName);
  424. LPBYTE pb = (LPBYTE)MemAlloc(uLen);
  425. if (pb)
  426. {
  427. ZeroMemory(pb, uLen);
  428. DWORD *pdw = (DWORD *)pb;
  429. pdw[0] = uLen;
  430. pdw[1] = 0x5;
  431. pdw[2] = 0x1;
  432. pdw[3] = 0x0;
  433. pdw[4] = 2 * (1 + lstrlenW(pszDomainName));
  434. lstrcpyW((PWSTR)&pdw[5], pszDomainName);
  435. (VOID)::HrRegSetBinary(hkey015, L"OptionValue",
  436. (const BYTE *)pb, uLen);
  437. MemFree(pb);
  438. }
  439. RegCloseKey(hkey015);
  440. }
  441. RegCloseKey(hkeySubnetOptions);
  442. }
  443. RegCloseKey(hkey10Dot);
  444. }
  445. RegCloseKey(hkeySubnets);
  446. }
  447. TraceError("HrWriteDhcpSubnets", hr);
  448. return hr;
  449. }
  450. //+---------------------------------------------------------------------------
  451. //
  452. // Member: CDHCPServer::HrProcessDhcpServerSolutionsParams
  453. //
  454. // Purpose: Handles necessary processing of contents of the answer file.
  455. //
  456. // Arguments:
  457. // pcsif [in] Filename of answer file for upgrade.
  458. // pszAnswerSection [in] Answerfile section in the
  459. // file appropriate to this component.
  460. //
  461. // Returns: S_OK if successful, setup API error otherwise.
  462. //
  463. // Notes:
  464. //
  465. HRESULT
  466. CDHCPServer::HrProcessDhcpServerSolutionsParams (
  467. IN CSetupInfFile * pcsif,
  468. IN PCWSTR pszAnswerSection)
  469. {
  470. HRESULT hr;
  471. tstring str;
  472. tstring strStartIp;
  473. tstring strSubnet;
  474. hr = pcsif->HrGetString(pszAnswerSection, c_szSubnets, &strSubnet);
  475. if (SUCCEEDED(hr))
  476. {
  477. hr = pcsif->HrGetString(pszAnswerSection, c_szStartIp, &strStartIp);
  478. if (SUCCEEDED(hr))
  479. {
  480. hr = pcsif->HrGetString(pszAnswerSection, c_szEndIp, &str);
  481. if (SUCCEEDED(hr))
  482. {
  483. DWORD dwEndIp = IpPszToHostAddr(str.c_str());
  484. hr = pcsif->HrGetString(pszAnswerSection, c_szSubnetMask, &str);
  485. if (SUCCEEDED(hr))
  486. {
  487. DWORD dwSubnetMask = IpPszToHostAddr(str.c_str());
  488. hr = pcsif->HrGetString(pszAnswerSection, c_szDnsServer, &str);
  489. if (SUCCEEDED(hr))
  490. {
  491. DWORD dwLeaseDuration;
  492. DWORD dwDnsServer = IpPszToHostAddr(str.c_str());
  493. hr = pcsif->HrGetDword(pszAnswerSection, c_szLeaseDuration,
  494. &dwLeaseDuration);
  495. if (SUCCEEDED(hr))
  496. {
  497. hr = pcsif->HrGetString(pszAnswerSection,
  498. c_szDomainName, &str);
  499. if (SUCCEEDED(hr) && lstrlenW(str.c_str()))
  500. {
  501. HKEY hkeyDhcpCfg = NULL;
  502. DWORD dwDisposition;
  503. // Write the registry data
  504. //
  505. hr = ::HrRegCreateKeyEx(HKEY_LOCAL_MACHINE,
  506. c_szDHCPServerConfigPath,
  507. REG_OPTION_NON_VOLATILE,
  508. KEY_READ_WRITE, NULL,
  509. &hkeyDhcpCfg, &dwDisposition);
  510. if (SUCCEEDED(hr))
  511. {
  512. hr = HrWriteDhcpOptionInfo(hkeyDhcpCfg);
  513. if (SUCCEEDED(hr))
  514. {
  515. hr = HrWriteDhcpSubnets(hkeyDhcpCfg,
  516. strSubnet.c_str(),
  517. strStartIp.c_str(),
  518. dwEndIp,
  519. dwSubnetMask,
  520. dwLeaseDuration,
  521. dwDnsServer,
  522. str.c_str());
  523. }
  524. RegCloseKey(hkeyDhcpCfg);
  525. }
  526. }
  527. }
  528. }
  529. }
  530. }
  531. }
  532. }
  533. // If there are any params missing, so be it
  534. //
  535. if ((SPAPI_E_SECTION_NOT_FOUND == hr) ||
  536. (SPAPI_E_LINE_NOT_FOUND == hr) ||
  537. (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr))
  538. {
  539. hr = S_OK;
  540. }
  541. TraceHr(ttidDHCPServer, FAL, hr, FALSE, "CDHCPServer::HrProcessDhcpServerSolutionsParams");
  542. return hr;
  543. }
  544. //+---------------------------------------------------------------------------
  545. //
  546. // Member: CDHCPServer::HrProcessAnswerFile
  547. //
  548. // Purpose: Handles necessary processing of contents of the answer file.
  549. //
  550. // Arguments:
  551. // pszAnswerFile [in] Filename of answer file for upgrade.
  552. // pszAnswerSection [in] Answer file section in the
  553. // file appropriate to this component.
  554. //
  555. // Returns: S_OK if successful, setup API error otherwise.
  556. //
  557. // Author: jeffspr 8 May 1997
  558. //
  559. // Notes:
  560. //
  561. HRESULT
  562. CDHCPServer::HrProcessAnswerFile (
  563. IN PCWSTR pszAnswerFile,
  564. IN PCWSTR pszAnswerSection)
  565. {
  566. HRESULT hr = S_OK;
  567. CSetupInfFile csif;
  568. TraceTag(ttidDHCPServer, "CDHCPServer::HrProcessAnswerFile()");
  569. // Open the answer file.
  570. hr = csif.HrOpen(pszAnswerFile, NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL);
  571. if (FAILED(hr))
  572. {
  573. TraceHr(ttidDHCPServer, FAL, hr, FALSE, "CDHCPServer::HrProcessAnswerFile -- HrOpen failed()");
  574. hr = S_OK;
  575. goto Exit;
  576. }
  577. // Restore portions of the registry based on file names from the answer
  578. // file
  579. // Get restore file for "Parameters" key
  580. hr = csif.HrGetString(pszAnswerSection, c_szAfDhcpServerParameters,
  581. &m_strParamsRestoreFile);
  582. if (FAILED(hr))
  583. {
  584. TraceHr(ttidDHCPServer, FAL, hr, FALSE, "CDHCPServer::HrProcessAnswerFile - Error restoring "
  585. "Parameters key");
  586. // oh well, just continue
  587. hr = S_OK;
  588. }
  589. // Get restore file for "Configuration" key
  590. hr = csif.HrGetString(pszAnswerSection, c_szAfDhcpServerConfiguration,
  591. &m_strConfigRestoreFile);
  592. if (FAILED(hr))
  593. {
  594. TraceHr(ttidDHCPServer, FAL, hr, FALSE, "CDHCPServer::HrProcessAnswerFile - Error restoring "
  595. "Config key");
  596. // oh well, just continue
  597. hr = S_OK;
  598. }
  599. // Server Solutions has some parameters that need to be plumbed into the registry
  600. // for their unattended install scenarios
  601. //
  602. hr = HrProcessDhcpServerSolutionsParams(&csif, pszAnswerSection);
  603. Exit:
  604. TraceHr(ttidDHCPServer, FAL, hr, FALSE, "CDHCPServer::HrProcessAnswerFile");
  605. return hr;
  606. }
  607. STDMETHODIMP CDHCPServer::ReadAnswerFile(
  608. IN PCWSTR pszAnswerFile,
  609. IN PCWSTR pszAnswerSection)
  610. {
  611. HRESULT hr = S_OK;
  612. TraceTag(ttidDHCPServer, "CDHCPServer::ReadAnswerFile()");
  613. // don't call Validate_INetCfgNotify_ReadAnswerFile here, as the netoc
  614. // installer for this will intentionally call it with NULL params. The
  615. // Validate macro actually causes a return E_INVALIDARG in this case.
  616. // We're being installed unattended
  617. //
  618. m_fUnattend = TRUE;
  619. TraceTag(ttidDHCPServer, "Answerfile: %S",
  620. pszAnswerFile ? pszAnswerFile : L"<none>");
  621. TraceTag(ttidDHCPServer, "Answersection: %S",
  622. pszAnswerSection ? pszAnswerSection : L"<none>");
  623. // If we're not already installed, do the work.
  624. //
  625. if (pszAnswerFile && pszAnswerSection)
  626. {
  627. // Process the actual answer file (read our sections)
  628. //
  629. hr = HrProcessAnswerFile(pszAnswerFile, pszAnswerSection);
  630. if (FAILED(hr))
  631. {
  632. TraceHr(ttidDHCPServer, FAL, NETSETUP_E_ANS_FILE_ERROR, FALSE,
  633. "CDHCPServer::ReadAnswerFile - Answer file has errors. Defaulting "
  634. "all information as if answer file did not exist.");
  635. hr = S_OK;
  636. }
  637. }
  638. Validate_INetCfgNotify_ReadAnswerFile_Return(hr);
  639. TraceHr(ttidDHCPServer, FAL, hr, FALSE, "CDHCPServer::ReadAnswerFile");
  640. return hr;
  641. }
  642. STDMETHODIMP CDHCPServer::Install(DWORD dwSetupFlags)
  643. {
  644. TraceTag(ttidDHCPServer, "CDHCPServer::Install()");
  645. Validate_INetCfgNotify_Install(dwSetupFlags);
  646. m_eInstallAction = eActInstall;
  647. TraceTag(ttidDHCPServer, "dwSetupFlags = %d", dwSetupFlags);
  648. TraceTag(ttidDHCPServer, "NSF_WINNT_WKS_UPGRADE = %x", NSF_WINNT_WKS_UPGRADE);
  649. TraceTag(ttidDHCPServer, "NSF_WINNT_SVR_UPGRADE = %x", NSF_WINNT_SVR_UPGRADE);
  650. if ((NSF_WINNT_WKS_UPGRADE & dwSetupFlags) ||
  651. (NSF_WINNT_SBS_UPGRADE & dwSetupFlags) ||
  652. (NSF_WINNT_SVR_UPGRADE & dwSetupFlags))
  653. {
  654. TraceTag(ttidDHCPServer, "This is indeed an upgrade");
  655. m_fUpgrade = TRUE;
  656. }
  657. else
  658. {
  659. TraceTag(ttidDHCPServer, "This is NOT an upgrade");
  660. }
  661. return S_OK;
  662. }
  663. STDMETHODIMP CDHCPServer::Removing()
  664. {
  665. m_eInstallAction = eActRemove;
  666. return S_OK;
  667. }
  668. STDMETHODIMP CDHCPServer::Validate()
  669. {
  670. return S_OK;
  671. }
  672. STDMETHODIMP CDHCPServer::CancelChanges()
  673. {
  674. return S_OK;
  675. }
  676. STDMETHODIMP CDHCPServer::ApplyRegistryChanges()
  677. {
  678. HRESULT hr = S_OK;
  679. TraceTag(ttidDHCPServer, "CDHCPServer::ApplyRegistryChanges()");
  680. TraceTag(ttidDHCPServer, "ApplyRegistryChanges -- Unattend: %d", m_fUnattend);
  681. TraceTag(ttidDHCPServer, "ApplyRegistryChanges -- Upgrade: %d", m_fUpgrade);
  682. if (m_eInstallAction == eActInstall)
  683. {
  684. TraceTag(ttidDHCPServer, "ApplyRegistryChanges -- Installing");
  685. // We used to only do this on upgrade, now we'll do it all the time.
  686. // If there's no answerfile info for the restore files, then we
  687. // won't do anything, and life will still be fine.
  688. //
  689. hr = HrRestoreRegistry();
  690. if (FAILED(hr))
  691. {
  692. TraceHr(ttidDHCPServer, FAL, hr, FALSE,
  693. "CDHCPServer::ApplyRegistryChanges - HrRestoreRegistry non-fatal error");
  694. hr = S_OK;
  695. }
  696. if (m_fUnattend && !m_fUpgrade)
  697. {
  698. // I'm if 0'ing this out for now. All of this work was done to appease Ram Cherala
  699. // and whoever asked him to do the same for SP4. Now we're hearing from Ye Gu that
  700. // we don't even want this code on normal NT4/NT5. Who knows what the desire will
  701. // be in the future.
  702. //
  703. #if 0
  704. hr = HrWriteUnattendedKeys();
  705. if (FAILED(hr))
  706. {
  707. TraceHr(ttidDHCPServer, FAL, hr, FALSE,
  708. "CDHCPServer::ApplyRegistryChanges - HrWriteUnattendedKeys non-fatal error");
  709. hr = S_OK;
  710. }
  711. #endif
  712. }
  713. // Bug #153298: Mark as upgrade so DS info is upgraded
  714. if (m_fUpgrade)
  715. {
  716. DHCP_MARKUPG_ROUTINE pfnDhcpMarkUpgrade;
  717. HMODULE hmod;
  718. hr = HrLoadLibAndGetProc(L"dhcpssvc.dll",
  719. "DhcpMarkUpgrade",
  720. &hmod,
  721. (FARPROC *)&pfnDhcpMarkUpgrade);
  722. if (SUCCEEDED(hr))
  723. {
  724. TraceTag(ttidDHCPServer, "Upgrading DS info...");
  725. pfnDhcpMarkUpgrade();
  726. FreeLibrary(hmod);
  727. }
  728. else
  729. {
  730. TraceHr(ttidDHCPServer, FAL, hr, FALSE,
  731. "CDHCPServer::ApplyRegistryChanges - Failed to upgrade DS info. Non-fatal");
  732. hr = S_OK;
  733. }
  734. }
  735. }
  736. else if (m_eInstallAction == eActRemove)
  737. {
  738. TraceTag(ttidDHCPServer, "ApplyRegistryChanges -- removing");
  739. // RAID #154380: Clean up DS before uninstalling
  740. {
  741. DHCP_CLEAR_DS_ROUTINE pfnDhcpDsClearHostServerEntries;
  742. HMODULE hmod;
  743. hr = HrLoadLibAndGetProc(L"dhcpsapi.dll",
  744. "DhcpDsClearHostServerEntries",
  745. &hmod,
  746. (FARPROC *)&pfnDhcpDsClearHostServerEntries);
  747. if (SUCCEEDED(hr))
  748. {
  749. TraceTag(ttidDHCPServer, "Removing DS info...");
  750. pfnDhcpDsClearHostServerEntries();
  751. FreeLibrary(hmod);
  752. }
  753. else
  754. {
  755. TraceHr(ttidDHCPServer, FAL, hr, FALSE,
  756. "CDHCPServer::ApplyRegistryChanges - Failed to remove DS info. Non-fatal");
  757. hr = S_OK;
  758. }
  759. }
  760. }
  761. Validate_INetCfgNotify_Apply_Return(hr);
  762. TraceHr(ttidDHCPServer, FAL, hr, (hr == S_FALSE), "CDHCPServer::ApplyRegistryChanges");
  763. return hr;
  764. }