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
1697 lines
49 KiB
/******************************************************************************
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
InstalledDatabaseStore.cpp
|
|
|
|
|
|
Abstract:
|
|
This file contains the implementation of the Taxonomy::InstalledInstanceStore class,
|
|
which controls the set of Topic Databases installed on the machine.
|
|
|
|
Revision History:
|
|
Davide Massarenti (Dmassare) 05/01/2000
|
|
created
|
|
|
|
******************************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include <SAFLIB.h>
|
|
|
|
#include <SEConfig.h>
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static const WCHAR c_DB_BUGREPT [] = L"bugrept.cab";
|
|
static const WCHAR c_DB_RCBDY [] = L"rcBuddy.cab";
|
|
static const WCHAR c_DB_PSS [] = L"pss.cab";
|
|
static const WCHAR c_DB_NEWSGROUPS[] = L"newsgroups.cab";
|
|
|
|
static const WCHAR c_REG_BACKUP [] = L"PackageStore";
|
|
static const WCHAR c_REG_CRC [] = L"CRC_Disk";
|
|
static const WCHAR c_REG_CRC_BAK[] = L"CRC_Registry";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
LPCWSTR const Taxonomy::Strings::s_file_PackageDescription = L"package_description.xml";
|
|
|
|
LPCWSTR const Taxonomy::Strings::s_tag_root_PackageDescription = L"HELPCENTERPACKAGE";
|
|
|
|
LPCWSTR const Taxonomy::Strings::s_tag_root_HHT = L"METADATA";
|
|
|
|
LPCWSTR const Taxonomy::Strings::s_tag_root_SAF = L"SAFConfig";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void local_GetFileForCRC( /*[out]*/ MPC::wstring& strDest ,
|
|
/*[in]*/ LPCWSTR szValue )
|
|
{
|
|
strDest = HC_ROOT_HELPSVC_PKGSTORE L"\\";
|
|
strDest += szValue;
|
|
|
|
MPC::SubstituteEnvVariables( strDest );
|
|
}
|
|
|
|
static HRESULT local_OpenForRead( /*[in/out]*/ MPC::RegKey& rkBase )
|
|
{
|
|
__HCP_FUNC_ENTRY( "local_OpenForRead" );
|
|
|
|
HRESULT hr;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.SetRoot( HKEY_LOCAL_MACHINE ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.Attach ( HC_REGISTRY_HELPSVC L"\\Backup" ));
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
static HRESULT local_OpenForWrite( /*[in/out]*/ MPC::RegKey& rkBase )
|
|
{
|
|
__HCP_FUNC_ENTRY( "local_OpenForWrite" );
|
|
|
|
HRESULT hr;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.SetRoot( HKEY_LOCAL_MACHINE, KEY_ALL_ACCESS ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.Attach ( HC_REGISTRY_HELPSVC L"\\Backup" ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.Create ( ));
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
static HRESULT local_CreateCRC( /*[in]*/ MPC::RegKey* rkBase ,
|
|
/*[in]*/ LPCWSTR szValue ,
|
|
/*[in]*/ IStream* stream )
|
|
{
|
|
__HCP_FUNC_ENTRY( "local_CreateCRC" );
|
|
|
|
HRESULT hr;
|
|
LARGE_INTEGER li = { 0, 0 };
|
|
DWORD dwCRC; MPC::InitCRC( dwCRC );
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, stream->Seek( li, STREAM_SEEK_SET, NULL ));
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ComputeCRC( dwCRC, stream ));
|
|
|
|
if(rkBase)
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, rkBase->Write( dwCRC, szValue ));
|
|
}
|
|
else
|
|
{
|
|
MPC::wstring strDest;
|
|
CComPtr<MPC::FileStream> stream2;
|
|
ULONG cb;
|
|
|
|
local_GetFileForCRC( strDest, szValue );
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::SafeSave_Init( strDest.c_str(), stream2 ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, stream2->Write( &dwCRC, sizeof(dwCRC), &cb )); stream2.Release();
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::SafeSave_Finalize( strDest.c_str(), stream2 ));
|
|
}
|
|
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
static HRESULT local_CheckCRC( /*[in]*/ MPC::RegKey* rkBase ,
|
|
/*[in]*/ LPCWSTR szValue ,
|
|
/*[in]*/ IStream* stream )
|
|
{
|
|
__HCP_FUNC_ENTRY( "local_CheckCRC" );
|
|
|
|
HRESULT hr;
|
|
DWORD dwCRC;
|
|
bool fFound = false;
|
|
|
|
|
|
if(rkBase)
|
|
{
|
|
if(FAILED(rkBase->Read( dwCRC, fFound, szValue ))) fFound = false;
|
|
}
|
|
else
|
|
{
|
|
MPC::wstring strDest;
|
|
CComPtr<MPC::FileStream> stream2;
|
|
|
|
local_GetFileForCRC( strDest, szValue );
|
|
|
|
if(SUCCEEDED(SVC::SafeLoad( strDest.c_str(), stream2 )))
|
|
{
|
|
ULONG cb;
|
|
|
|
if(SUCCEEDED(stream2->Read( &dwCRC, sizeof(dwCRC), &cb )) && cb == sizeof(dwCRC))
|
|
{
|
|
fFound = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(fFound)
|
|
{
|
|
|
|
LARGE_INTEGER li = { 0, 0 };
|
|
DWORD dwCRC2; MPC::InitCRC( dwCRC2 );
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, stream->Seek( li, STREAM_SEEK_SET, NULL ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ComputeCRC( dwCRC2, stream ));
|
|
|
|
if(dwCRC != dwCRC2)
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////
|
|
|
|
static HRESULT local_AddPackage( /*[in ]*/ Taxonomy::InstalledInstanceStore* store ,
|
|
/*[in/out]*/ MPC::wstring& strTmp ,
|
|
/*[in ]*/ const MPC::wstring& strDir ,
|
|
/*[in ]*/ LPCWSTR szExtra ,
|
|
/*[in ]*/ const Taxonomy::HelpSet& ths )
|
|
{
|
|
__HCP_FUNC_ENTRY( "local_AddPackage" );
|
|
|
|
HRESULT hr;
|
|
Taxonomy::PackageIter it;
|
|
bool fFound;
|
|
|
|
|
|
strTmp = strDir; strTmp.append( szExtra );
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, store->Package_Add( strTmp.c_str(), NULL, &ths, /*fInsertAtTop*/true, fFound, it ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::DeleteFile ( strTmp ));
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT Taxonomy::Instance::InitializeFromBase( /*[in]*/ const InstanceBase& base, /*[in]*/ bool fSystem, /*[in]*/ bool fMUI )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::Instance::InitializeFromBase" );
|
|
|
|
HRESULT hr;
|
|
Taxonomy::Settings ts( base.m_ths );
|
|
|
|
((InstanceBase&)*this) = base;
|
|
|
|
m_fSystem = fSystem;
|
|
m_fMUI = fMUI;
|
|
|
|
|
|
if(fSystem)
|
|
{
|
|
//
|
|
// Set machine-wide defaults.
|
|
//
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::HelpSet::SetMachineInfo ( base ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, OfflineCache::Root::s_GLOBAL->SetMachineInfo( *this ));
|
|
}
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ts.BaseDir ( m_strSystem , /*fExpand*/false ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ts.HelpFilesDir( m_strHelpFiles, /*fExpand*/false, /*fMUI*/m_fMUI ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ts.DatabaseDir ( m_strDatabaseDir ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ts.DatabaseFile( m_strDatabaseFile ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ts.IndexFile ( m_strIndexFile ));
|
|
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT Taxonomy::Instance::Import( /*[in]*/ LPCWSTR szFile, /*[in/out]*/ DWORD* pdwCRC )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::Instance::Import" );
|
|
|
|
HRESULT hr;
|
|
MPC::wstring strFileDst;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, GetFileName ( strFileDst ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CopyFile( szFile, strFileDst.c_str() ));
|
|
|
|
::SetFileAttributesW( strFileDst.c_str(), FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM );
|
|
|
|
if(pdwCRC)
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ComputeCRC( *pdwCRC, strFileDst.c_str() ));
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT Taxonomy::Instance::Remove()
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::Instance::Remove" );
|
|
|
|
HRESULT hr;
|
|
MPC::wstring strFileDst;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, GetFileName ( strFileDst ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::DeleteFile( strFileDst ));
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Taxonomy::InstalledInstance::InstalledInstance()
|
|
{
|
|
// Instance m_inst;
|
|
// ProcessedPackageList m_lst;
|
|
m_fInvalidated = false; // bool m_fInvalidated;
|
|
m_fRecreateCache = true; // bool m_fRecreateCache;
|
|
m_fCreateIndex = true; // bool m_fCreateIndex;
|
|
m_fCreateIndexForce = true; // bool m_fCreateIndexForce;
|
|
m_dwCRC = 0; // DWORD m_dwCRC;
|
|
//
|
|
m_dwRef = 0; // DWORD m_dwRef; // VOLATILE
|
|
}
|
|
|
|
HRESULT Taxonomy::operator>>( /*[in]*/ MPC::Serializer& stream, /*[out]*/ Taxonomy::InstalledInstance& val )
|
|
{
|
|
HRESULT hr;
|
|
|
|
if(SUCCEEDED(hr = (stream >> val.m_inst )) &&
|
|
SUCCEEDED(hr = (stream >> val.m_lst )) &&
|
|
SUCCEEDED(hr = (stream >> val.m_fInvalidated )) &&
|
|
SUCCEEDED(hr = (stream >> val.m_fRecreateCache )) &&
|
|
SUCCEEDED(hr = (stream >> val.m_fCreateIndex )) &&
|
|
SUCCEEDED(hr = (stream >> val.m_fCreateIndexForce)) &&
|
|
SUCCEEDED(hr = (stream >> val.m_dwCRC )) )
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT Taxonomy::operator<<( /*[in]*/ MPC::Serializer& stream, /*[in] */ const Taxonomy::InstalledInstance& val )
|
|
{
|
|
HRESULT hr;
|
|
|
|
if(SUCCEEDED(hr = (stream << val.m_inst )) &&
|
|
SUCCEEDED(hr = (stream << val.m_lst )) &&
|
|
SUCCEEDED(hr = (stream << val.m_fInvalidated )) &&
|
|
SUCCEEDED(hr = (stream << val.m_fRecreateCache )) &&
|
|
SUCCEEDED(hr = (stream << val.m_fCreateIndex )) &&
|
|
SUCCEEDED(hr = (stream << val.m_fCreateIndexForce)) &&
|
|
SUCCEEDED(hr = (stream << val.m_dwCRC )) )
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstance::InstallFiles( /*[in]*/ bool fAlsoHelpFiles ,
|
|
/*[in]*/ InstalledInstanceStore* store )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstance::InstallFiles" );
|
|
|
|
HRESULT hr;
|
|
Taxonomy::Settings ts( m_inst.m_ths );
|
|
Installer::Package pkg;
|
|
MPC::wstring strDir_System;
|
|
MPC::wstring strDir_HelpFiles;
|
|
MPC::wstring strDir_Database;
|
|
MPC::wstring strFile_Database;
|
|
MPC::wstring strFile_SetupImage;
|
|
bool fReinstall = (store == NULL);
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ts.BaseDir ( strDir_System , /*fExpand*/false ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ts.HelpFilesDir( strDir_HelpFiles, /*fExpand*/false, /*fMUI*/m_inst.m_fMUI ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ts.DatabaseDir ( strDir_Database ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ts.DatabaseFile( strFile_Database ));
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_DATABASE , /*fRemove*/true , /*fRecreate*/true ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_INDEX , /*fRemove*/true , /*fRecreate*/true ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_SYSTEM , /*fRemove*/true , /*fRecreate*/true ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_SYSTEM_OEM, /*fRemove*/true , /*fRecreate*/true ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_VENDORS , /*fRemove*/true , /*fRecreate*/true ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_HELPFILES , /*fRemove*/fAlsoHelpFiles, /*fRecreate*/true ));
|
|
|
|
//
|
|
// Change the ACL for system directories.
|
|
//
|
|
{
|
|
CPCHSecurityDescriptorDirect sdd;
|
|
MPC::wstring strGroupName;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::LocalizeString( IDS_HELPSVC_GROUPNAME, strGroupName ));
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, sdd.Initialize());
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, sdd.SetGroup( strGroupName.c_str() ));
|
|
|
|
|
|
//
|
|
// LOCAL SYSTEM, Admin, Admins : any access.
|
|
// Everyone : read and execute.
|
|
//
|
|
//
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, sdd.Add( (PSID)&sdd.s_SystemSid ,
|
|
ACCESS_ALLOWED_ACE_TYPE ,
|
|
OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE ,
|
|
FILE_ALL_ACCESS ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, sdd.Add( (PSID)&sdd.s_Alias_AdminsSid ,
|
|
ACCESS_ALLOWED_ACE_TYPE ,
|
|
OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE ,
|
|
FILE_ALL_ACCESS ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, sdd.Add( (PSID)&sdd.s_EveryoneSid ,
|
|
ACCESS_ALLOWED_ACE_TYPE ,
|
|
OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE ,
|
|
FILE_GENERIC_READ | FILE_GENERIC_EXECUTE ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, strDir_System ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, strDir_System, HC_HELPSET_SUB_DATABASE ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, strDir_System, HC_HELPSET_SUB_INDEX ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, strDir_System, HC_HELPSET_SUB_SYSTEM ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, strDir_System, HC_HELPSET_SUB_SYSTEM_OEM ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, strDir_System, HC_HELPSET_SUB_VENDORS ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, strDir_System, HC_HELPSET_SUB_HELPFILES ));
|
|
}
|
|
|
|
|
|
{
|
|
bool fReload = false;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, m_inst.GetFileName( strFile_SetupImage ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Init ( strFile_SetupImage.c_str() ));
|
|
|
|
if(m_dwCRC)
|
|
{
|
|
DWORD dwCRC;
|
|
|
|
if(FAILED(MPC::ComputeCRC( dwCRC, strFile_SetupImage.c_str() )) || m_dwCRC != dwCRC) fReload = true;
|
|
}
|
|
|
|
if(fReload == false)
|
|
{
|
|
if(FAILED(pkg.Load())) fReload = true;
|
|
}
|
|
|
|
//
|
|
// If the package has been corrupted, try to restore from BINARIES.
|
|
//
|
|
if(fReload)
|
|
{
|
|
MPC::WStringList lst;
|
|
MPC::WStringIter it;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::LocateDataArchive( HC_ROOT_HELPSVC_BINARIES, lst ));
|
|
|
|
for(it = lst.begin(); it != lst.end(); it++)
|
|
{
|
|
if(SUCCEEDED(pkg.Init( it->c_str() )) &&
|
|
SUCCEEDED(pkg.Load( )) )
|
|
{
|
|
if(pkg.GetData().m_ths == m_inst.m_ths)
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, m_inst.Import( it->c_str(), &m_dwCRC ));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if(it == lst.end())
|
|
{
|
|
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_FILE_NOT_FOUND);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Phase Two: install files.
|
|
//
|
|
{
|
|
static const Installer::PURPOSE c_allowedFull[] =
|
|
{
|
|
Installer::PURPOSE_DATABASE,
|
|
Installer::PURPOSE_PACKAGE ,
|
|
Installer::PURPOSE_UI ,
|
|
Installer::PURPOSE_INVALID ,
|
|
};
|
|
|
|
static const Installer::PURPOSE c_allowedReinstall[] =
|
|
{
|
|
Installer::PURPOSE_DATABASE,
|
|
////Installer::PURPOSE_PACKAGE , Don't extract system packages on a reinstall.
|
|
Installer::PURPOSE_UI ,
|
|
Installer::PURPOSE_INVALID ,
|
|
};
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Install( fReinstall ? c_allowedReinstall : c_allowedFull, m_inst.m_fSystem ? NULL : strDir_System.c_str() ));
|
|
}
|
|
|
|
if(m_inst.m_fSystem || m_inst.m_fMUI)
|
|
{
|
|
if(store)
|
|
{
|
|
MPC::wstring strTmp;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, local_AddPackage( store, strTmp, strDir_Database, c_DB_NEWSGROUPS, m_inst.m_ths ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, local_AddPackage( store, strTmp, strDir_Database, c_DB_PSS , m_inst.m_ths ));
|
|
// No Remote Assistence on IA64
|
|
#ifndef WIN64
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, local_AddPackage( store, strTmp, strDir_Database, c_DB_RCBDY , m_inst.m_ths ));
|
|
#endif
|
|
// Only available on Beta releases.
|
|
#if 0
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, local_AddPackage( store, strTmp, strDir_Database, c_DB_BUGREPT , m_inst.m_ths ));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstance::UninstallFiles( /*[in]*/ bool fAlsoHelpFiles )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstance::UninstallFiles" );
|
|
|
|
USES_CONVERSION;
|
|
|
|
HRESULT hr;
|
|
Taxonomy::Settings ts( m_inst.m_ths );
|
|
MPC::wstring strDir_System;
|
|
MPC::wstring strFile_Database;
|
|
SearchEngine::Config cfg;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ts.BaseDir ( strDir_System , /*fExpand*/false ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ts.DatabaseFile( strFile_Database ));
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, JetBlue::SessionPool::s_GLOBAL->ReleaseDatabase( W2A( strFile_Database.c_str() ) ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, CSAFReg:: s_GLOBAL->RemoveSKU ( m_inst.m_ths ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, cfg . ResetSKU ( m_inst.m_ths ));
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_DATABASE , /*fRemove*/true, /*fRecreate*/false ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_INDEX , /*fRemove*/true, /*fRecreate*/false ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_SYSTEM , /*fRemove*/true, /*fRecreate*/false ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_SYSTEM_OEM, /*fRemove*/true, /*fRecreate*/false ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_VENDORS , /*fRemove*/true, /*fRecreate*/false ));
|
|
|
|
if(fAlsoHelpFiles)
|
|
{
|
|
if(!m_inst.m_fMUI)
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, HC_HELPSET_SUB_HELPFILES, /*fRemove*/true, /*fRecreate*/false ));
|
|
}
|
|
|
|
if(!m_inst.m_fSystem)
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( strDir_System, NULL, /*fRemove*/true, /*fRecreate*/false ));
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Taxonomy::LockingHandle::LockingHandle()
|
|
{
|
|
m_main = NULL; // InstalledInstanceStore* m_main;
|
|
m_logPrevious = NULL; // Logger* m_logPrevious;
|
|
}
|
|
|
|
Taxonomy::LockingHandle::~LockingHandle()
|
|
{
|
|
Release();
|
|
}
|
|
|
|
void Taxonomy::LockingHandle::Attach( /*[in]*/ InstalledInstanceStore* main ,
|
|
/*[in]*/ Logger* log )
|
|
{
|
|
Release();
|
|
|
|
main->Lock();
|
|
|
|
m_main = main;
|
|
m_logPrevious = main->m_log;
|
|
|
|
if(log) main->m_log = log;
|
|
}
|
|
|
|
void Taxonomy::LockingHandle::Release()
|
|
{
|
|
if(m_main)
|
|
{
|
|
m_main->m_log = m_logPrevious; m_logPrevious = NULL;
|
|
|
|
m_main->Unlock(); m_main = NULL;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
Taxonomy::InstalledInstanceStore::InstalledInstanceStore()
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::InstalledInstanceStore" );
|
|
|
|
// InstanceList m_lstInstances;
|
|
// PackageList m_lstPackages;
|
|
// InstalledInstanceList m_lstSKUs;
|
|
//
|
|
//
|
|
MPC::SubstituteEnvVariables( m_strStore = HC_HELPSVC_STORE_SKUS ); // MPC::wstring m_strStore;
|
|
m_fLoaded = false; // bool m_fLoaded;
|
|
m_fDirty = false; // bool m_fDirty;
|
|
m_log = NULL; // Logger* m_log;
|
|
//
|
|
m_dwRecurse = 0; // DWORD m_dwRecurse;
|
|
//
|
|
m_fShutdown = false; // bool m_fShutdown;
|
|
}
|
|
|
|
Taxonomy::InstalledInstanceStore::~InstalledInstanceStore()
|
|
{
|
|
(void)EnsureInSync();
|
|
}
|
|
|
|
////////////////////
|
|
|
|
Taxonomy::InstalledInstanceStore* Taxonomy::InstalledInstanceStore::s_GLOBAL( NULL );
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::InitializeSystem()
|
|
{
|
|
if(s_GLOBAL == NULL)
|
|
{
|
|
s_GLOBAL = new Taxonomy::InstalledInstanceStore;
|
|
}
|
|
|
|
return s_GLOBAL ? S_OK : E_OUTOFMEMORY;
|
|
}
|
|
|
|
void Taxonomy::InstalledInstanceStore::FinalizeSystem()
|
|
{
|
|
if(s_GLOBAL)
|
|
{
|
|
delete s_GLOBAL; s_GLOBAL = NULL;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
|
|
void Taxonomy::InstalledInstanceStore::Shutdown()
|
|
{
|
|
LockingHandle handle;
|
|
|
|
m_fShutdown = true;
|
|
|
|
if(SUCCEEDED(GrabControl( handle, NULL ))) // This will wait until the rest of the system has release the object.
|
|
{
|
|
(void)EnsureInSync();
|
|
}
|
|
}
|
|
|
|
void Taxonomy::InstalledInstanceStore::Clean()
|
|
{
|
|
m_lstInstances.clear();
|
|
m_lstPackages .clear();
|
|
m_lstSKUs .clear();
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::Load()
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::Load" );
|
|
|
|
HRESULT hr;
|
|
bool fSystemSet = false;
|
|
|
|
if(FAILED(LoadFromDisk ( m_strStore.c_str() )) &&
|
|
FAILED(LoadFromRegistry( )) )
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
|
|
}
|
|
|
|
for(InstalledInstanceIter it = m_lstSKUs.begin(); it != m_lstSKUs.end(); it++)
|
|
{
|
|
Taxonomy::Instance& data = it->m_inst;
|
|
|
|
if(data.m_fSystem)
|
|
{
|
|
if(fSystemSet)
|
|
{
|
|
data.m_fSystem = false; // No other sku can be SYSTEM!!
|
|
}
|
|
else
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::Settings::SetMachineInfo( data ));
|
|
fSystemSet = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::LoadFromDisk( /*[in]*/ LPCWSTR szFile )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::LoadFromDisk" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<MPC::FileStream> stream;
|
|
|
|
|
|
Clean();
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::SafeLoad ( szFile, stream ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, LoadFromStream( stream ));
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, local_CheckCRC( NULL, c_REG_CRC, stream ));
|
|
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::LoadFromRegistry()
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::LoadFromRegistry" );
|
|
|
|
HRESULT hr;
|
|
MPC::RegKey rkBase;
|
|
CComPtr<IStream> stream;
|
|
CComVariant v;
|
|
bool fFound;
|
|
|
|
|
|
Clean();
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, local_OpenForRead( rkBase ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.get_Value( v, fFound, c_REG_BACKUP ));
|
|
if(!fFound)
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
|
|
}
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertVariantToIStream( &v, &stream ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, LoadFromStream ( stream ));
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, local_CheckCRC( &rkBase, c_REG_CRC_BAK, stream ));
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::LoadFromStream( /*[in]*/ IStream* stream )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::LoadFromStream" );
|
|
|
|
HRESULT hr;
|
|
MPC::Serializer_IStream streamGen ( stream );
|
|
MPC::Serializer_Buffering streamGen2( streamGen );
|
|
DWORD dwVer;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2 >> dwVer); if(dwVer != s_dwVersion) __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2 >> m_lstInstances);
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2 >> m_lstPackages );
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2 >> m_lstSKUs );
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::Save()
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::Save" );
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SaveToDisk( m_strStore.c_str() ));
|
|
|
|
//
|
|
// Ignore failures on backup.
|
|
//
|
|
(void)SaveToRegistry();
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::SaveToDisk( /*[in]*/ LPCWSTR szFile )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::SaveToDisk" );
|
|
|
|
HRESULT hr;
|
|
CComPtr<MPC::FileStream> stream;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::SafeSave_Init ( szFile, stream ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SaveToStream ( stream ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::SafeSave_Finalize( szFile, stream ));
|
|
|
|
if(SUCCEEDED(SVC::SafeLoad( szFile, stream )))
|
|
{
|
|
(void)local_CreateCRC( NULL, c_REG_CRC, stream );
|
|
}
|
|
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::SaveToRegistry()
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::SaveToRegistry" );
|
|
|
|
HRESULT hr;
|
|
MPC::RegKey rkBase;
|
|
CComPtr<IStream> stream;
|
|
CComVariant v;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, local_OpenForWrite( rkBase ));
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, ::CreateStreamOnHGlobal ( NULL, TRUE, &stream ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SaveToStream ( stream ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertIStreamToVariant( stream, v ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, rkBase.put_Value ( v, c_REG_BACKUP ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, local_CreateCRC( &rkBase, c_REG_CRC_BAK, stream ));
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::SaveToStream( /*[in]*/ IStream* stream )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::SaveToStream" );
|
|
|
|
HRESULT hr;
|
|
MPC::Serializer_IStream streamGen ( stream );
|
|
MPC::Serializer_Buffering streamGen2( streamGen );
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2 << s_dwVersion);
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2 << m_lstInstances);
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2 << m_lstPackages );
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2 << m_lstSKUs );
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, streamGen2.Flush());
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::EnsureInSync()
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::EnsureInSync" );
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
if(m_fLoaded == false)
|
|
{
|
|
m_fLoaded = true;
|
|
|
|
if(FAILED(Load()))
|
|
{
|
|
Clean();
|
|
}
|
|
}
|
|
|
|
if(m_fDirty == true)
|
|
{
|
|
m_fDirty = false;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, Save());
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__MPC_FUNC_CLEANUP;
|
|
|
|
__MPC_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::InUse_Lock( /*[in]*/ const Taxonomy::HelpSet& ths )
|
|
{
|
|
__HCP_BEGIN_PROPERTY_PUT( "Taxonomy::InstalledInstanceStore::InUse_Lock", hr );
|
|
|
|
InstalledInstanceIter it;
|
|
bool fFound;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SKU_Find( ths, fFound, it ));
|
|
if(fFound)
|
|
{
|
|
it->m_dwRef++;
|
|
}
|
|
|
|
__HCP_END_PROPERTY(hr);
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::InUse_Unlock( /*[in]*/ const Taxonomy::HelpSet& ths )
|
|
{
|
|
__HCP_BEGIN_PROPERTY_PUT( "Taxonomy::InstalledInstanceStore::InUse_Unlock", hr );
|
|
|
|
InstalledInstanceIter it;
|
|
bool fFound;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SKU_Find( ths, fFound, it ));
|
|
if(fFound && it->m_dwRef)
|
|
{
|
|
it->m_dwRef--;
|
|
}
|
|
|
|
__HCP_END_PROPERTY(hr);
|
|
}
|
|
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::GrabControl( /*[in]*/ LockingHandle& handle,
|
|
/*[in]*/ Logger* log )
|
|
{
|
|
HRESULT hr;
|
|
|
|
handle.Attach( this, log );
|
|
|
|
if(FAILED(hr = EnsureInSync()))
|
|
{
|
|
handle.Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::Instance_GetList( /*[out]*/ InstanceIterConst& itBegin, /*[out]*/ InstanceIterConst& itEnd )
|
|
{
|
|
itBegin = m_lstInstances.begin();
|
|
itEnd = m_lstInstances.end ();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::Package_GetList( /*[out]*/ PackageIterConst& itBegin, /*[out]*/ PackageIterConst& itEnd )
|
|
{
|
|
itBegin = m_lstPackages.begin();
|
|
itEnd = m_lstPackages.end ();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::SKU_GetList( /*[out]*/ InstalledInstanceIterConst& itBegin, /*[out]*/ InstalledInstanceIterConst& itEnd )
|
|
{
|
|
itBegin = m_lstSKUs.begin();
|
|
itEnd = m_lstSKUs.end ();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
////////////////////
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::Instance_Find( /*[in ]*/ const Taxonomy::HelpSet& ths ,
|
|
/*[out]*/ bool& fFound ,
|
|
/*[out]*/ InstanceIter& it )
|
|
{
|
|
fFound = false;
|
|
|
|
|
|
for(it = m_lstInstances.begin(); it != m_lstInstances.end(); it++)
|
|
{
|
|
if(it->m_ths == ths)
|
|
{
|
|
fFound = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::Instance_Add( /*[in ]*/ LPCWSTR szFile ,
|
|
/*[in ]*/ const Instance& data ,
|
|
/*[out]*/ bool& fFound ,
|
|
/*[out]*/ InstanceIter& it )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::Instance_Add" );
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, Instance_Find( data.m_ths, fFound, it ));
|
|
if(!fFound)
|
|
{
|
|
it = m_lstInstances.insert( m_lstInstances.end(), data ); it->SetTimeStamp();
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, it->Import( szFile, NULL ));
|
|
|
|
m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::Instance_Remove( /*[in]*/ InstanceIter& it )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::Instance_Remove" );
|
|
|
|
HRESULT hr;
|
|
MPC::wstring strFileDst;
|
|
bool fFound;
|
|
|
|
|
|
//
|
|
// Uninstall SKU.
|
|
//
|
|
{
|
|
InstalledInstanceIter itSKU;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SKU_Find( it->m_ths, fFound, itSKU ));
|
|
if(fFound)
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SKU_Remove( itSKU ));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Remove any built-in package from this instance.
|
|
//
|
|
{
|
|
Logger logTmp;
|
|
Logger* log = (m_log ? m_log : &logTmp);
|
|
PackageIter itPackage;
|
|
|
|
for(itPackage = m_lstPackages.begin(); itPackage != m_lstPackages.end(); )
|
|
{
|
|
PackageIter itPackage2 = itPackage++; // Copy iterator to protect against deletion.
|
|
Package& pkg = *itPackage2;
|
|
|
|
if(pkg.m_fBuiltin && it->Match( pkg ))
|
|
{
|
|
(void)pkg.Remove( *log );
|
|
|
|
m_lstPackages.erase( itPackage2 );
|
|
|
|
m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, it->Remove());
|
|
|
|
|
|
m_lstInstances.erase( it );
|
|
|
|
|
|
m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::Package_Find( /*[in ]*/ const Package& pkg ,
|
|
/*[out]*/ bool& fFound ,
|
|
/*[out]*/ PackageIter& it )
|
|
{
|
|
fFound = false;
|
|
|
|
|
|
for(it = m_lstPackages.begin(); it != m_lstPackages.end(); it++)
|
|
{
|
|
if(it->Compare( pkg ) == 0)
|
|
{
|
|
fFound = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::Package_Add( /*[in ]*/ LPCWSTR szFile ,
|
|
/*[in ]*/ MPC::Impersonation* imp ,
|
|
/*[in ]*/ const Taxonomy::HelpSet* ths ,
|
|
/*[in ]*/ bool fInsertAtTop ,
|
|
/*[out]*/ bool& fFound ,
|
|
/*[out]*/ PackageIter& it )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::Package_Add" );
|
|
|
|
HRESULT hr;
|
|
Logger logTmp;
|
|
Logger* log = (m_log ? m_log : &logTmp);
|
|
Package pkg;
|
|
long lSequence = 1;
|
|
|
|
|
|
if(ths)
|
|
{
|
|
WCHAR rgLCID[64];
|
|
|
|
pkg.m_fBuiltin = true;
|
|
pkg.m_strSKU = ths->GetSKU ();
|
|
pkg.m_strLanguage = _ltow( ths->GetLanguage(), rgLCID, 10 );
|
|
}
|
|
|
|
//
|
|
// Found a suitable sequence number.
|
|
//
|
|
for(it = m_lstPackages.begin(); it != m_lstPackages.end(); it++)
|
|
{
|
|
if(lSequence <= it->m_lSequence) lSequence = it->m_lSequence + 1;
|
|
}
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Import ( *log, szFile, lSequence, imp ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Authenticate( *log ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, Package_Find( pkg, fFound, it ));
|
|
if(fFound)
|
|
{
|
|
if(it->m_dwCRC != pkg.m_dwCRC) // CRC differs, different package?
|
|
{
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, Package_Remove( it ));
|
|
|
|
fFound = false;
|
|
}
|
|
}
|
|
|
|
if(fFound)
|
|
{
|
|
pkg.m_fTemporary = true; // Delete the copy...
|
|
}
|
|
else
|
|
{
|
|
if (fInsertAtTop)
|
|
{
|
|
it = m_lstPackages.insert( m_lstPackages.begin(), pkg );
|
|
}
|
|
else
|
|
{
|
|
it = m_lstPackages.insert( m_lstPackages.end(), pkg );
|
|
}
|
|
|
|
m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
|
|
}
|
|
|
|
//
|
|
// Check if have an installed SKU that actually matches this package.
|
|
//
|
|
{
|
|
InstalledInstanceIter itSKU;
|
|
|
|
for(itSKU = m_lstSKUs.begin(); itSKU != m_lstSKUs.end(); itSKU++)
|
|
{
|
|
InstalledInstance& sku = *itSKU;
|
|
|
|
if(sku.m_inst.Match( *it ))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if(itSKU == m_lstSKUs.end())
|
|
{
|
|
log->WriteLog( -1, L"\nWARNING: the package cannot be applied to any of the installed SKUs\n\n" );
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::Package_Remove( /*[in]*/ PackageIter& it )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::Package_Remove" );
|
|
|
|
HRESULT hr;
|
|
Logger logTmp;
|
|
Logger* log = (m_log ? m_log : &logTmp);
|
|
bool fFound;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, it->Remove( *log ));
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, State_InvalidatePackage( it->m_lSequence ));
|
|
|
|
m_lstPackages.erase( it );
|
|
m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::SKU_Find( /*[in ]*/ const Taxonomy::HelpSet& ths ,
|
|
/*[out]*/ bool& fFound ,
|
|
/*[out]*/ InstalledInstanceIter& it )
|
|
{
|
|
fFound = false;
|
|
|
|
|
|
for(it = m_lstSKUs.begin(); it != m_lstSKUs.end(); it++)
|
|
{
|
|
if(it->m_inst.m_ths == ths)
|
|
{
|
|
fFound = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::SKU_Add( /*[in ]*/ const Instance& data ,
|
|
/*[out]*/ bool& fFound ,
|
|
/*[out]*/ InstalledInstanceIter& it )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::SKU_Add" );
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, SKU_Find( data.m_ths, fFound, it ));
|
|
if(!fFound)
|
|
{
|
|
it = m_lstSKUs.insert( m_lstSKUs.end() );
|
|
|
|
it->m_inst = data; it->m_inst.SetTimeStamp();
|
|
|
|
m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, it->InstallFiles( /*fAlsoHelpFiles*/true, this ));
|
|
|
|
//
|
|
// Propagate change to the offline cache.
|
|
//
|
|
if(SUCCEEDED(OfflineCache::Root::s_GLOBAL->Import( it->m_inst )))
|
|
{
|
|
(void)OfflineCache::Root::s_GLOBAL->Flush();
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::SKU_Updated( /*[in]*/ InstalledInstanceIter& it )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::SKU_Updated" );
|
|
|
|
HRESULT hr;
|
|
bool fFound;
|
|
|
|
|
|
it->m_inst.SetTimeStamp();
|
|
m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
|
|
|
|
|
|
//
|
|
// Propagate change to the offline cache.
|
|
//
|
|
{
|
|
if(SUCCEEDED(OfflineCache::Root::s_GLOBAL->Import( it->m_inst )))
|
|
{
|
|
(void)OfflineCache::Root::s_GLOBAL->Flush();
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::SKU_Remove( /*[in]*/ InstalledInstanceIter& it )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::SKU_Remove" );
|
|
|
|
HRESULT hr;
|
|
|
|
|
|
if(m_dwRef)
|
|
{
|
|
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_BUSY);
|
|
}
|
|
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, it->UninstallFiles( /*fAlsoHelpFiles*/true ));
|
|
|
|
|
|
//
|
|
// Propagate change to the offline cache.
|
|
//
|
|
{
|
|
if(SUCCEEDED(OfflineCache::Root::s_GLOBAL->Remove( it->m_inst.m_ths )))
|
|
{
|
|
(void)OfflineCache::Root::s_GLOBAL->Flush();
|
|
}
|
|
}
|
|
|
|
m_lstSKUs.erase( it );
|
|
m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::State_InvalidateSKU( /*[in]*/ const Taxonomy::HelpSet& ths, /*[in]*/ bool fAlsoDatabase )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::State_InvalidateSKU" );
|
|
|
|
HRESULT hr;
|
|
InstalledInstanceIter itSKU;
|
|
|
|
|
|
for(itSKU = m_lstSKUs.begin(); itSKU != m_lstSKUs.end(); itSKU++)
|
|
{
|
|
InstalledInstance& sku = *itSKU;
|
|
|
|
if(sku.m_inst.m_ths == ths)
|
|
{
|
|
ProcessedPackageIter itProcessedPackage;
|
|
|
|
if(fAlsoDatabase) sku.m_fInvalidated = true;
|
|
|
|
for(itProcessedPackage = sku.m_lst.begin(); itProcessedPackage != sku.m_lst.end(); itProcessedPackage++)
|
|
{
|
|
itProcessedPackage->m_fProcessed = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::State_InvalidatePackage( /*[in]*/ long lSequence )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::State_InvalidatePackage" );
|
|
|
|
HRESULT hr;
|
|
InstalledInstanceIter itSKU;
|
|
|
|
|
|
for(itSKU = m_lstSKUs.begin(); itSKU != m_lstSKUs.end(); itSKU++)
|
|
{
|
|
InstalledInstance& sku = *itSKU;
|
|
ProcessedPackageIter itProcessedPackage;
|
|
|
|
for(itProcessedPackage = sku.m_lst.begin(); itProcessedPackage != sku.m_lst.end(); itProcessedPackage++)
|
|
{
|
|
if(itProcessedPackage->m_lSequence == lSequence) break;
|
|
}
|
|
|
|
if(itProcessedPackage != sku.m_lst.end())
|
|
{
|
|
sku.m_lst.erase( itProcessedPackage );
|
|
sku.m_fInvalidated = true;
|
|
|
|
for(itProcessedPackage = sku.m_lst.begin(); itProcessedPackage != sku.m_lst.end(); itProcessedPackage++)
|
|
{
|
|
itProcessedPackage->m_fProcessed = false;
|
|
}
|
|
|
|
m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT Taxonomy::InstalledInstanceStore::MakeReady( /*[in]*/ InstallationEngine& engine, /*[in]*/ bool fNoOp, /*[in]*/ bool& fWorkToProcess )
|
|
{
|
|
__HCP_FUNC_ENTRY( "Taxonomy::InstalledInstanceStore::MakeReady" );
|
|
|
|
HRESULT hr;
|
|
int iRepeat = 0;
|
|
bool fRepeat = true;
|
|
bool fRecurse = false;
|
|
|
|
//
|
|
// Already processing the list of packages.
|
|
//
|
|
if(m_dwRecurse)
|
|
{
|
|
__MPC_SET_ERROR_AND_EXIT(hr, S_FALSE);
|
|
}
|
|
|
|
fRecurse = true;
|
|
m_dwRecurse++;
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
|
|
|
|
fWorkToProcess = false;
|
|
|
|
while(fRepeat && IsShutdown() == false)
|
|
{
|
|
InstalledInstanceIter itSKU;
|
|
|
|
// If we are rebuilding too many times, abort the process, to protect against endless looping.
|
|
if(iRepeat++ >= 5) break;
|
|
|
|
fRepeat = false;
|
|
|
|
for(itSKU = m_lstSKUs.begin(); itSKU != m_lstSKUs.end() && IsShutdown() == false; itSKU++)
|
|
{
|
|
InstalledInstance& sku = *itSKU;
|
|
bool fProcessedSomething = false;
|
|
|
|
engine.ResetModificationFlags();
|
|
|
|
if(sku.m_fInvalidated)
|
|
{
|
|
if(fNoOp)
|
|
{
|
|
fWorkToProcess = true;
|
|
}
|
|
else
|
|
{
|
|
if(m_log)
|
|
{
|
|
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() );
|
|
}
|
|
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, sku.UninstallFiles( /*fAlsoHelpFiles*/false ));
|
|
__MPC_EXIT_IF_METHOD_FAILS(hr, sku.InstallFiles ( /*fAlsoHelpFiles*/false, NULL ));
|
|
|
|
sku.m_fInvalidated = false;
|
|
sku.m_fRecreateCache = true;
|
|
sku.m_fCreateIndex = true;
|
|
sku.m_fCreateIndexForce = true;
|
|
m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
|
|
|
|
fRepeat = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PackageIter itPackage;
|
|
|
|
for(itPackage = m_lstPackages.begin(); itPackage != m_lstPackages.end(); itPackage++)
|
|
{
|
|
Package& pkg = *itPackage;
|
|
|
|
if(sku.m_inst.Match( pkg ))
|
|
{
|
|
ProcessedPackageIter itProcessedPackage;
|
|
|
|
for(itProcessedPackage = sku.m_lst.begin(); itProcessedPackage != sku.m_lst.end(); itProcessedPackage++)
|
|
{
|
|
if(itProcessedPackage->m_lSequence == pkg.m_lSequence) break;
|
|
}
|
|
if(itProcessedPackage == sku.m_lst.end())
|
|
{
|
|
itProcessedPackage = sku.m_lst.insert( sku.m_lst.end() );
|
|
|
|
itProcessedPackage->m_lSequence = pkg.m_lSequence;
|
|
|
|
m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
|
|
}
|
|
|
|
{
|
|
ProcessedPackage& ppkg = *itProcessedPackage;
|
|
|
|
if(ppkg.m_fDisabled ) continue;
|
|
if(ppkg.m_fProcessed) continue;
|
|
|
|
if(fNoOp)
|
|
{
|
|
fWorkToProcess = true;
|
|
}
|
|
else
|
|
{
|
|
hr = engine.ProcessPackage( sku, pkg );
|
|
if(FAILED(hr))
|
|
{
|
|
if(IsShutdown())
|
|
{
|
|
State_InvalidateSKU( sku.m_inst.m_ths, /*fAlsoDatabase*/true );
|
|
|
|
__MPC_SET_ERROR_AND_EXIT(hr, S_OK);
|
|
}
|
|
|
|
if(sku.m_fInvalidated)
|
|
{
|
|
; // Already invalidated.
|
|
}
|
|
else
|
|
{
|
|
ppkg.m_fDisabled = true;
|
|
|
|
sku.m_fInvalidated = true;
|
|
iRepeat = 0; // Reset repeat counter on a bad package.
|
|
|
|
for(itProcessedPackage = sku.m_lst.begin(); itProcessedPackage != sku.m_lst.end(); itProcessedPackage++)
|
|
{
|
|
itProcessedPackage->m_fProcessed = false;
|
|
}
|
|
}
|
|
|
|
fRepeat = true;
|
|
}
|
|
else
|
|
{
|
|
if(engine.m_fTaxonomyModified)
|
|
{
|
|
//
|
|
// Update the timestamp.
|
|
//
|
|
sku.m_inst.SetTimeStamp();
|
|
}
|
|
|
|
ppkg.m_fProcessed = true;
|
|
fProcessedSomething = true;
|
|
}
|
|
|
|
m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
|
|
}
|
|
}
|
|
}
|
|
|
|
if(fRepeat) break;
|
|
}
|
|
}
|
|
|
|
if(!sku.m_fInvalidated)
|
|
{
|
|
if(engine.m_fTaxonomyModified)
|
|
{
|
|
sku.m_fRecreateCache = true;
|
|
|
|
m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
|
|
}
|
|
|
|
if(fProcessedSomething)
|
|
{
|
|
sku.m_fCreateIndex = true;
|
|
sku.m_fCreateIndexForce = engine.m_fRecreateIndex;
|
|
|
|
m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
|
|
}
|
|
}
|
|
|
|
if(fRepeat) break;
|
|
|
|
////////////////////
|
|
|
|
if(sku.m_fCreateIndex)
|
|
{
|
|
if(FAILED(hr = engine.RecreateIndex( sku, sku.m_fCreateIndexForce )))
|
|
{
|
|
;
|
|
}
|
|
|
|
sku.m_fCreateIndex = false;
|
|
sku.m_fCreateIndexForce = false;
|
|
|
|
m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
|
|
}
|
|
|
|
if(sku.m_fRecreateCache)
|
|
{
|
|
if(SUCCEEDED(Taxonomy::Cache::s_GLOBAL->Erase ( sku.m_inst.m_ths )) &&
|
|
SUCCEEDED(Taxonomy::Cache::s_GLOBAL->PrePopulate( sku.m_inst.m_ths )) )
|
|
{
|
|
;
|
|
}
|
|
|
|
//
|
|
// Propagate settings to the offline cache.
|
|
//
|
|
if(SUCCEEDED(OfflineCache::Root::s_GLOBAL->SetReady( true )))
|
|
{
|
|
(void)OfflineCache::Root::s_GLOBAL->Flush();
|
|
}
|
|
|
|
sku.m_fRecreateCache = false;
|
|
|
|
m_fDirty = true; __MPC_EXIT_IF_METHOD_FAILS(hr, EnsureInSync());
|
|
}
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
|
|
|
|
__HCP_FUNC_CLEANUP;
|
|
|
|
if(fRecurse) m_dwRecurse--;
|
|
|
|
__HCP_FUNC_EXIT(hr);
|
|
}
|