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.

391 lines
12 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // SaInstall.cpp : Implementation of SaInstall
  7. //
  8. // Description:
  9. // Implements the 3 methods in ISaInstall to provide
  10. // installation and uninstallation of the SAK 2.0.
  11. // SASetup.msi is located and run from the system32 directory.
  12. //
  13. // Documentation:
  14. // SaInstall2.2.doc
  15. //
  16. // Header File:
  17. // SaInstall.h
  18. //
  19. // History:
  20. // travisn 23-JUL-2001 Created
  21. // travisn 2-AUG-2001 Modified to better follow coding standards
  22. // travisn 22-AUG-2001 Added file tracing calls
  23. // travisn 5-OCT-2001 Added UsersAndGroups to Blade
  24. //
  25. //////////////////////////////////////////////////////////////////////////////
  26. #include "stdafx.h"
  27. #include <initguid.h>
  28. #include <assert.h>
  29. #include "sainstallcom.h"
  30. #include "SaInstall.h"
  31. #include "MetabaseObject.h"
  32. #include "helper.h"
  33. #include "satrace.h"
  34. /////////////////////////////////////////////////////////////////////////////
  35. // Define constants
  36. /////////////////////////////////////////////////////////////////////////////
  37. //
  38. // Command line options for a silent install, prepended to other options
  39. //
  40. const LPCWSTR MSIEXEC_INSTALL = L"msiexec.exe /qb /i ";
  41. //
  42. // Command line options for a silent install without a progress dialog
  43. //
  44. const LPCWSTR MSIEXEC_NO_PROGRESS_INSTALL = L"msiexec.exe /qn /i ";
  45. //
  46. // Install 16 components for WEB
  47. // What WEB has that NAS doesn't: WebBlade
  48. //
  49. const LPCWSTR WEB_INSTALL_OPTIONS =
  50. L" ADDLOCAL=BackEndFramework,WebUI,WebCore,SetDateAndTime,Set_Language,\
  51. NetworkSetup,Logs,AlertEmail,Shutdown,\
  52. UsersAndGroups,RemoteDesktop,SysInfo,WebBlade";
  53. //
  54. // Other command line options
  55. //
  56. const LPCWSTR REMOVE_ALL = L"msiexec /qn /X";
  57. //Path to IIS in the metabase
  58. const LPCWSTR METABASE_IIS_PATH = L"LM/w3svc";
  59. //////////////////////////////////////////////////////////////////////////////
  60. //
  61. // SaInstall::SAAlreadyInstalled
  62. //
  63. // Description:
  64. // Detects if a type of Server Appliance is installed.
  65. //
  66. // Arguments:
  67. // [in] SA_TYPE: The type of SA to query (NAS or WEB)
  68. // [OUT] VARIANT_BOOL: Whether this type of SA is installed
  69. //
  70. // Returns:
  71. // HRESULT
  72. //
  73. // history:
  74. // travisn Created 23-JUL-2001
  75. //
  76. //////////////////////////////////////////////////////////////////////////////
  77. STDMETHODIMP SaInstall::SAAlreadyInstalled(
  78. const SA_TYPE installedType, //[in] Is a NAS or WEB solution is installed?
  79. VARIANT_BOOL *pbInstalled)//[out] tells if the SAK is already installed
  80. {
  81. HRESULT hr = S_OK;
  82. SATraceString ("Entering SaInstall::SAAlreadyInstalled");
  83. try
  84. {
  85. //Check to see if a valid SAK type was passed in
  86. if (installedType != NAS && installedType != WEB)
  87. {
  88. hr = E_ABORT;
  89. SATraceString (" Invalid installedType");
  90. }
  91. else
  92. { //Check to see if the NAS or WEB is installed
  93. *pbInstalled = bSAIsInstalled(installedType) ? VARIANT_TRUE : VARIANT_FALSE;
  94. hr = S_OK;
  95. }
  96. }
  97. catch (...)
  98. {
  99. hr = E_FAIL;
  100. }
  101. //Single point of return
  102. SATraceString ("Exiting SaInstall::SAAlreadyInstalled");
  103. return hr;
  104. }
  105. //////////////////////////////////////////////////////////////////////////////
  106. //
  107. // SaInstall::SAUninstall
  108. //
  109. // Description:
  110. // Uninstalls a Server Appliance solution, if the type requested
  111. // is installed.
  112. //
  113. // Arguments:
  114. // [in] SA_TYPE: The type to uninstall (WEB)
  115. // [OUT] BSTR*: Currently there are no reported errors
  116. // Returns:
  117. // HRESULT
  118. //
  119. // history:
  120. // travisn Created 23-JUL-2001
  121. //
  122. //////////////////////////////////////////////////////////////////////////////
  123. STDMETHODIMP SaInstall::SAUninstall(
  124. const SA_TYPE uninstallType, //[in]Type of SAK to uninstall
  125. BSTR* pbstrErrorString)//[out]
  126. {
  127. SATraceString ("Entering SaInstall::SAUninstall");
  128. //Clear out the error string
  129. *pbstrErrorString = NULL;
  130. HRESULT hr = S_OK;
  131. try
  132. {
  133. //
  134. // Create this do...while(false) loop to create a single point
  135. // of return
  136. //
  137. do
  138. {
  139. if (uninstallType != WEB)
  140. {
  141. //Unidentified or unsupported type to uninstall
  142. hr = E_ABORT;
  143. ReportError(pbstrErrorString, VARIANT_FALSE, IDS_INVALID_TYPE);
  144. break;
  145. }
  146. //Detect if it's installed
  147. if (bSAIsInstalled(WEB))
  148. {
  149. //
  150. // uninstall the whole thing.
  151. // Generate the command line to call MSI to uninstall the package
  152. //
  153. wstring wsCommand(REMOVE_ALL);
  154. wsCommand += SAK_PRODUCT_CODE;
  155. hr = CreateHiddenConsoleProcess(wsCommand.data());
  156. if (FAILED(hr))
  157. {
  158. ReportError(pbstrErrorString, VARIANT_FALSE, IDS_UNINSTALL_SA_FAILED);
  159. }
  160. break;
  161. }
  162. //
  163. // Neither of these types are installed, so report an error
  164. // since they shouldn't have requested to uninstall.
  165. //
  166. ReportError(pbstrErrorString, VARIANT_FALSE, IDS_NOT_INSTALLED);
  167. //
  168. // Since trying to uninstall something that is not present
  169. // isn't fatal, return S_FALSE
  170. //
  171. hr = S_FALSE;
  172. }
  173. while (false);
  174. }
  175. catch (...)
  176. {
  177. hr = E_FAIL;
  178. }
  179. //Single point of return
  180. SATraceString ("Exiting SaInstall::SAUninstall");
  181. return hr;
  182. }
  183. //////////////////////////////////////////////////////////////////////////////
  184. //
  185. // SaInstall::SAInstall
  186. //
  187. // Description:
  188. // Installs a Server Appliance solution, depending on the arguments.
  189. // Does some simple error checking to make sure that SaSetup.msi
  190. // is present, and displays error messages if any errors occur.
  191. //
  192. // Arguments:
  193. // [in] SA_TYPE: The type to install (NAS or WEB)
  194. // [in] BSTR: The name of the CD that will be prompted for if
  195. // SaSetup.msi is not found. Not used anymore
  196. // [in] VARIANT_BOOL: Whether error dialog prompts will appear
  197. // [in] VARIANT_BOOL: Whether the install is unattended
  198. // [OUT] BSTR*: If an error occurs during installation, the error
  199. // string is returned here
  200. // Returns:
  201. // HRESULT
  202. //
  203. // history:
  204. // travisn Created 23-JUL-2001
  205. //
  206. //////////////////////////////////////////////////////////////////////////////
  207. STDMETHODIMP SaInstall::SAInstall(
  208. const SA_TYPE installType, //[in]
  209. const BSTR bstrDiskName, //[in]
  210. const VARIANT_BOOL bDispError, //[in]
  211. const VARIANT_BOOL bUnattended, //[in]
  212. BSTR* pbstrErrorString) //[out]
  213. {
  214. HRESULT hr = E_FAIL;
  215. SATraceString("Entering SaInstall::SAInstall");
  216. try
  217. {
  218. //Clear out the error string
  219. *pbstrErrorString = NULL;
  220. //
  221. // Create this do...while(false) loop to create a single point
  222. // of return
  223. //
  224. do
  225. { //
  226. //Check the parameters
  227. //
  228. //Check to see if a valid SAK type was passed in
  229. if (installType != WEB)
  230. {
  231. ReportError(pbstrErrorString, VARIANT_FALSE, IDS_INVALID_TYPE);
  232. break;
  233. }
  234. //Check to see if this SAK type is already installed
  235. if (bSAIsInstalled(installType))
  236. {
  237. ReportError(pbstrErrorString, VARIANT_FALSE, IDS_ALREADY_INSTALLED);
  238. break;
  239. }
  240. //
  241. // Make sure that IIS is installed and functioning
  242. //
  243. { // CMetabaseObject must go out of scope to avoid keeping a read-lock
  244. // on the metabase during our install
  245. CMetabaseObject metabase;
  246. hr = metabase.openObject(METABASE_IIS_PATH);
  247. if (FAILED(hr))
  248. {
  249. ReportError(pbstrErrorString, VARIANT_FALSE, IDS_IIS_NOT_INSTALLED);
  250. break; // Something wrong with IIS installation
  251. }
  252. }
  253. //
  254. // Make sure we're installing on an NTFS partition
  255. //
  256. if (!InstallingOnNTFS())
  257. {
  258. ReportError(pbstrErrorString, VARIANT_FALSE, IDS_NTFS_REQUIRED);
  259. hr = E_FAIL;
  260. break;
  261. }
  262. //
  263. // Find the path to SaSetup.msi in system32
  264. //
  265. wstring wsLocationOfSaSetup;
  266. hr = GetInstallLocation(wsLocationOfSaSetup);
  267. if (FAILED(hr))
  268. {
  269. ReportError(pbstrErrorString, VARIANT_FALSE, IDS_SASETUP_NOT_FOUND);
  270. break;
  271. }
  272. //
  273. // Create the complete command line for the SaSetup, whether for NAS or
  274. // WebBlade. We already have the complete path to SaSetup.msi in
  275. // wsLocationOfSaSetup, so we need to append the command-line parameters.
  276. //
  277. //Create the command-line options applicable to all installations
  278. wstring wsCommand;
  279. //
  280. // There are 3 sources that call this installation: CYS, IIS, and SaInstall.exe.
  281. // We want to display a progress dialog for CYS and IIS, but not SaInstall.
  282. // SaInstall is the only source that calls this function with bDispError == true.
  283. //
  284. if (bDispError)
  285. wsCommand = MSIEXEC_NO_PROGRESS_INSTALL;
  286. else
  287. wsCommand = MSIEXEC_INSTALL;
  288. wsCommand += wsLocationOfSaSetup;
  289. //Install a Web solution
  290. wsCommand += WEB_INSTALL_OPTIONS;
  291. //
  292. //Take the command line and create a hidden window to execute it
  293. //
  294. hr = CreateHiddenConsoleProcess(wsCommand.data());
  295. if (FAILED(hr))
  296. {
  297. ReportError(pbstrErrorString, VARIANT_FALSE, IDS_SASETUP_FAILED);
  298. break;
  299. }
  300. //
  301. // Check to make sure that the installation completed successfully
  302. // in case the user aborted by clicking Cancel
  303. // If they did cancel, return E_FAIL
  304. // If it is a valid installation, return S_OK
  305. // This is necessary since the return value from the MSI process
  306. // always returns SUCCESS, even if the user aborted
  307. //
  308. if (!bSAIsInstalled(installType))
  309. {
  310. ReportError(pbstrErrorString, VARIANT_FALSE, IDS_INSTALL_FAILED);
  311. hr = E_FAIL;
  312. break;
  313. }
  314. //
  315. // Test to make sure the Admin site started
  316. //
  317. TestWebSites(bDispError, pbstrErrorString);
  318. hr = S_OK;
  319. }
  320. while (false);
  321. }
  322. catch (...)
  323. {
  324. SATraceString ("Unexpected exception in SAInstall::SAInstall");
  325. //Unexpected exception!!
  326. }
  327. SATraceString("Exiting SAInstall::SAInstall");
  328. //Single point of return
  329. return hr;
  330. }
  331. //////////////////////////////////////////////////////////////////////////////
  332. //++
  333. //
  334. // SaInstall::InterfaceSupportsErrorInfo
  335. //
  336. // Description:
  337. // From Interface ISupportErrorInfo
  338. //
  339. // history
  340. // travisn 2-AUG-2001 Some comments added
  341. //--
  342. //////////////////////////////////////////////////////////////////////////////
  343. STDMETHODIMP SaInstall::InterfaceSupportsErrorInfo(REFIID riid)//[in]
  344. {
  345. if (InlineIsEqualGUID(IID_ISaInstall, riid))
  346. {
  347. return S_OK;
  348. }
  349. return S_FALSE;
  350. }