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.

374 lines
11 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright(C) Microsoft Corporation all rights reserved.
  4. //
  5. // Module: setup.cpp
  6. //
  7. // Description: IAS MigrateOrUpgrade class implementation
  8. //
  9. /////////////////////////////////////////////////////////////////////////////
  10. #include "stdafx.h"
  11. #include "doupgrade.h"
  12. #include "iasdb.h"
  13. #include "setup.h" // to get the CIASMigrateOrUpgrade class
  14. #include "ias.h"
  15. #include "CheckLicense.h"
  16. ////////////////////////////
  17. // CIASMigrateOrUpgrade Constructor
  18. ////////////////////////////
  19. CIASMigrateOrUpgrade::CIASMigrateOrUpgrade()
  20. {
  21. ///////////////////////////////////////////////////////////////
  22. // Expand the three string even if two only might be needed in
  23. // the netshell scenario
  24. // The mdb files can be:
  25. // \ias\iasnew.mdb";
  26. // \ias\ias.mdb";
  27. // \ias\iasold.mdb";
  28. ///////////////////////////////////////////////////////////////
  29. wchar_t sysWow64Path[MAX_PATH+1] = L"";
  30. //
  31. // << GetSystemWow64Directory>> returns the number of chars copied to the buffer.
  32. // If we get zero back, then we need to check the last error code to see what the
  33. // reason for failure was. If it was call not implemented then we know we are
  34. // running on native x86.
  35. //
  36. UINT uReturn = GetSystemWow64DirectoryW(sysWow64Path, MAX_PATH);
  37. if ( uReturn != 0 )
  38. {
  39. // proper path found
  40. m_pIASNewMdb = sysWow64Path;
  41. m_pIASNewMdb += L"\\ias\\iasnew.mdb";
  42. m_pIASMdb = sysWow64Path;
  43. m_pIASMdb += L"\\ias\\ias.mdb";
  44. m_pIASOldMdb = sysWow64Path;
  45. m_pIASOldMdb += L"\\ias\\iasold.mdb";
  46. }
  47. else
  48. {
  49. // check the error message
  50. DWORD error = GetLastError();
  51. if (ERROR_CALL_NOT_IMPLEMENTED == error)
  52. {
  53. // Pure 32 bits environment
  54. uReturn = GetWindowsDirectoryW(sysWow64Path, MAX_PATH);
  55. if ( uReturn != 0 )
  56. {
  57. // proper path found
  58. m_pIASNewMdb = sysWow64Path;
  59. m_pIASNewMdb += L"\\System32\\ias\\iasnew.mdb";
  60. m_pIASMdb = sysWow64Path;
  61. m_pIASMdb += L"\\System32\\ias\\ias.mdb";
  62. m_pIASOldMdb = sysWow64Path;
  63. m_pIASOldMdb += L"\\System32\\ias\\iasold.mdb";
  64. }
  65. else
  66. {
  67. _com_issue_error(HRESULT_FROM_WIN32(error));
  68. }
  69. }
  70. else
  71. {
  72. _com_issue_error(HRESULT_FROM_WIN32(error));
  73. }
  74. }
  75. ///////////////////////////////////////////////
  76. // Check that all the strings are properly set
  77. ///////////////////////////////////////////////
  78. if ( !m_pIASNewMdb || !m_pIASMdb || !m_pIASOldMdb )
  79. {
  80. _com_issue_error(E_OUTOFMEMORY);
  81. }
  82. }
  83. /////////////////////////////////
  84. // CIASMigrateOrUpgrade::GetVersionNumber
  85. /////////////////////////////////
  86. LONG CIASMigrateOrUpgrade::GetVersionNumber(LPCWSTR DatabaseName)
  87. {
  88. if ( !DatabaseName )
  89. {
  90. _com_issue_error(E_INVALIDARG);
  91. }
  92. /////////////////////////////////////////////////
  93. // Check %TMP% and create a directory if needed
  94. // That's to fix a bug with JET
  95. /////////////////////////////////////////////////
  96. IASCreateTmpDirectory();
  97. CComPtr<IUnknown> Session = NULL;
  98. HRESULT hr = IASOpenJetDatabase(DatabaseName, TRUE, &Session);
  99. if ( FAILED(hr) )
  100. {
  101. _com_issue_error(hr);
  102. }
  103. CComBSTR SelectVersion(L"SELECT * FROM Version");
  104. if ( !SelectVersion )
  105. {
  106. _com_issue_error(E_OUTOFMEMORY);
  107. }
  108. LONG Version = 0;
  109. hr = IASExecuteSQLFunction(Session, SelectVersion, &Version);
  110. if ( FAILED(hr) ) // no Version table for instance
  111. {
  112. // Version 0. That's not an error
  113. }
  114. Session.Release();
  115. return Version;
  116. }
  117. ///////////////////////////////////////////////////////////////
  118. // CIASMigrateOrUpgrade::DoNetshellDataMigration
  119. // Reads as "Do Netshell Data Migration"
  120. //
  121. // The call to the upgrade is the result of a netshell script
  122. // ias.mdb is assumed present and good (Whistler).
  123. // iasold is assumed present and will be migrated into ias.mdb
  124. ///////////////////////////////////////////////////////////////
  125. void CIASMigrateOrUpgrade::DoNetshellDataMigration(
  126. IAS_SHOW_TOKEN_LIST configType
  127. )
  128. {
  129. CheckLicense(m_pIASOldMdb, configType);
  130. ///////////////////////////////////////////////////////
  131. // Now Upgrade the Win2k, Whistler 1.0 or Whistler 2.0
  132. // DB into the current Whistler 2.0 DB
  133. // The upgrade will throw if it fails
  134. ///////////////////////////////////////////////////////
  135. {
  136. CMigrateOrUpgradeWindowsDB Upgrade(configType);
  137. Upgrade.Execute();
  138. }
  139. }
  140. //////////////////////////////////////////////////
  141. // DoNT4UpgradeOrCleanInstall
  142. //
  143. // The file ias.mdb did not exist before
  144. // That's either a NT4 upgrade or a clean install
  145. // iasnew.mdb was successfuly copied into ias.mdb
  146. //////////////////////////////////////////////////
  147. void CIASMigrateOrUpgrade::DoNT4UpgradeOrCleanInstall()
  148. {
  149. ////////////////////////////////////
  150. // Delete iasnew.mdb no matter what
  151. ////////////////////////////////////
  152. DeleteFile(m_pIASNewMdb);
  153. //////////////////////////////////////////////////////
  154. // Call DoUpgrade: that will check if a NT4 migration
  155. // should be done or not and do it if necessary
  156. //////////////////////////////////////////////////////
  157. CDoNT4OrCleanUpgrade Upgrade;
  158. Upgrade.Execute();
  159. }
  160. /////////////////////////////////////////////////////////////////////////////
  161. // CIASMigrateOrUpgrade::DoWin2000Upgrade
  162. /////////////////////////////////////////////////////////////////////////////
  163. void CIASMigrateOrUpgrade::DoWin2000Upgrade()
  164. {
  165. LONG Result = ERROR_SUCCESS;
  166. //////////////////////////////////////////
  167. // now force copy ias.mdb into iasold.mdb
  168. //////////////////////////////////////////
  169. BOOL Succeeded = CopyFile(m_pIASMdb, m_pIASOldMdb, FALSE);
  170. if ( !Succeeded )
  171. {
  172. ////////////////////////////////////////////////
  173. // iasnew.mdb will still be copied into ias.mdb
  174. // later but not upgraded after that
  175. ////////////////////////////////////////////////
  176. Result = GetLastError();
  177. }
  178. //////////////////////////////////////
  179. // force copy iasnew.mdb into ias.mdb
  180. //////////////////////////////////////
  181. Succeeded = CopyFile(m_pIASNewMdb, m_pIASMdb, FALSE);
  182. if ( !Succeeded )
  183. {
  184. /////////////////////////////
  185. // do not upgrade after that
  186. /////////////////////////////
  187. Result = GetLastError();
  188. }
  189. ////////////////////////////////////////////////////
  190. // Delete iasnew.mdb no matter what: if the upgrade
  191. // throws an exception then iasnew.mdb will not be
  192. // left on the drive
  193. ////////////////////////////////////////////////////
  194. DeleteFile(m_pIASNewMdb);
  195. /////////////////////////////////////////////
  196. // Now Upgrade the Win2k or Whistler 1.0 DB
  197. // into the Whistler DB if the previous copy
  198. // operations were successful
  199. /////////////////////////////////////////////
  200. if ( Result == ERROR_SUCCESS )
  201. {
  202. ///////////////////////////////////
  203. // will throw if the upgrade fails
  204. ///////////////////////////////////
  205. CMigrateOrUpgradeWindowsDB Upgrade2k;
  206. Upgrade2k.Execute();
  207. }
  208. else
  209. {
  210. _com_issue_error(HRESULT_FROM_WIN32(Result));
  211. }
  212. ////////////////////////////////////
  213. // Delete iasold.mdb no matter what
  214. // here the upgrade was successful
  215. ////////////////////////////////////
  216. DeleteFile(m_pIASOldMdb);
  217. }
  218. ////////////////////////////////////////
  219. // CIASMigrateOrUpgrade::DoXPOrDotNetUpgrade
  220. //
  221. // nothing to do: already a Whistler DB
  222. ////////////////////////////////////////
  223. void CIASMigrateOrUpgrade::DoXPOrDotNetUpgrade()
  224. {
  225. ////////////////////////////////////
  226. // Delete iasnew.mdb no matter what
  227. ////////////////////////////////////
  228. DeleteFile(m_pIASNewMdb);
  229. }
  230. /////////////////////////////////////////////////////////////////////////////
  231. // CIASMigrateOrUpgrade::Execute
  232. /////////////////////////////////////////////////////////////////////////////
  233. HRESULT CIASMigrateOrUpgrade::Execute(
  234. BOOL FromNetshell,
  235. IAS_SHOW_TOKEN_LIST configType
  236. )
  237. {
  238. HRESULT hr = S_OK;
  239. ////////////////////////////
  240. // Now get the upgrade type
  241. ////////////////////////////
  242. do
  243. {
  244. if ( FromNetshell )
  245. {
  246. m_migrateType = NetshellDataMigration;
  247. break;
  248. }
  249. ///////////////////////////////////////
  250. // try to copy iasnew.mdb into ias.mdb
  251. // fails if the file is already there
  252. ///////////////////////////////////////
  253. BOOL IsNT4OrCleanInstall = CopyFile(m_pIASNewMdb, m_pIASMdb, TRUE);
  254. if ( IsNT4OrCleanInstall )
  255. {
  256. // select NT4 or Clean install
  257. m_migrateType = NT4UpgradeOrCleanInstall;
  258. break;
  259. }
  260. else // Win2k or Whistler upgrade
  261. {
  262. ///////////////////////////////////////////
  263. // cannot copy: the file is already there.
  264. // Check the version number (of ias.mdb)
  265. ///////////////////////////////////////////
  266. LONG CurrentVersion = GetVersionNumber(m_pIASMdb);
  267. if ( CurrentVersion < IAS_CURRENT_VERSION )
  268. {
  269. m_migrateType = Win2kUpgrade;
  270. break;
  271. }
  272. else
  273. {
  274. m_migrateType = XPOrDotNetUpgrade;
  275. break;
  276. }
  277. }
  278. }
  279. while (FALSE);
  280. try
  281. {
  282. switch ( m_migrateType )
  283. {
  284. case NetshellDataMigration:
  285. {
  286. DoNetshellDataMigration(configType);
  287. break;
  288. }
  289. case NT4UpgradeOrCleanInstall:
  290. {
  291. DoNT4UpgradeOrCleanInstall();
  292. break;
  293. }
  294. case Win2kUpgrade:
  295. {
  296. DoWin2000Upgrade();
  297. break;
  298. }
  299. case XPOrDotNetUpgrade:
  300. {
  301. DoXPOrDotNetUpgrade();
  302. break;
  303. }
  304. default:
  305. {
  306. _com_issue_error(E_FAIL);
  307. }
  308. }
  309. }
  310. catch(const _com_error& e)
  311. {
  312. hr = e.Error();
  313. }
  314. catch(...)
  315. {
  316. hr = HRESULT_FROM_WIN32(GetLastError());
  317. }
  318. if ( FromNetshell )
  319. {
  320. // From net shell, we never want to leave the temporary mdb -- even if we
  321. // failed.
  322. DeleteFile(m_pIASOldMdb);
  323. /////////////////////////////////////
  324. // Return the error code to netshell
  325. /////////////////////////////////////
  326. return hr;
  327. }
  328. else
  329. {
  330. ///////////////////////////////////////
  331. // Result ignored: no errors returned.
  332. ///////////////////////////////////////
  333. return S_OK;
  334. }
  335. }