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.

1697 lines
49 KiB

  1. /******************************************************************************
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. InstalledDatabaseStore.cpp
  5. Abstract:
  6. This file contains the implementation of the Taxonomy::InstalledInstanceStore class,
  7. which controls the set of Topic Databases installed on the machine.
  8. Revision History:
  9. Davide Massarenti (Dmassare) 05/01/2000
  10. created
  11. ******************************************************************************/
  12. #include "stdafx.h"
  13. #include <SAFLIB.h>
  14. #include <SEConfig.h>
  15. ////////////////////////////////////////////////////////////////////////////////
  16. static const WCHAR c_DB_BUGREPT [] = L"bugrept.cab";
  17. static const WCHAR c_DB_RCBDY [] = L"rcBuddy.cab";
  18. static const WCHAR c_DB_PSS [] = L"pss.cab";
  19. static const WCHAR c_DB_NEWSGROUPS[] = L"newsgroups.cab";
  20. static const WCHAR c_REG_BACKUP [] = L"PackageStore";
  21. static const WCHAR c_REG_CRC [] = L"CRC_Disk";
  22. static const WCHAR c_REG_CRC_BAK[] = L"CRC_Registry";
  23. ////////////////////////////////////////////////////////////////////////////////
  24. LPCWSTR const Taxonomy::Strings::s_file_PackageDescription = L"package_description.xml";
  25. LPCWSTR const Taxonomy::Strings::s_tag_root_PackageDescription = L"HELPCENTERPACKAGE";
  26. LPCWSTR const Taxonomy::Strings::s_tag_root_HHT = L"METADATA";
  27. LPCWSTR const Taxonomy::Strings::s_tag_root_SAF = L"SAFConfig";
  28. ////////////////////////////////////////////////////////////////////////////////
  29. static void local_GetFileForCRC( /*[out]*/ MPC::wstring& strDest ,
  30. /*[in]*/ LPCWSTR szValue )
  31. {
  32. strDest = HC_ROOT_HELPSVC_PKGSTORE L"\\";
  33. strDest += szValue;
  34. MPC::SubstituteEnvVariables( strDest );
  35. }
  36. static HRESULT local_OpenForRead( /*[in/out]*/ MPC::RegKey& rkBase )
  37. {
  38. __HCP_FUNC_ENTRY( "local_OpenForRead" );
  39. HRESULT hr;
  40. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.SetRoot( HKEY_LOCAL_MACHINE ));
  41. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.Attach ( HC_REGISTRY_HELPSVC L"\\Backup" ));
  42. hr = S_OK;
  43. __HCP_FUNC_CLEANUP;
  44. __HCP_FUNC_EXIT(hr);
  45. }
  46. static HRESULT local_OpenForWrite( /*[in/out]*/ MPC::RegKey& rkBase )
  47. {
  48. __HCP_FUNC_ENTRY( "local_OpenForWrite" );
  49. HRESULT hr;
  50. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.SetRoot( HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS ));
  51. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.Attach ( HC_REGISTRY_HELPSVC L"\\Backup" ));
  52. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.Create ( ));
  53. hr = S_OK;
  54. __HCP_FUNC_CLEANUP;
  55. __HCP_FUNC_EXIT(hr);
  56. }
  57. static HRESULT local_CreateCRC( /*[in]*/ MPC::RegKey* rkBase ,
  58. /*[in]*/ LPCWSTR szValue ,
  59. /*[in]*/ IStream* stream )
  60. {
  61. __HCP_FUNC_ENTRY( "local_CreateCRC" );
  62. HRESULT hr;
  63. LARGE_INTEGER li = { 0, 0 };
  64. DWORD dwCRC; MPC::InitCRC( dwCRC );
  65. __MPC_EXIT_IF_METHOD_FAILS(hr, stream->Seek( li, STREAM_SEEK_SET, NULL ));
  66. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ComputeCRC( dwCRC, stream ));
  67. if(rkBase)
  68. {
  69. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase->Write( dwCRC, szValue ));
  70. }
  71. else
  72. {
  73. MPC::wstring strDest;
  74. CComPtr<MPC::FileStream> stream2;
  75. ULONG cb;
  76. local_GetFileForCRC( strDest, szValue );
  77. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::SafeSave_Init( strDest.c_str(), stream2 ));
  78. __MPC_EXIT_IF_METHOD_FAILS(hr, stream2->Write( &dwCRC, sizeof(dwCRC), &cb )); stream2.Release();
  79. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::SafeSave_Finalize( strDest.c_str(), stream2 ));
  80. }
  81. hr = S_OK;
  82. __HCP_FUNC_CLEANUP;
  83. __HCP_FUNC_EXIT(hr);
  84. }
  85. static HRESULT local_CheckCRC( /*[in]*/ MPC::RegKey* rkBase ,
  86. /*[in]*/ LPCWSTR szValue ,
  87. /*[in]*/ IStream* stream )
  88. {
  89. __HCP_FUNC_ENTRY( "local_CheckCRC" );
  90. HRESULT hr;
  91. DWORD dwCRC;
  92. bool fFound = false;
  93. if(rkBase)
  94. {
  95. if(FAILED(rkBase->Read( dwCRC, fFound, szValue ))) fFound = false;
  96. }
  97. else
  98. {
  99. MPC::wstring strDest;
  100. CComPtr<MPC::FileStream> stream2;
  101. local_GetFileForCRC( strDest, szValue );
  102. if(SUCCEEDED(SVC::SafeLoad( strDest.c_str(), stream2 )))
  103. {
  104. ULONG cb;
  105. if(SUCCEEDED(stream2->Read( &dwCRC, sizeof(dwCRC), &cb )) && cb == sizeof(dwCRC))
  106. {
  107. fFound = true;
  108. }
  109. }
  110. }
  111. if(fFound)
  112. {
  113. LARGE_INTEGER li = { 0, 0 };
  114. DWORD dwCRC2; MPC::InitCRC( dwCRC2 );
  115. __MPC_EXIT_IF_METHOD_FAILS(hr, stream->Seek( li, STREAM_SEEK_SET, NULL ));
  116. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ComputeCRC( dwCRC2, stream ));
  117. if(dwCRC != dwCRC2)
  118. {
  119. __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  120. }
  121. }
  122. hr = S_OK;
  123. __HCP_FUNC_CLEANUP;
  124. __HCP_FUNC_EXIT(hr);
  125. }
  126. ////////////////////
  127. static HRESULT local_AddPackage( /*[in ]*/ Taxonomy::InstalledInstanceStore* store ,
  128. /*[in/out]*/ MPC::wstring& strTmp ,
  129. /*[in ]*/ const MPC::wstring& strDir ,
  130. /*[in ]*/ LPCWSTR szExtra ,
  131. /*[in ]*/ const Taxonomy::HelpSet& ths )
  132. {
  133. __HCP_FUNC_ENTRY( "local_AddPackage" );
  134. HRESULT hr;
  135. Taxonomy::PackageIter it;
  136. bool fFound;
  137. strTmp = strDir; strTmp.append( szExtra );
  138. __MPC_EXIT_IF_METHOD_FAILS(hr, store->Package_Add( strTmp.c_str(), NULL, &ths, /*fInsertAtTop*/true, fFound, it ));
  139. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::DeleteFile ( strTmp ));
  140. hr = S_OK;
  141. __HCP_FUNC_CLEANUP;
  142. __HCP_FUNC_EXIT(hr);
  143. }
  144. ////////////////////////////////////////////////////////////////////////////////
  145. HRESULT Taxonomy::Instance::InitializeFromBase( /*[in]*/ const InstanceBase& base, /*[in]*/ bool fSystem, /*[in]*/ bool fMUI )
  146. {
  147. __HCP_FUNC_ENTRY( "Taxonomy::Instance::InitializeFromBase" );
  148. HRESULT hr;
  149. Taxonomy::Settings ts( base.m_ths );
  150. ((InstanceBase&)*this) = base;
  151. m_fSystem = fSystem;
  152. m_fMUI = fMUI;
  153. if(fSystem)
  154. {
  155. //
  156. // Set machine-wide defaults.
  157. //
  158. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::HelpSet::SetMachineInfo ( base ));
  159. __MPC_EXIT_IF_METHOD_FAILS(hr, OfflineCache::Root::s_GLOBAL->SetMachineInfo( *this ));
  160. }
  161. __MPC_EXIT_IF_METHOD_FAILS(hr, ts.BaseDir ( m_strSystem , /*fExpand*/false ));
  162. __MPC_EXIT_IF_METHOD_FAILS(hr, ts.HelpFilesDir( m_strHelpFiles, /*fExpand*/false, /*fMUI*/m_fMUI ));
  163. __MPC_EXIT_IF_METHOD_FAILS(hr, ts.DatabaseDir ( m_strDatabaseDir ));
  164. __MPC_EXIT_IF_METHOD_FAILS(hr, ts.DatabaseFile( m_strDatabaseFile ));
  165. __MPC_EXIT_IF_METHOD_FAILS(hr, ts.IndexFile ( m_strIndexFile ));
  166. hr = S_OK;
  167. __HCP_FUNC_CLEANUP;
  168. __HCP_FUNC_EXIT(hr);
  169. }
  170. HRESULT Taxonomy::Instance::Import( /*[in]*/ LPCWSTR szFile, /*[in/out]*/ DWORD* pdwCRC )
  171. {
  172. __HCP_FUNC_ENTRY( "Taxonomy::Instance::Import" );
  173. HRESULT hr;
  174. MPC::wstring strFileDst;
  175. __MPC_EXIT_IF_METHOD_FAILS(hr, GetFileName ( strFileDst ));
  176. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CopyFile( szFile, strFileDst.c_str() ));
  177. ::SetFileAttributesW( strFileDst.c_str(), FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM );
  178. if(pdwCRC)
  179. {
  180. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ComputeCRC( *pdwCRC, strFileDst.c_str() ));
  181. }
  182. hr = S_OK;
  183. __HCP_FUNC_CLEANUP;
  184. __HCP_FUNC_EXIT(hr);
  185. }
  186. HRESULT Taxonomy::Instance::Remove()
  187. {
  188. __HCP_FUNC_ENTRY( "Taxonomy::Instance::Remove" );
  189. HRESULT hr;
  190. MPC::wstring strFileDst;
  191. __MPC_EXIT_IF_METHOD_FAILS(hr, GetFileName ( strFileDst ));
  192. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::DeleteFile( strFileDst ));
  193. hr = S_OK;
  194. __HCP_FUNC_CLEANUP;
  195. __HCP_FUNC_EXIT(hr);
  196. }
  197. ////////////////////////////////////////////////////////////////////////////////
  198. Taxonomy::InstalledInstance::InstalledInstance()
  199. {
  200. // Instance m_inst;
  201. // ProcessedPackageList m_lst;
  202. m_fInvalidated = false; // bool m_fInvalidated;
  203. m_fRecreateCache = true; // bool m_fRecreateCache;
  204. m_fCreateIndex = true; // bool m_fCreateIndex;
  205. m_fCreateIndexForce = true; // bool m_fCreateIndexForce;
  206. m_dwCRC = 0; // DWORD m_dwCRC;
  207. //
  208. m_dwRef = 0; // DWORD m_dwRef; // VOLATILE
  209. }
  210. HRESULT Taxonomy::operator>>( /*[in]*/ MPC::Serializer& stream, /*[out]*/ Taxonomy::InstalledInstance& val )
  211. {
  212. HRESULT hr;
  213. if(SUCCEEDED(hr = (stream >> val.m_inst )) &&
  214. SUCCEEDED(hr = (stream >> val.m_lst )) &&
  215. SUCCEEDED(hr = (stream >> val.m_fInvalidated )) &&
  216. SUCCEEDED(hr = (stream >> val.m_fRecreateCache )) &&
  217. SUCCEEDED(hr = (stream >> val.m_fCreateIndex )) &&
  218. SUCCEEDED(hr = (stream >> val.m_fCreateIndexForce)) &&
  219. SUCCEEDED(hr = (stream >> val.m_dwCRC )) )
  220. {
  221. hr = S_OK;
  222. }
  223. return hr;
  224. }
  225. HRESULT Taxonomy::operator<<( /*[in]*/ MPC::Serializer& stream, /*[in] */ const Taxonomy::InstalledInstance& val )
  226. {
  227. HRESULT hr;
  228. if(SUCCEEDED(hr = (stream << val.m_inst )) &&
  229. SUCCEEDED(hr = (stream << val.m_lst )) &&
  230. SUCCEEDED(hr = (stream << val.m_fInvalidated )) &&
  231. SUCCEEDED(hr = (stream << val.m_fRecreateCache )) &&
  232. SUCCEEDED(hr = (stream << val.m_fCreateIndex )) &&
  233. SUCCEEDED(hr = (stream << val.m_fCreateIndexForce)) &&
  234. SUCCEEDED(hr = (stream << val.m_dwCRC )) )
  235. {
  236. hr = S_OK;
  237. }
  238. return hr;
  239. }
  240. HRESULT Taxonomy::InstalledInstance::InstallFiles( /*[in]*/ bool fAlsoHelpFiles ,
  241. /*[in]*/ InstalledInstanceStore* store )
  242. {
  243. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstance::InstallFiles" );
  244. HRESULT hr;
  245. Taxonomy::Settings ts( m_inst.m_ths );
  246. Installer::Package pkg;
  247. MPC::wstring strDir_System;
  248. MPC::wstring strDir_HelpFiles;
  249. MPC::wstring strDir_Database;
  250. MPC::wstring strFile_Database;
  251. MPC::wstring strFile_SetupImage;
  252. bool fReinstall = (store == NULL);
  253. __MPC_EXIT_IF_METHOD_FAILS(hr, ts.BaseDir ( strDir_System , /*fExpand*/false ));
  254. __MPC_EXIT_IF_METHOD_FAILS(hr, ts.HelpFilesDir( strDir_HelpFiles, /*fExpand*/false, /*fMUI*/m_inst.m_fMUI ));
  255. __MPC_EXIT_IF_METHOD_FAILS(hr, ts.DatabaseDir ( strDir_Database ));
  256. __MPC_EXIT_IF_METHOD_FAILS(hr, ts.DatabaseFile( strFile_Database ));
  257. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_DATABASE , /*fRemove*/true , /*fRecreate*/true ));
  258. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_INDEX , /*fRemove*/true , /*fRecreate*/true ));
  259. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_SYSTEM , /*fRemove*/true , /*fRecreate*/true ));
  260. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_SYSTEM_OEM, /*fRemove*/true , /*fRecreate*/true ));
  261. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_VENDORS , /*fRemove*/true , /*fRecreate*/true ));
  262. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_HELPFILES , /*fRemove*/fAlsoHelpFiles, /*fRecreate*/true ));
  263. //
  264. // Change the ACL for system directories.
  265. //
  266. {
  267. CPCHSecurityDescriptorDirect sdd;
  268. MPC::wstring strGroupName;
  269. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::LocalizeString( IDS_HELPSVC_GROUPNAME, strGroupName ));
  270. __MPC_EXIT_IF_METHOD_FAILS(hr, sdd.Initialize());
  271. __MPC_EXIT_IF_METHOD_FAILS(hr, sdd.SetGroup( strGroupName.c_str() ));
  272. //
  273. // LOCAL SYSTEM, Admin, Admins : any access.
  274. // Everyone : read and execute.
  275. //
  276. //
  277. __MPC_EXIT_IF_METHOD_FAILS(hr, sdd.Add( (PSID)&sdd.s_SystemSid ,
  278. ACCESS_ALLOWED_ACE_TYPE ,
  279. OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE ,
  280. FILE_ALL_ACCESS ));
  281. __MPC_EXIT_IF_METHOD_FAILS(hr, sdd.Add( (PSID)&sdd.s_Alias_AdminsSid ,
  282. ACCESS_ALLOWED_ACE_TYPE ,
  283. OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE ,
  284. FILE_ALL_ACCESS ));
  285. __MPC_EXIT_IF_METHOD_FAILS(hr, sdd.Add( (PSID)&sdd.s_EveryoneSid ,
  286. ACCESS_ALLOWED_ACE_TYPE ,
  287. OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE ,
  288. FILE_GENERIC_READ | FILE_GENERIC_EXECUTE ));
  289. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, strDir_System ));
  290. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, strDir_System, HC_HELPSET_SUB_DATABASE ));
  291. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, strDir_System, HC_HELPSET_SUB_INDEX ));
  292. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, strDir_System, HC_HELPSET_SUB_SYSTEM ));
  293. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, strDir_System, HC_HELPSET_SUB_SYSTEM_OEM ));
  294. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, strDir_System, HC_HELPSET_SUB_VENDORS ));
  295. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, strDir_System, HC_HELPSET_SUB_HELPFILES ));
  296. }
  297. {
  298. bool fReload = false;
  299. __MPC_EXIT_IF_METHOD_FAILS(hr, m_inst.GetFileName( strFile_SetupImage ));
  300. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Init ( strFile_SetupImage.c_str() ));
  301. if(m_dwCRC)
  302. {
  303. DWORD dwCRC;
  304. if(FAILED(MPC::ComputeCRC( dwCRC, strFile_SetupImage.c_str() )) || m_dwCRC != dwCRC) fReload = true;
  305. }
  306. if(fReload == false)
  307. {
  308. if(FAILED(pkg.Load())) fReload = true;
  309. }
  310. //
  311. // If the package has been corrupted, try to restore from BINARIES.
  312. //
  313. if(fReload)
  314. {
  315. MPC::WStringList lst;
  316. MPC::WStringIter it;
  317. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::LocateDataArchive( HC_ROOT_HELPSVC_BINARIES, lst ));
  318. for(it = lst.begin(); it != lst.end(); it++)
  319. {
  320. if(SUCCEEDED(pkg.Init( it->c_str() )) &&
  321. SUCCEEDED(pkg.Load( )) )
  322. {
  323. if(pkg.GetData().m_ths == m_inst.m_ths)
  324. {
  325. __MPC_EXIT_IF_METHOD_FAILS(hr, m_inst.Import( it->c_str(), &m_dwCRC ));
  326. break;
  327. }
  328. }
  329. }
  330. if(it == lst.end())
  331. {
  332. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_FILE_NOT_FOUND);
  333. }
  334. }
  335. }
  336. ////////////////////////////////////////////////////////////////////////////////
  337. //
  338. // Phase Two: install files.
  339. //
  340. {
  341. static const Installer::PURPOSE c_allowedFull[] =
  342. {
  343. Installer::PURPOSE_DATABASE,
  344. Installer::PURPOSE_PACKAGE ,
  345. Installer::PURPOSE_UI ,
  346. Installer::PURPOSE_INVALID ,
  347. };
  348. static const Installer::PURPOSE c_allowedReinstall[] =
  349. {
  350. Installer::PURPOSE_DATABASE,
  351. ////Installer::PURPOSE_PACKAGE , Don't extract system packages on a reinstall.
  352. Installer::PURPOSE_UI ,
  353. Installer::PURPOSE_INVALID ,
  354. };
  355. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Install( fReinstall ? c_allowedReinstall : c_allowedFull, m_inst.m_fSystem ? NULL : strDir_System.c_str() ));
  356. }
  357. if(m_inst.m_fSystem || m_inst.m_fMUI)
  358. {
  359. if(store)
  360. {
  361. MPC::wstring strTmp;
  362. __MPC_EXIT_IF_METHOD_FAILS(hr, local_AddPackage( store, strTmp, strDir_Database, c_DB_NEWSGROUPS, m_inst.m_ths ));
  363. __MPC_EXIT_IF_METHOD_FAILS(hr, local_AddPackage( store, strTmp, strDir_Database, c_DB_PSS , m_inst.m_ths ));
  364. // No Remote Assistence on IA64
  365. #ifndef WIN64
  366. __MPC_EXIT_IF_METHOD_FAILS(hr, local_AddPackage( store, strTmp, strDir_Database, c_DB_RCBDY , m_inst.m_ths ));
  367. #endif
  368. // Only available on Beta releases.
  369. #if 0
  370. __MPC_EXIT_IF_METHOD_FAILS(hr, local_AddPackage( store, strTmp, strDir_Database, c_DB_BUGREPT , m_inst.m_ths ));
  371. #endif
  372. }
  373. }
  374. hr = S_OK;
  375. __HCP_FUNC_CLEANUP;
  376. __HCP_FUNC_EXIT(hr);
  377. }
  378. HRESULT Taxonomy::InstalledInstance::UninstallFiles( /*[in]*/ bool fAlsoHelpFiles )
  379. {
  380. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstance::UninstallFiles" );
  381. USES_CONVERSION;
  382. HRESULT hr;
  383. Taxonomy::Settings ts( m_inst.m_ths );
  384. MPC::wstring strDir_System;
  385. MPC::wstring strFile_Database;
  386. SearchEngine::Config cfg;
  387. __MPC_EXIT_IF_METHOD_FAILS(hr, ts.BaseDir ( strDir_System , /*fExpand*/false ));
  388. __MPC_EXIT_IF_METHOD_FAILS(hr, ts.DatabaseFile( strFile_Database ));
  389. __MPC_EXIT_IF_METHOD_FAILS(hr, JetBlue::SessionPool::s_GLOBAL->ReleaseDatabase( W2A( strFile_Database.c_str() ) ));
  390. __MPC_EXIT_IF_METHOD_FAILS(hr, CSAFReg:: s_GLOBAL->RemoveSKU ( m_inst.m_ths ));
  391. __MPC_EXIT_IF_METHOD_FAILS(hr, cfg . ResetSKU ( m_inst.m_ths ));
  392. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_DATABASE , /*fRemove*/true, /*fRecreate*/false ));
  393. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_INDEX , /*fRemove*/true, /*fRecreate*/false ));
  394. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_SYSTEM , /*fRemove*/true, /*fRecreate*/false ));
  395. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_SYSTEM_OEM, /*fRemove*/true, /*fRecreate*/false ));
  396. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_VENDORS , /*fRemove*/true, /*fRecreate*/false ));
  397. if(fAlsoHelpFiles)
  398. {
  399. if(!m_inst.m_fMUI)
  400. {
  401. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_HELPFILES, /*fRemove*/true, /*fRecreate*/false ));
  402. }
  403. if(!m_inst.m_fSystem)
  404. {
  405. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, NULL, /*fRemove*/true, /*fRecreate*/false ));
  406. }
  407. }
  408. hr = S_OK;
  409. __HCP_FUNC_CLEANUP;
  410. __HCP_FUNC_EXIT(hr);
  411. }
  412. ////////////////////////////////////////////////////////////////////////////////
  413. Taxonomy::LockingHandle::LockingHandle()
  414. {
  415. m_main = NULL; // InstalledInstanceStore* m_main;
  416. m_logPrevious = NULL; // Logger* m_logPrevious;
  417. }
  418. Taxonomy::LockingHandle::~LockingHandle()
  419. {
  420. Release();
  421. }
  422. void Taxonomy::LockingHandle::Attach( /*[in]*/ InstalledInstanceStore* main ,
  423. /*[in]*/ Logger* log )
  424. {
  425. Release();
  426. main->Lock();
  427. m_main = main;
  428. m_logPrevious = main->m_log;
  429. if(log) main->m_log = log;
  430. }
  431. void Taxonomy::LockingHandle::Release()
  432. {
  433. if(m_main)
  434. {
  435. m_main->m_log = m_logPrevious; m_logPrevious = NULL;
  436. m_main->Unlock(); m_main = NULL;
  437. }
  438. }
  439. ////////////////////////////////////////////////////////////////////////////////
  440. Taxonomy::InstalledInstanceStore::InstalledInstanceStore()
  441. {
  442. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::InstalledInstanceStore" );
  443. // InstanceList m_lstInstances;
  444. // PackageList m_lstPackages;
  445. // InstalledInstanceList m_lstSKUs;
  446. //
  447. //
  448. MPC::SubstituteEnvVariables( m_strStore = HC_HELPSVC_STORE_SKUS ); // MPC::wstring m_strStore;
  449. m_fLoaded = false; // bool m_fLoaded;
  450. m_fDirty = false; // bool m_fDirty;
  451. m_log = NULL; // Logger* m_log;
  452. //
  453. m_dwRecurse = 0; // DWORD m_dwRecurse;
  454. //
  455. m_fShutdown = false; // bool m_fShutdown;
  456. }
  457. Taxonomy::InstalledInstanceStore::~InstalledInstanceStore()
  458. {
  459. (void)EnsureInSync();
  460. }
  461. ////////////////////
  462. Taxonomy::InstalledInstanceStore* Taxonomy::InstalledInstanceStore::s_GLOBAL( NULL );
  463. HRESULT Taxonomy::InstalledInstanceStore::InitializeSystem()
  464. {
  465. if(s_GLOBAL == NULL)
  466. {
  467. s_GLOBAL = new Taxonomy::InstalledInstanceStore;
  468. }
  469. return s_GLOBAL ? S_OK : E_OUTOFMEMORY;
  470. }
  471. void Taxonomy::InstalledInstanceStore::FinalizeSystem()
  472. {
  473. if(s_GLOBAL)
  474. {
  475. delete s_GLOBAL; s_GLOBAL = NULL;
  476. }
  477. }
  478. ////////////////////////////////////////
  479. void Taxonomy::InstalledInstanceStore::Shutdown()
  480. {
  481. LockingHandle handle;
  482. m_fShutdown = true;
  483. if(SUCCEEDED(GrabControl( handle, NULL ))) // This will wait until the rest of the system has release the object.
  484. {
  485. (void)EnsureInSync();
  486. }
  487. }
  488. void Taxonomy::InstalledInstanceStore::Clean()
  489. {
  490. m_lstInstances.clear();
  491. m_lstPackages .clear();
  492. m_lstSKUs .clear();
  493. }
  494. HRESULT Taxonomy::InstalledInstanceStore::Load()
  495. {
  496. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::Load" );
  497. HRESULT hr;
  498. bool fSystemSet = false;
  499. if(FAILED(LoadFromDisk ( m_strStore.c_str() )) &&
  500. FAILED(LoadFromRegistry( )) )
  501. {
  502. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
  503. }
  504. for(InstalledInstanceIter it = m_lstSKUs.begin(); it != m_lstSKUs.end(); it++)
  505. {
  506. Taxonomy::Instance& data = it->m_inst;
  507. if(data.m_fSystem)
  508. {
  509. if(fSystemSet)
  510. {
  511. data.m_fSystem = false; // No other sku can be SYSTEM!!
  512. }
  513. else
  514. {
  515. __MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::Settings::SetMachineInfo( data ));
  516. fSystemSet = true;
  517. }
  518. }
  519. }
  520. hr = S_OK;
  521. __MPC_FUNC_CLEANUP;
  522. __MPC_FUNC_EXIT(hr);
  523. }
  524. HRESULT Taxonomy::InstalledInstanceStore::LoadFromDisk( /*[in]*/ LPCWSTR szFile )
  525. {
  526. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::LoadFromDisk" );
  527. HRESULT hr;
  528. CComPtr<MPC::FileStream> stream;
  529. Clean();
  530. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::SafeLoad ( szFile, stream ));
  531. __MPC_EXIT_IF_METHOD_FAILS(hr, LoadFromStream( stream ));
  532. __MPC_EXIT_IF_METHOD_FAILS(hr, local_CheckCRC( NULL, c_REG_CRC, stream ));
  533. hr = S_OK;
  534. __MPC_FUNC_CLEANUP;
  535. __MPC_FUNC_EXIT(hr);
  536. }
  537. HRESULT Taxonomy::InstalledInstanceStore::LoadFromRegistry()
  538. {
  539. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::LoadFromRegistry" );
  540. HRESULT hr;
  541. MPC::RegKey rkBase;
  542. CComPtr<IStream> stream;
  543. CComVariant v;
  544. bool fFound;
  545. Clean();
  546. __MPC_EXIT_IF_METHOD_FAILS(hr, local_OpenForRead( rkBase ));
  547. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.get_Value( v, fFound, c_REG_BACKUP ));
  548. if(!fFound)
  549. {
  550. __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
  551. }
  552. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertVariantToIStream( &v, &stream ));
  553. __MPC_EXIT_IF_METHOD_FAILS(hr, LoadFromStream ( stream ));
  554. __MPC_EXIT_IF_METHOD_FAILS(hr, local_CheckCRC( &rkBase, c_REG_CRC_BAK, stream ));
  555. hr = S_OK;
  556. __MPC_FUNC_CLEANUP;
  557. __MPC_FUNC_EXIT(hr);
  558. }
  559. HRESULT Taxonomy::InstalledInstanceStore::LoadFromStream( /*[in]*/ IStream* stream )
  560. {
  561. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::LoadFromStream" );
  562. HRESULT hr;
  563. MPC::Serializer_IStream streamGen ( stream );
  564. MPC::Serializer_Buffering streamGen2( streamGen );
  565. DWORD dwVer;
  566. __MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2 >> dwVer); if(dwVer != s_dwVersion) __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
  567. __MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2 >> m_lstInstances);
  568. __MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2 >> m_lstPackages );
  569. __MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2 >> m_lstSKUs );
  570. hr = S_OK;
  571. __HCP_FUNC_CLEANUP;
  572. __HCP_FUNC_EXIT(hr);
  573. }
  574. ////////////////////
  575. HRESULT Taxonomy::InstalledInstanceStore::Save()
  576. {
  577. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::Save" );
  578. HRESULT hr;
  579. __MPC_EXIT_IF_METHOD_FAILS(hr, SaveToDisk( m_strStore.c_str() ));
  580. //
  581. // Ignore failures on backup.
  582. //
  583. (void)SaveToRegistry();
  584. hr = S_OK;
  585. __MPC_FUNC_CLEANUP;
  586. __MPC_FUNC_EXIT(hr);
  587. }
  588. HRESULT Taxonomy::InstalledInstanceStore::SaveToDisk( /*[in]*/ LPCWSTR szFile )
  589. {
  590. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::SaveToDisk" );
  591. HRESULT hr;
  592. CComPtr<MPC::FileStream> stream;
  593. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::SafeSave_Init ( szFile, stream ));
  594. __MPC_EXIT_IF_METHOD_FAILS(hr, SaveToStream ( stream ));
  595. __MPC_EXIT_IF_METHOD_FAILS(hr, SVC::SafeSave_Finalize( szFile, stream ));
  596. if(SUCCEEDED(SVC::SafeLoad( szFile, stream )))
  597. {
  598. (void)local_CreateCRC( NULL, c_REG_CRC, stream );
  599. }
  600. hr = S_OK;
  601. __MPC_FUNC_CLEANUP;
  602. __MPC_FUNC_EXIT(hr);
  603. }
  604. HRESULT Taxonomy::InstalledInstanceStore::SaveToRegistry()
  605. {
  606. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::SaveToRegistry" );
  607. HRESULT hr;
  608. MPC::RegKey rkBase;
  609. CComPtr<IStream> stream;
  610. CComVariant v;
  611. __MPC_EXIT_IF_METHOD_FAILS(hr, local_OpenForWrite( rkBase ));
  612. __MPC_EXIT_IF_METHOD_FAILS(hr, ::CreateStreamOnHGlobal ( NULL, TRUE, &stream ));
  613. __MPC_EXIT_IF_METHOD_FAILS(hr, SaveToStream ( stream ));
  614. __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertIStreamToVariant( stream, v ));
  615. __MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.put_Value ( v, c_REG_BACKUP ));
  616. __MPC_EXIT_IF_METHOD_FAILS(hr, local_CreateCRC( &rkBase, c_REG_CRC_BAK, stream ));
  617. hr = S_OK;
  618. __MPC_FUNC_CLEANUP;
  619. __MPC_FUNC_EXIT(hr);
  620. }
  621. HRESULT Taxonomy::InstalledInstanceStore::SaveToStream( /*[in]*/ IStream* stream )
  622. {
  623. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::SaveToStream" );
  624. HRESULT hr;
  625. MPC::Serializer_IStream streamGen ( stream );
  626. MPC::Serializer_Buffering streamGen2( streamGen );
  627. __MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2 << s_dwVersion);
  628. __MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2 << m_lstInstances);
  629. __MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2 << m_lstPackages );
  630. __MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2 << m_lstSKUs );
  631. __MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2.Flush());
  632. hr = S_OK;
  633. __MPC_FUNC_CLEANUP;
  634. __MPC_FUNC_EXIT(hr);
  635. }
  636. ////////////////////
  637. HRESULT Taxonomy::InstalledInstanceStore::EnsureInSync()
  638. {
  639. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::EnsureInSync" );
  640. HRESULT hr;
  641. if(m_fLoaded == false)
  642. {
  643. m_fLoaded = true;
  644. if(FAILED(Load()))
  645. {
  646. Clean();
  647. }
  648. }
  649. if(m_fDirty == true)
  650. {
  651. m_fDirty = false;
  652. __MPC_EXIT_IF_METHOD_FAILS(hr, Save());
  653. }
  654. hr = S_OK;
  655. __MPC_FUNC_CLEANUP;
  656. __MPC_FUNC_EXIT(hr);
  657. }
  658. ////////////////////////////////////////////////////////////////////////////////
  659. HRESULT Taxonomy::InstalledInstanceStore::InUse_Lock( /*[in]*/ const Taxonomy::HelpSet& ths )
  660. {
  661. __HCP_BEGIN_PROPERTY_PUT( "Taxonomy::InstalledInstanceStore::InUse_Lock", hr );
  662. InstalledInstanceIter it;
  663. bool fFound;
  664. __MPC_EXIT_IF_METHOD_FAILS(hr, SKU_Find( ths, fFound, it ));
  665. if(fFound)
  666. {
  667. it->m_dwRef++;
  668. }
  669. __HCP_END_PROPERTY(hr);
  670. }
  671. HRESULT Taxonomy::InstalledInstanceStore::InUse_Unlock( /*[in]*/ const Taxonomy::HelpSet& ths )
  672. {
  673. __HCP_BEGIN_PROPERTY_PUT( "Taxonomy::InstalledInstanceStore::InUse_Unlock", hr );
  674. InstalledInstanceIter it;
  675. bool fFound;
  676. __MPC_EXIT_IF_METHOD_FAILS(hr, SKU_Find( ths, fFound, it ));
  677. if(fFound && it->m_dwRef)
  678. {
  679. it->m_dwRef--;
  680. }
  681. __HCP_END_PROPERTY(hr);
  682. }
  683. HRESULT Taxonomy::InstalledInstanceStore::GrabControl( /*[in]*/ LockingHandle& handle,
  684. /*[in]*/ Logger* log )
  685. {
  686. HRESULT hr;
  687. handle.Attach( this, log );
  688. if(FAILED(hr = EnsureInSync()))
  689. {
  690. handle.Release();
  691. }
  692. return hr;
  693. }
  694. ////////////////////////////////////////////////////////////////////////////////
  695. HRESULT Taxonomy::InstalledInstanceStore::Instance_GetList( /*[out]*/ InstanceIterConst& itBegin, /*[out]*/ InstanceIterConst& itEnd )
  696. {
  697. itBegin = m_lstInstances.begin();
  698. itEnd = m_lstInstances.end ();
  699. return S_OK;
  700. }
  701. HRESULT Taxonomy::InstalledInstanceStore::Package_GetList( /*[out]*/ PackageIterConst& itBegin, /*[out]*/ PackageIterConst& itEnd )
  702. {
  703. itBegin = m_lstPackages.begin();
  704. itEnd = m_lstPackages.end ();
  705. return S_OK;
  706. }
  707. HRESULT Taxonomy::InstalledInstanceStore::SKU_GetList( /*[out]*/ InstalledInstanceIterConst& itBegin, /*[out]*/ InstalledInstanceIterConst& itEnd )
  708. {
  709. itBegin = m_lstSKUs.begin();
  710. itEnd = m_lstSKUs.end ();
  711. return S_OK;
  712. }
  713. ////////////////////
  714. HRESULT Taxonomy::InstalledInstanceStore::Instance_Find( /*[in ]*/ const Taxonomy::HelpSet& ths ,
  715. /*[out]*/ bool& fFound ,
  716. /*[out]*/ InstanceIter& it )
  717. {
  718. fFound = false;
  719. for(it = m_lstInstances.begin(); it != m_lstInstances.end(); it++)
  720. {
  721. if(it->m_ths == ths)
  722. {
  723. fFound = true;
  724. break;
  725. }
  726. }
  727. return S_OK;
  728. }
  729. HRESULT Taxonomy::InstalledInstanceStore::Instance_Add( /*[in ]*/ LPCWSTR szFile ,
  730. /*[in ]*/ const Instance& data ,
  731. /*[out]*/ bool& fFound ,
  732. /*[out]*/ InstanceIter& it )
  733. {
  734. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::Instance_Add" );
  735. HRESULT hr;
  736. __MPC_EXIT_IF_METHOD_FAILS(hr, Instance_Find( data.m_ths, fFound, it ));
  737. if(!fFound)
  738. {
  739. it = m_lstInstances.insert( m_lstInstances.end(), data ); it->SetTimeStamp();
  740. __MPC_EXIT_IF_METHOD_FAILS(hr, it->Import( szFile, NULL ));
  741. m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  742. }
  743. hr = S_OK;
  744. __HCP_FUNC_CLEANUP;
  745. __HCP_FUNC_EXIT(hr);
  746. }
  747. HRESULT Taxonomy::InstalledInstanceStore::Instance_Remove( /*[in]*/ InstanceIter& it )
  748. {
  749. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::Instance_Remove" );
  750. HRESULT hr;
  751. MPC::wstring strFileDst;
  752. bool fFound;
  753. //
  754. // Uninstall SKU.
  755. //
  756. {
  757. InstalledInstanceIter itSKU;
  758. __MPC_EXIT_IF_METHOD_FAILS(hr, SKU_Find( it->m_ths, fFound, itSKU ));
  759. if(fFound)
  760. {
  761. __MPC_EXIT_IF_METHOD_FAILS(hr, SKU_Remove( itSKU ));
  762. }
  763. }
  764. //
  765. // Remove any built-in package from this instance.
  766. //
  767. {
  768. Logger logTmp;
  769. Logger* log = (m_log ? m_log : &logTmp);
  770. PackageIter itPackage;
  771. for(itPackage = m_lstPackages.begin(); itPackage != m_lstPackages.end(); )
  772. {
  773. PackageIter itPackage2 = itPackage++; // Copy iterator to protect against deletion.
  774. Package& pkg = *itPackage2;
  775. if(pkg.m_fBuiltin && it->Match( pkg ))
  776. {
  777. (void)pkg.Remove( *log );
  778. m_lstPackages.erase( itPackage2 );
  779. m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  780. }
  781. }
  782. }
  783. __MPC_EXIT_IF_METHOD_FAILS(hr, it->Remove());
  784. m_lstInstances.erase( it );
  785. m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  786. hr = S_OK;
  787. __HCP_FUNC_CLEANUP;
  788. __HCP_FUNC_EXIT(hr);
  789. }
  790. ////////////////////////////////////////////////////////////////////////////////
  791. HRESULT Taxonomy::InstalledInstanceStore::Package_Find( /*[in ]*/ const Package& pkg ,
  792. /*[out]*/ bool& fFound ,
  793. /*[out]*/ PackageIter& it )
  794. {
  795. fFound = false;
  796. for(it = m_lstPackages.begin(); it != m_lstPackages.end(); it++)
  797. {
  798. if(it->Compare( pkg ) == 0)
  799. {
  800. fFound = true;
  801. break;
  802. }
  803. }
  804. return S_OK;
  805. }
  806. HRESULT Taxonomy::InstalledInstanceStore::Package_Add( /*[in ]*/ LPCWSTR szFile ,
  807. /*[in ]*/ MPC::Impersonation* imp ,
  808. /*[in ]*/ const Taxonomy::HelpSet* ths ,
  809. /*[in ]*/ bool fInsertAtTop ,
  810. /*[out]*/ bool& fFound ,
  811. /*[out]*/ PackageIter& it )
  812. {
  813. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::Package_Add" );
  814. HRESULT hr;
  815. Logger logTmp;
  816. Logger* log = (m_log ? m_log : &logTmp);
  817. Package pkg;
  818. long lSequence = 1;
  819. if(ths)
  820. {
  821. WCHAR rgLCID[64];
  822. pkg.m_fBuiltin = true;
  823. pkg.m_strSKU = ths->GetSKU ();
  824. pkg.m_strLanguage = _ltow( ths->GetLanguage(), rgLCID, 10 );
  825. }
  826. //
  827. // Found a suitable sequence number.
  828. //
  829. for(it = m_lstPackages.begin(); it != m_lstPackages.end(); it++)
  830. {
  831. if(lSequence <= it->m_lSequence) lSequence = it->m_lSequence + 1;
  832. }
  833. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Import ( *log, szFile, lSequence, imp ));
  834. __MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Authenticate( *log ));
  835. __MPC_EXIT_IF_METHOD_FAILS(hr, Package_Find( pkg, fFound, it ));
  836. if(fFound)
  837. {
  838. if(it->m_dwCRC != pkg.m_dwCRC) // CRC differs, different package?
  839. {
  840. __MPC_EXIT_IF_METHOD_FAILS(hr, Package_Remove( it ));
  841. fFound = false;
  842. }
  843. }
  844. if(fFound)
  845. {
  846. pkg.m_fTemporary = true; // Delete the copy...
  847. }
  848. else
  849. {
  850. if (fInsertAtTop)
  851. {
  852. it = m_lstPackages.insert( m_lstPackages.begin(), pkg );
  853. }
  854. else
  855. {
  856. it = m_lstPackages.insert( m_lstPackages.end(), pkg );
  857. }
  858. m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  859. }
  860. //
  861. // Check if have an installed SKU that actually matches this package.
  862. //
  863. {
  864. InstalledInstanceIter itSKU;
  865. for(itSKU = m_lstSKUs.begin(); itSKU != m_lstSKUs.end(); itSKU++)
  866. {
  867. InstalledInstance& sku = *itSKU;
  868. if(sku.m_inst.Match( *it ))
  869. {
  870. break;
  871. }
  872. }
  873. if(itSKU == m_lstSKUs.end())
  874. {
  875. log->WriteLog( -1, L"\nWARNING: the package cannot be applied to any of the installed SKUs\n\n" );
  876. }
  877. }
  878. hr = S_OK;
  879. __HCP_FUNC_CLEANUP;
  880. __HCP_FUNC_EXIT(hr);
  881. }
  882. HRESULT Taxonomy::InstalledInstanceStore::Package_Remove( /*[in]*/ PackageIter& it )
  883. {
  884. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::Package_Remove" );
  885. HRESULT hr;
  886. Logger logTmp;
  887. Logger* log = (m_log ? m_log : &logTmp);
  888. bool fFound;
  889. __MPC_EXIT_IF_METHOD_FAILS(hr, it->Remove( *log ));
  890. __MPC_EXIT_IF_METHOD_FAILS(hr, State_InvalidatePackage( it->m_lSequence ));
  891. m_lstPackages.erase( it );
  892. m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  893. hr = S_OK;
  894. __HCP_FUNC_CLEANUP;
  895. __HCP_FUNC_EXIT(hr);
  896. }
  897. ////////////////////
  898. HRESULT Taxonomy::InstalledInstanceStore::SKU_Find( /*[in ]*/ const Taxonomy::HelpSet& ths ,
  899. /*[out]*/ bool& fFound ,
  900. /*[out]*/ InstalledInstanceIter& it )
  901. {
  902. fFound = false;
  903. for(it = m_lstSKUs.begin(); it != m_lstSKUs.end(); it++)
  904. {
  905. if(it->m_inst.m_ths == ths)
  906. {
  907. fFound = true;
  908. break;
  909. }
  910. }
  911. return S_OK;
  912. }
  913. HRESULT Taxonomy::InstalledInstanceStore::SKU_Add( /*[in ]*/ const Instance& data ,
  914. /*[out]*/ bool& fFound ,
  915. /*[out]*/ InstalledInstanceIter& it )
  916. {
  917. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::SKU_Add" );
  918. HRESULT hr;
  919. __MPC_EXIT_IF_METHOD_FAILS(hr, SKU_Find( data.m_ths, fFound, it ));
  920. if(!fFound)
  921. {
  922. it = m_lstSKUs.insert( m_lstSKUs.end() );
  923. it->m_inst = data; it->m_inst.SetTimeStamp();
  924. m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  925. __MPC_EXIT_IF_METHOD_FAILS(hr, it->InstallFiles( /*fAlsoHelpFiles*/true, this ));
  926. //
  927. // Propagate change to the offline cache.
  928. //
  929. if(SUCCEEDED(OfflineCache::Root::s_GLOBAL->Import( it->m_inst )))
  930. {
  931. (void)OfflineCache::Root::s_GLOBAL->Flush();
  932. }
  933. }
  934. hr = S_OK;
  935. __HCP_FUNC_CLEANUP;
  936. __HCP_FUNC_EXIT(hr);
  937. }
  938. HRESULT Taxonomy::InstalledInstanceStore::SKU_Updated( /*[in]*/ InstalledInstanceIter& it )
  939. {
  940. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::SKU_Updated" );
  941. HRESULT hr;
  942. bool fFound;
  943. it->m_inst.SetTimeStamp();
  944. m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  945. //
  946. // Propagate change to the offline cache.
  947. //
  948. {
  949. if(SUCCEEDED(OfflineCache::Root::s_GLOBAL->Import( it->m_inst )))
  950. {
  951. (void)OfflineCache::Root::s_GLOBAL->Flush();
  952. }
  953. }
  954. hr = S_OK;
  955. __HCP_FUNC_CLEANUP;
  956. __HCP_FUNC_EXIT(hr);
  957. }
  958. HRESULT Taxonomy::InstalledInstanceStore::SKU_Remove( /*[in]*/ InstalledInstanceIter& it )
  959. {
  960. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::SKU_Remove" );
  961. HRESULT hr;
  962. if(m_dwRef)
  963. {
  964. __MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_BUSY);
  965. }
  966. __MPC_EXIT_IF_METHOD_FAILS(hr, it->UninstallFiles( /*fAlsoHelpFiles*/true ));
  967. //
  968. // Propagate change to the offline cache.
  969. //
  970. {
  971. if(SUCCEEDED(OfflineCache::Root::s_GLOBAL->Remove( it->m_inst.m_ths )))
  972. {
  973. (void)OfflineCache::Root::s_GLOBAL->Flush();
  974. }
  975. }
  976. m_lstSKUs.erase( it );
  977. m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  978. hr = S_OK;
  979. __HCP_FUNC_CLEANUP;
  980. __HCP_FUNC_EXIT(hr);
  981. }
  982. ////////////////////////////////////////////////////////////////////////////////
  983. HRESULT Taxonomy::InstalledInstanceStore::State_InvalidateSKU( /*[in]*/ const Taxonomy::HelpSet& ths, /*[in]*/ bool fAlsoDatabase )
  984. {
  985. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::State_InvalidateSKU" );
  986. HRESULT hr;
  987. InstalledInstanceIter itSKU;
  988. for(itSKU = m_lstSKUs.begin(); itSKU != m_lstSKUs.end(); itSKU++)
  989. {
  990. InstalledInstance& sku = *itSKU;
  991. if(sku.m_inst.m_ths == ths)
  992. {
  993. ProcessedPackageIter itProcessedPackage;
  994. if(fAlsoDatabase) sku.m_fInvalidated = true;
  995. for(itProcessedPackage = sku.m_lst.begin(); itProcessedPackage != sku.m_lst.end(); itProcessedPackage++)
  996. {
  997. itProcessedPackage->m_fProcessed = false;
  998. }
  999. }
  1000. }
  1001. m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  1002. hr = S_OK;
  1003. __HCP_FUNC_CLEANUP;
  1004. __HCP_FUNC_EXIT(hr);
  1005. }
  1006. HRESULT Taxonomy::InstalledInstanceStore::State_InvalidatePackage( /*[in]*/ long lSequence )
  1007. {
  1008. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::State_InvalidatePackage" );
  1009. HRESULT hr;
  1010. InstalledInstanceIter itSKU;
  1011. for(itSKU = m_lstSKUs.begin(); itSKU != m_lstSKUs.end(); itSKU++)
  1012. {
  1013. InstalledInstance& sku = *itSKU;
  1014. ProcessedPackageIter itProcessedPackage;
  1015. for(itProcessedPackage = sku.m_lst.begin(); itProcessedPackage != sku.m_lst.end(); itProcessedPackage++)
  1016. {
  1017. if(itProcessedPackage->m_lSequence == lSequence) break;
  1018. }
  1019. if(itProcessedPackage != sku.m_lst.end())
  1020. {
  1021. sku.m_lst.erase( itProcessedPackage );
  1022. sku.m_fInvalidated = true;
  1023. for(itProcessedPackage = sku.m_lst.begin(); itProcessedPackage != sku.m_lst.end(); itProcessedPackage++)
  1024. {
  1025. itProcessedPackage->m_fProcessed = false;
  1026. }
  1027. m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  1028. }
  1029. }
  1030. hr = S_OK;
  1031. __HCP_FUNC_CLEANUP;
  1032. __HCP_FUNC_EXIT(hr);
  1033. }
  1034. ////////////////////////////////////////////////////////////////////////////////
  1035. HRESULT Taxonomy::InstalledInstanceStore::MakeReady( /*[in]*/ InstallationEngine& engine, /*[in]*/ bool fNoOp, /*[in]*/ bool& fWorkToProcess )
  1036. {
  1037. __HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::MakeReady" );
  1038. HRESULT hr;
  1039. int iRepeat = 0;
  1040. bool fRepeat = true;
  1041. bool fRecurse = false;
  1042. //
  1043. // Already processing the list of packages.
  1044. //
  1045. if(m_dwRecurse)
  1046. {
  1047. __MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
  1048. }
  1049. fRecurse = true;
  1050. m_dwRecurse++;
  1051. __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  1052. fWorkToProcess = false;
  1053. while(fRepeat && IsShutdown() == false)
  1054. {
  1055. InstalledInstanceIter itSKU;
  1056. // If we are rebuilding too many times, abort the process, to protect against endless looping.
  1057. if(iRepeat++ >= 5) break;
  1058. fRepeat = false;
  1059. for(itSKU = m_lstSKUs.begin(); itSKU != m_lstSKUs.end() && IsShutdown() == false; itSKU++)
  1060. {
  1061. InstalledInstance& sku = *itSKU;
  1062. bool fProcessedSomething = false;
  1063. engine.ResetModificationFlags();
  1064. if(sku.m_fInvalidated)
  1065. {
  1066. if(fNoOp)
  1067. {
  1068. fWorkToProcess = true;
  1069. }
  1070. else
  1071. {
  1072. if(m_log)
  1073. {
  1074. m_log->WriteLog( -1, L"\nRestoring original database for %s (Language: %d)\n\n", sku.m_inst.m_ths.GetSKU(), sku.m_inst.m_ths.GetLanguage() );
  1075. }
  1076. __MPC_EXIT_IF_METHOD_FAILS(hr, sku.UninstallFiles( /*fAlsoHelpFiles*/false ));
  1077. __MPC_EXIT_IF_METHOD_FAILS(hr, sku.InstallFiles ( /*fAlsoHelpFiles*/false, NULL ));
  1078. sku.m_fInvalidated = false;
  1079. sku.m_fRecreateCache = true;
  1080. sku.m_fCreateIndex = true;
  1081. sku.m_fCreateIndexForce = true;
  1082. m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  1083. fRepeat = true;
  1084. }
  1085. }
  1086. else
  1087. {
  1088. PackageIter itPackage;
  1089. for(itPackage = m_lstPackages.begin(); itPackage != m_lstPackages.end(); itPackage++)
  1090. {
  1091. Package& pkg = *itPackage;
  1092. if(sku.m_inst.Match( pkg ))
  1093. {
  1094. ProcessedPackageIter itProcessedPackage;
  1095. for(itProcessedPackage = sku.m_lst.begin(); itProcessedPackage != sku.m_lst.end(); itProcessedPackage++)
  1096. {
  1097. if(itProcessedPackage->m_lSequence == pkg.m_lSequence) break;
  1098. }
  1099. if(itProcessedPackage == sku.m_lst.end())
  1100. {
  1101. itProcessedPackage = sku.m_lst.insert( sku.m_lst.end() );
  1102. itProcessedPackage->m_lSequence = pkg.m_lSequence;
  1103. m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  1104. }
  1105. {
  1106. ProcessedPackage& ppkg = *itProcessedPackage;
  1107. if(ppkg.m_fDisabled ) continue;
  1108. if(ppkg.m_fProcessed) continue;
  1109. if(fNoOp)
  1110. {
  1111. fWorkToProcess = true;
  1112. }
  1113. else
  1114. {
  1115. hr = engine.ProcessPackage( sku, pkg );
  1116. if(FAILED(hr))
  1117. {
  1118. if(IsShutdown())
  1119. {
  1120. State_InvalidateSKU( sku.m_inst.m_ths, /*fAlsoDatabase*/true );
  1121. __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
  1122. }
  1123. if(sku.m_fInvalidated)
  1124. {
  1125. ; // Already invalidated.
  1126. }
  1127. else
  1128. {
  1129. ppkg.m_fDisabled = true;
  1130. sku.m_fInvalidated = true;
  1131. iRepeat = 0; // Reset repeat counter on a bad package.
  1132. for(itProcessedPackage = sku.m_lst.begin(); itProcessedPackage != sku.m_lst.end(); itProcessedPackage++)
  1133. {
  1134. itProcessedPackage->m_fProcessed = false;
  1135. }
  1136. }
  1137. fRepeat = true;
  1138. }
  1139. else
  1140. {
  1141. if(engine.m_fTaxonomyModified)
  1142. {
  1143. //
  1144. // Update the timestamp.
  1145. //
  1146. sku.m_inst.SetTimeStamp();
  1147. }
  1148. ppkg.m_fProcessed = true;
  1149. fProcessedSomething = true;
  1150. }
  1151. m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  1152. }
  1153. }
  1154. }
  1155. if(fRepeat) break;
  1156. }
  1157. }
  1158. if(!sku.m_fInvalidated)
  1159. {
  1160. if(engine.m_fTaxonomyModified)
  1161. {
  1162. sku.m_fRecreateCache = true;
  1163. m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  1164. }
  1165. if(fProcessedSomething)
  1166. {
  1167. sku.m_fCreateIndex = true;
  1168. sku.m_fCreateIndexForce = engine.m_fRecreateIndex;
  1169. m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  1170. }
  1171. }
  1172. if(fRepeat) break;
  1173. ////////////////////
  1174. if(sku.m_fCreateIndex)
  1175. {
  1176. if(FAILED(hr = engine.RecreateIndex( sku, sku.m_fCreateIndexForce )))
  1177. {
  1178. ;
  1179. }
  1180. sku.m_fCreateIndex = false;
  1181. sku.m_fCreateIndexForce = false;
  1182. m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  1183. }
  1184. if(sku.m_fRecreateCache)
  1185. {
  1186. if(SUCCEEDED(Taxonomy::Cache::s_GLOBAL->Erase ( sku.m_inst.m_ths )) &&
  1187. SUCCEEDED(Taxonomy::Cache::s_GLOBAL->PrePopulate( sku.m_inst.m_ths )) )
  1188. {
  1189. ;
  1190. }
  1191. //
  1192. // Propagate settings to the offline cache.
  1193. //
  1194. if(SUCCEEDED(OfflineCache::Root::s_GLOBAL->SetReady( true )))
  1195. {
  1196. (void)OfflineCache::Root::s_GLOBAL->Flush();
  1197. }
  1198. sku.m_fRecreateCache = false;
  1199. m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
  1200. }
  1201. }
  1202. }
  1203. hr = S_OK;
  1204. __HCP_FUNC_CLEANUP;
  1205. if(fRecurse) m_dwRecurse--;
  1206. __HCP_FUNC_EXIT(hr);
  1207. }