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.

355 lines
7.7 KiB

  1. // Copyright (C) 1998 Microsoft Corporation
  2. //
  3. // DNS installation and configuration code
  4. //
  5. // 6-16-98 sburns
  6. #include "headers.hxx"
  7. #include "resource.h"
  8. #include "ProgressDialog.hpp"
  9. static const DWORD HELP_MAP[] =
  10. {
  11. 0, 0
  12. };
  13. static const int NAP_TIME = 3000; // in ms
  14. int
  15. millisecondsToSeconds(int millis)
  16. {
  17. static const int MILLIS_PER_SECOND = 1000;
  18. return millis / MILLIS_PER_SECOND;
  19. }
  20. bool
  21. pollForDNSServiceStart(ProgressDialog& progressDialog)
  22. {
  23. LOG_FUNCTION(PollForDNSServiceStart);
  24. for (int waitCount = 0; /* empty */ ; waitCount++)
  25. {
  26. progressDialog.UpdateText(
  27. String::format(
  28. IDS_WAITING_FOR_SERVICE_START,
  29. millisecondsToSeconds(NAP_TIME * waitCount)));
  30. if (progressDialog.WaitForButton(NAP_TIME) == ProgressDialog::PRESSED)
  31. {
  32. progressDialog.UpdateButton(String());
  33. popup.Info(
  34. progressDialog.GetHWND(),
  35. String::load(IDS_SKIP_DNS_MESSAGE));
  36. break;
  37. }
  38. if (Dns::IsServiceRunning())
  39. {
  40. // success!
  41. return true;
  42. }
  43. }
  44. return false;
  45. }
  46. bool
  47. pollForDNSServiceInstallAndStart(ProgressDialog& progressDialog)
  48. {
  49. LOG_FUNCTION(pollForDNSServiceInstallAndStart);
  50. for (int waitCount = 0; /* empty */ ; waitCount++)
  51. {
  52. progressDialog.UpdateText(
  53. String::format(
  54. IDS_WAITING_FOR_SERVICE_INSTALL,
  55. millisecondsToSeconds(NAP_TIME * waitCount)));
  56. if (progressDialog.WaitForButton(NAP_TIME) == ProgressDialog::PRESSED)
  57. {
  58. progressDialog.UpdateButton(String());
  59. popup.Info(
  60. progressDialog.GetHWND(),
  61. String::load(IDS_SKIP_DNS_MESSAGE));
  62. break;
  63. }
  64. if (Dns::IsServiceInstalled())
  65. {
  66. // Service is installed. Now check to see if it is running.
  67. return pollForDNSServiceStart(progressDialog);
  68. }
  69. }
  70. return false;
  71. }
  72. HRESULT
  73. createTempFile(const String& name, int textResID)
  74. {
  75. LOG_FUNCTION2(createTempFile, name);
  76. ASSERT(!name.empty());
  77. ASSERT(textResID);
  78. HRESULT hr = S_OK;
  79. HANDLE h = INVALID_HANDLE_VALUE;
  80. do
  81. {
  82. hr =
  83. FS::CreateFile(
  84. name,
  85. h,
  86. GENERIC_WRITE,
  87. 0,
  88. CREATE_ALWAYS,
  89. FILE_ATTRIBUTE_NORMAL);
  90. BREAK_ON_FAILED_HRESULT(hr);
  91. AnsiString ansi;
  92. String::load(textResID).convert(ansi);
  93. ASSERT(!ansi.empty());
  94. // write to file with end of file character.
  95. hr = FS::Write(h, ansi + "\032");
  96. BREAK_ON_FAILED_HRESULT(hr);
  97. }
  98. while (0);
  99. Win::CloseHandle(h);
  100. return hr;
  101. }
  102. HRESULT
  103. spawnDNSInstaller(PROCESS_INFORMATION& info)
  104. {
  105. LOG_FUNCTION(spawnDNSInstaller);
  106. HRESULT hr = S_OK;
  107. // CODEWORK: use GetTempPath?
  108. String sysFolder = Win::GetSystemDirectory();
  109. String infPath = sysFolder + L"\\dcpinf.000";
  110. String unattendPath = sysFolder + L"\\dcpunat.001";
  111. // create the inf and unattend files for the oc manager
  112. do
  113. {
  114. hr = createTempFile(infPath, IDS_INSTALL_DNS_INF_TEXT);
  115. BREAK_ON_FAILED_HRESULT(hr);
  116. hr = createTempFile(unattendPath, IDS_INSTALL_DNS_UNATTEND_TEXT);
  117. BREAK_ON_FAILED_HRESULT(hr);
  118. String commandLine =
  119. String::format(
  120. IDS_INSTALL_DNS_COMMAND_LINE,
  121. sysFolder.c_str(),
  122. infPath.c_str(),
  123. unattendPath.c_str());
  124. STARTUPINFO startup;
  125. memset(&startup, 0, sizeof(startup));
  126. LOG(L"Calling CreateProcess");
  127. LOG(commandLine);
  128. hr =
  129. Win::CreateProcess(
  130. commandLine,
  131. 0,
  132. 0,
  133. false,
  134. 0,
  135. 0,
  136. String(),
  137. startup,
  138. info);
  139. BREAK_ON_FAILED_HRESULT(hr);
  140. }
  141. while (0);
  142. return hr;
  143. }
  144. bool
  145. installDNS(ProgressDialog& progressDialog)
  146. {
  147. LOG_FUNCTION(installDNS);
  148. if (Dns::IsServiceInstalled())
  149. {
  150. LOG(L"DNS service is already installed");
  151. if (Dns::IsServiceRunning())
  152. {
  153. LOG(L"DNS service is already running");
  154. return true;
  155. }
  156. // @@ start the DNS service Dns::StartService?
  157. }
  158. progressDialog.UpdateText(String::load(IDS_INSTALLING_DNS));
  159. PROCESS_INFORMATION info;
  160. HRESULT hr = spawnDNSInstaller(info);
  161. if (FAILED(hr))
  162. {
  163. progressDialog.UpdateText(
  164. String::load(IDS_PROGRESS_ERROR_INSTALLING_DNS));
  165. popup.Error(
  166. progressDialog.GetHWND(),
  167. hr,
  168. IDS_ERROR_LAUNCHING_INSTALLER);
  169. return false;
  170. }
  171. progressDialog.UpdateButton(IDS_PROGRESS_BUTTON_SKIP_DNS);
  172. // monitor the state of the installer process.
  173. for (int waitCount = 0; /* empty */ ; waitCount++)
  174. {
  175. progressDialog.UpdateText(
  176. String::format(
  177. IDS_WAITING_FOR_INSTALLER,
  178. millisecondsToSeconds(NAP_TIME * waitCount)));
  179. if (progressDialog.WaitForButton(NAP_TIME) == ProgressDialog::PRESSED)
  180. {
  181. progressDialog.UpdateButton(String());
  182. popup.Info(
  183. progressDialog.GetHWND(),
  184. String::load(IDS_SKIP_DNS_MESSAGE));
  185. break;
  186. }
  187. DWORD exitCode = 0;
  188. hr = Win::GetExitCodeProcess(info.hProcess, exitCode);
  189. if (FAILED(hr))
  190. {
  191. LOG(L"GetExitCodeProcess failed");
  192. LOG_HRESULT(hr);
  193. progressDialog.UpdateText(
  194. String::load(IDS_PROGRESS_ERROR_INSTALLING_DNS));
  195. popup.Error(
  196. progressDialog.GetHWND(),
  197. hr,
  198. IDS_ERROR_QUERYING_INSTALLER);
  199. return false;
  200. }
  201. if (exitCode != STILL_ACTIVE)
  202. {
  203. // installer has terminated. Now check the status of the DNS
  204. // service
  205. return pollForDNSServiceInstallAndStart(progressDialog);
  206. }
  207. }
  208. // user bailed out
  209. return false;
  210. }
  211. bool
  212. InstallAndConfigureDns(
  213. ProgressDialog& progressDialog,
  214. const String& domainDNSName)
  215. {
  216. LOG_FUNCTION2(DNSSetup, domainDNSName);
  217. ASSERT(!domainDNSName.empty());
  218. if (!installDNS(progressDialog))
  219. {
  220. return false;
  221. }
  222. progressDialog.UpdateText(String::load(IDS_CONFIGURING_DNS));
  223. HINSTANCE dnsmgr = 0;
  224. HRESULT hr = Win::LoadLibrary(String::load(IDS_DNSMGR_DLL_NAME), dnsmgr);
  225. if (SUCCEEDED(hr))
  226. {
  227. FARPROC proc = 0;
  228. hr = Win::GetProcAddress(dnsmgr, L"DnsSetup", proc);
  229. if (SUCCEEDED(hr))
  230. {
  231. String p1 = domainDNSName;
  232. if (*(p1.rbegin()) != L'.')
  233. {
  234. // add trailing dot
  235. p1 += L'.';
  236. }
  237. String p2 = p1 + L"dns";
  238. LOG(L"Calling DnsSetup");
  239. LOG(String::format(L"lpszFwdZoneName : %1", p1.c_str()));
  240. LOG(String::format(L"lpszFwdZoneFileName : %1", p2.c_str()));
  241. LOG( L"lpszRevZoneName : (null)");
  242. LOG( L"lpszRevZoneFileName : (null)");
  243. LOG( L"dwFlags : 0");
  244. typedef HRESULT (*DNSSetup)(PCWSTR, PCWSTR, PCWSTR, PCWSTR, DWORD);
  245. DNSSetup dnsproc = reinterpret_cast<DNSSetup>(proc);
  246. hr = dnsproc(p1.c_str(), p2.c_str(), 0, 0, 0);
  247. }
  248. else
  249. {
  250. LOG(L"unable to locate DnsSetup proc address");
  251. }
  252. HRESULT unused = Win::FreeLibrary(dnsmgr);
  253. ASSERT(SUCCEEDED(unused));
  254. }
  255. else
  256. {
  257. LOG(L"unable to load DNSMGR");
  258. }
  259. LOG_HRESULT(hr);
  260. if (FAILED(hr))
  261. {
  262. // unable to configure DNS, but it was installed.
  263. progressDialog.UpdateText(
  264. String::load(IDS_PROGRESS_ERROR_CONFIGURING_DNS));
  265. popup.Error(
  266. progressDialog.GetHWND(),
  267. hr,
  268. String::format(IDS_ERROR_CONFIGURING_DNS, domainDNSName.c_str()));
  269. return false;
  270. }
  271. return true;
  272. }