windows-nt/Source/XPSP1/NT/admin/pchealth/helpctr/service/hcupdate/pkgdesc.cpp
2020-09-26 16:20:57 +08:00

1061 lines
34 KiB
C++

/********************************************************************
Copyright (c) 1999 Microsoft Corporation
Module Name:
pkgdesc.cpp
Abstract:
Functions related to package description file processing
Revision History:
Ghim-Sim Chua (gschua) 07/07/99
- created
********************************************************************/
#include "stdafx.h"
////////////////////////////////////////////////////////////////////////////////
const LPCWSTR HCUpdate::Engine::s_ActionText[] = { L"ADD", L"DELETE" };
////////////////////////////////////////////////////////////////////////////////
long HCUpdate::Engine::CountNodes( /*[in]*/ IXMLDOMNodeList* poNodeList )
{
long lCount = 0;
if(poNodeList)
{
(void)poNodeList->get_length( &lCount );
}
return lCount;
}
////////////////////////////////////////////////////////////////////////////////
void HCUpdate::Engine::DeleteTempFile( /*[in/out]*/ MPC::wstring& szFile )
{
if(FAILED(MPC::RemoveTemporaryFile( szFile )))
{
WriteLog( HRESULT_FROM_WIN32(ERROR_CAN_NOT_COMPLETE), L"Error cannot delete temporary file" );
}
}
HRESULT HCUpdate::Engine::PrepareTempFile( /*[in/out]*/ MPC::wstring& szFile )
{
DeleteTempFile( szFile );
return MPC::GetTemporaryFileName( szFile );
}
HRESULT HCUpdate::Engine::LookupAction( /*[in] */ LPCWSTR szAction ,
/*[out]*/ Action& id )
{
if(szAction)
{
if(_wcsicmp( szAction, L"ADD" ) == 0)
{
id = ACTION_ADD; return S_OK;
}
if(_wcsicmp( szAction, L"DEL" ) == 0)
{
id = ACTION_DELETE; return S_OK;
}
}
return WriteLog( HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION), L"Error Unknown action used to install trusted content" );
}
HRESULT HCUpdate::Engine::LookupBoolean( /*[in] */ LPCWSTR szString ,
/*[out]*/ bool& fVal ,
/*[in] */ bool fDefault )
{
if(szString[0] == 0)
{
fVal = fDefault; return S_OK;
}
if(_wcsicmp( szString, L"TRUE" ) == 0 ||
_wcsicmp( szString, L"1" ) == 0 ||
_wcsicmp( szString, L"ON" ) == 0 )
{
fVal = true; return S_OK;
}
if(_wcsicmp( szString, L"FALSE" ) == 0 ||
_wcsicmp( szString, L"0" ) == 0 ||
_wcsicmp( szString, L"OFF" ) == 0 )
{
fVal = false; return S_OK;
}
fVal = false; return S_OK;
}
HRESULT HCUpdate::Engine::LookupNavModel( /*[in] */ LPCWSTR szString ,
/*[out]*/ long& lVal ,
/*[in] */ long lDefault )
{
if(_wcsicmp( szString, L"DEFAULT" ) == 0) { lVal = QR_DEFAULT; return S_OK; }
if(_wcsicmp( szString, L"DESKTOP" ) == 0) { lVal = QR_DESKTOP; return S_OK; }
if(_wcsicmp( szString, L"SERVER" ) == 0) { lVal = QR_SERVER ; return S_OK; }
lVal = lDefault; return S_OK;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/*****************************************************************************
*
* FUNCTION : AppendVendorDir
*
* DESCRIPTION : Checks to see if it is a URL, if not, appends the correct path in front
*
* INPUTS :
*
* RETURNS :
*
* COMMENTS : Rules :
* 1. Apply environment variable (%env%) changes to URI string
* 2. Check if it has a '://' substring, if so it is a URL, do nothing and return
* 3. Check if there is a ':\' or ':/' substring, if so it has a fixed path, do nothing and return
* 4. Assume it is a relative path, prefix with vendor directory and return
*
*****************************************************************************/
HRESULT HCUpdate::Engine::AppendVendorDir( /*[in] */ LPCWSTR szURL ,
/*[in] */ LPCWSTR szOwnerID ,
/*[in] */ LPCWSTR szWinDir ,
/*[out]*/ LPWSTR szDest ,
/*[in] */ int iMaxLen )
{
__HCP_FUNC_ENTRY( "HCUpdate::Engine::AppendVendorDir" );
HRESULT hr;
LPWSTR rgTemp = NULL;
LPWSTR rgTemp2 = NULL;
__MPC_EXIT_IF_ALLOC_FAILS(hr, rgTemp, new WCHAR[iMaxLen]);
wcsncpy( rgTemp, szURL, iMaxLen );
//
// Check for :/ or :\ substring. If so, ignore.
//
if(_wcsnicmp( rgTemp, L"app:", 4 ) == 0 ||
wcsstr ( rgTemp, L":/" ) ||
wcsstr ( rgTemp, L":\\" ) )
{
wcscpy( szDest, rgTemp ); // Just copy straight since it is either a URL or fixed path.
}
else // Assume relative path.
{
int i = 0;
//
// Skip the initial slashes.
//
while(rgTemp[i] == '\\' ||
rgTemp[i] == '/' )
{
i++;
}
//
// If 'szWinDir' is not null, then a straight file path is required, otherwise a URL is required.
//
if(szWinDir)
{
MPC::wstring strRoot;
__MPC_EXIT_IF_METHOD_FAILS(hr, m_ts.BaseDir( strRoot )); strRoot.append( HC_HELPSET_SUB_VENDORS );
_snwprintf( szDest, iMaxLen-1, L"%s\\%s\\%s", strRoot.c_str(), szOwnerID, &rgTemp[i] ); szDest[iMaxLen-1] = 0;
//
// Replace all / with \ character.
//
while(szDest[0])
{
if(szDest[0] == '/')
{
szDest[0] = '\\';
}
szDest++;
}
}
else
{
const int iSizeMax = INTERNET_MAX_PATH_LENGTH;
DWORD dwSize = iMaxLen-1;
__MPC_EXIT_IF_ALLOC_FAILS(hr, rgTemp2, new WCHAR[iSizeMax]);
_snwprintf( rgTemp2, iSizeMax-1, PCH_STR_VENDOR_URL, szOwnerID, &rgTemp[i] ); rgTemp2[iSizeMax-1] = 0;
::InternetCanonicalizeUrlW( rgTemp2, szDest, &dwSize, ICU_ENCODE_SPACES_ONLY );
//
// Replace all \ with / character.
//
while(szDest[0])
{
if(szDest[0] == _T('\\'))
{
szDest[0] = _T('/');
}
szDest++;
}
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
delete [] rgTemp;
delete [] rgTemp2;
__HCP_FUNC_EXIT(hr);
}
/*****************************************************************************
*
* FUNCTION : ProcessRegisterContent
*
* DESCRIPTION : Registers trusted content with the content store
*
* INPUTS :
*
* RETURNS :
*
* COMMENTS :
*
*****************************************************************************/
HRESULT HCUpdate::Engine::ProcessRegisterContent( /*[in]*/ Action idAction ,
/*[in]*/ LPCWSTR szURI )
{
__HCP_FUNC_ENTRY( "HCUpdate::Engine::ProcessRegisterContent" );
HRESULT hr;
HRESULT hr2;
WCHAR rgDestPath[MAX_PATH];
bool fCSLocked = false;
PCH_MACRO_CHECK_STRINGW(hr, szURI, L"Error missing URI attribute");
//
// Get the complete URL for the link.
//
AppendVendorDir( szURI, m_pkg->m_strVendorID.c_str(), NULL, rgDestPath, MAXSTRLEN(rgDestPath) );
WriteLog( S_OK, L"Registering trusted content : %s : %s", s_ActionText[idAction], rgDestPath );
//
// Initialize the content store for processing.
//
if(FAILED(hr = CPCHContentStore::s_GLOBAL->Acquire()))
{
__MPC_SET_ERROR_AND_EXIT(hr, WriteLog( hr, L"Error initializing the content store" ));
}
fCSLocked = true;
if(idAction == ACTION_ADD)
{
if(FAILED(hr = CPCHContentStore::s_GLOBAL->Add( rgDestPath, m_pkg->m_strVendorID.c_str(), m_pkg->m_strVendorName.c_str() )))
{
if(hr == E_PCH_URI_EXISTS)
{
PCH_MACRO_DEBUG( L"Trusted content already registered" );
}
else
{
PCH_MACRO_DEBUG( L"Error Register trusted content failed" );
}
}
else
{
PCH_MACRO_DEBUG( L"Trusted content registered" );
}
}
else if(idAction == ACTION_DELETE)
{
if(FAILED(hr = CPCHContentStore::s_GLOBAL->Remove( rgDestPath, m_pkg->m_strVendorID.c_str(), m_pkg->m_strVendorName.c_str() )))
{
__MPC_SET_ERROR_AND_EXIT(hr, WriteLog( hr, L"Error Remove trusted content failed" ));
}
PCH_MACRO_DEBUG( L"Trusted content removed" );
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
if(fCSLocked)
{
if(FAILED(hr2 = CPCHContentStore::s_GLOBAL->Release( true )))
{
WriteLog( hr2, L"Error committing into Content Store" );
}
}
if(FAILED(hr))
{
WriteLog( hr, L"Error processing registered content" );
}
__HCP_FUNC_EXIT(hr);
}
/*****************************************************************************
*
* FUNCTION : ProcessInstallFile
*
* DESCRIPTION : Extracts files to be installed and moves them to the vendor's
* private directory
*
* INPUTS :
*
* RETURNS :
*
* COMMENTS :
*
*****************************************************************************/
HRESULT HCUpdate::Engine::ProcessInstallFile( /*[in]*/ Action idAction ,
/*[in]*/ LPCWSTR szSource ,
/*[in]*/ LPCWSTR szDestination ,
/*[in]*/ bool fSys ,
/*[in]*/ bool fSysHelp )
{
__HCP_FUNC_ENTRY( "HCUpdate::Engine::ProcessInstallFile" );
HRESULT hr;
WCHAR rgDestPath[MAX_PATH];
MPC::wstring strRoot;
if(m_updater.IsOEM() != true)
{
if(fSys == true ||
fSysHelp == true )
{
__MPC_SET_ERROR_AND_EXIT(hr, WriteLog( S_OK, L"Ignoring install file : %s because certificate does not have enough priviliges to install into Sys or SysHelp locations.", szDestination ));
}
}
WriteLog( S_OK, L"Installing file : %s : %s", s_ActionText[idAction], szDestination );
PCH_MACRO_CHECK_STRINGW(hr, szDestination, L"Error missing URI attribute");
// Check if system file modification.
if(fSys || fSysHelp)
{
//
// Destination/uri must be relative to system folder.
// We don't allow a destination to contain ".."
//
if(wcsstr( szDestination, L".." ))
{
__MPC_SET_ERROR_AND_EXIT(hr, WriteLog( HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), L"Error install file has '..' in its path and is not allowed." ));
}
if(fSys)
{
//
// Only Microsoft can actually write to the SYSTEM directory, OEMs write to the SYSTEM_OEM one.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, m_ts.BaseDir( strRoot )); strRoot.append( IsMicrosoft() ? HC_HELPSET_SUB_SYSTEM : HC_HELPSET_SUB_SYSTEM_OEM );
}
if(fSysHelp)
{
if(FAILED(hr = AcquireDatabase()))
{
__MPC_SET_ERROR_AND_EXIT(hr, WriteLog( hr, L"Error finding database to update" ));
}
strRoot = m_updater.GetHelpLocation();
ReleaseDatabase();
}
}
//
// Destination/uri must be relative
// If destination contains the ":" or "\\" char, it must be fullpath.
//
if(wcsstr( szDestination, L":" ) ||
wcsstr( szDestination, L"\\\\" ) )
{
__MPC_SET_ERROR_AND_EXIT(hr, WriteLog( HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), L"Error install file has fullpath, must be relative" ));
}
if(fSys || fSysHelp)
{
MPC::SubstituteEnvVariables( strRoot );
//
// If system folder.
//
_snwprintf( rgDestPath, MAXSTRLEN(rgDestPath), L"%s\\%s", strRoot.c_str(), szDestination ); rgDestPath[MAXSTRLEN(rgDestPath)] = 0;
}
else
{
//
// If regular vendor folder.
//
AppendVendorDir( szDestination, m_pkg->m_strVendorID.c_str(), m_strWinDir.c_str(), rgDestPath, MAXSTRLEN(rgDestPath) );
}
// Adjust slashes.
{
LPWSTR szDest = rgDestPath;
while(szDest[0])
{
if(szDest[0] == '/')
{
szDest[0] = '\\';
}
szDest++;
}
}
// Change the mode to read/write so that file can be replaced.
(void)::SetFileAttributesW( rgDestPath, FILE_ATTRIBUTE_NORMAL );
if(idAction == ACTION_ADD)
{
// Source must not be empty.
if(!STRINGISPRESENT( szSource ))
{
__MPC_SET_ERROR_AND_EXIT(hr, WriteLog( HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), L"Error - missing SOURCE attribute" ));
}
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::FailOnLowDiskSpace( HC_ROOT, PCH_SAFETYMARGIN ));
// Create the directory if it hasn't been created already
if(FAILED(hr = MPC::MakeDir( rgDestPath )))
{
__MPC_SET_ERROR_AND_EXIT(hr, WriteLog( hr, L"Error creating directory for %s", rgDestPath ));
}
// Extract the file and store it in the vendor's private storage area
__MPC_EXIT_IF_METHOD_FAILS(hr, m_pkg->ExtractFile( m_log, rgDestPath, szSource ));
}
else
{
MPC::FileSystemObject fso( rgDestPath );
if(fso.IsDirectory())
{
if(fSys || fSysHelp)
{
__MPC_SET_ERROR_AND_EXIT(hr, WriteLog( S_OK, L"Ignoring directory delete command on '%s', it only works for Vendor's directories.", rgDestPath ));
}
}
if(FAILED(fso.Delete( /*fForce*/true, /*fComplain*/true )))
{
__MPC_SET_ERROR_AND_EXIT(hr, WriteLog( -2, L"Error deleting installation file: %s", rgDestPath ));
}
}
PCH_MACRO_DEBUG( L"Installed file" );
hr = S_OK;
__HCP_FUNC_CLEANUP;
if(FAILED(hr))
{
WriteLog( hr, L"Error processing installation file" );
}
__HCP_FUNC_EXIT(hr);
}
/*****************************************************************************
*
* FUNCTION : ProcessSAFFile
*
* DESCRIPTION : Hand the SAF file over to the SAF lib for registration or removal
*
* INPUTS :
*
* RETURNS :
*
* COMMENTS :
*
*****************************************************************************/
HRESULT HCUpdate::Engine::ProcessSAFFile( /*[in]*/ Action idAction ,
/*[in]*/ LPCWSTR szSAFName ,
/*[in]*/ MPC::XmlUtil& oXMLUtil )
{
__HCP_FUNC_ENTRY( "HCUpdate::Engine::ProcessSAFFile" );
HRESULT hr;
CSAFChannelRecord cr;
WriteLog( S_OK, L"Processing SAF file : %s : %s. OwnerName : %s, Owner ID : %s", s_ActionText[idAction], szSAFName,
m_pkg->m_strVendorName.c_str(), m_pkg->m_strVendorID.c_str() );
cr.m_ths = m_ts;
cr.m_bstrVendorID = m_pkg->m_strVendorID .c_str();
cr.m_bstrVendorName = m_pkg->m_strVendorName.c_str();
if(idAction == ACTION_ADD)
{
if(FAILED(hr = CSAFReg::s_GLOBAL->RegisterSupportChannel( cr, oXMLUtil )))
{
__MPC_SET_ERROR_AND_EXIT(hr, WriteLog( hr, L"Error RegisterSupportChannel on SAF file failed" ));
}
WriteLog( S_OK, L"SAF file registered" );
}
else if(idAction == ACTION_DELETE)
{
if(FAILED(hr = CSAFReg::s_GLOBAL->RemoveSupportChannel( cr, oXMLUtil )))
{
__MPC_SET_ERROR_AND_EXIT(hr, WriteLog( hr, L"Error RemoveSupportChannel on SAF file failed" ));
}
WriteLog( S_OK, L"SAF file removed" );
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
if(FAILED(hr))
{
WriteLog( hr, L"Error processing SAF file" );
}
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/*****************************************************************************
*
* FUNCTION : ProcessPackage
*
* DESCRIPTION : Reads the help_description package and processes the various sections
*
* INPUTS :
*
* RETURNS :
*
* COMMENTS :
*
*****************************************************************************/
HRESULT HCUpdate::Engine::ProcessPackage( /*[in]*/ Taxonomy::InstalledInstance& sku ,
/*[in]*/ Taxonomy::Package& pkg )
{
__HCP_FUNC_ENTRY( "HCUpdate::Engine::ProcessPackage" );
HRESULT hr;
MPC::XmlUtil oXMLUtil;
bool fIsMachineHelp = (sku.m_inst.m_fSystem || sku.m_inst.m_fMUI);
bool fDB = false;
bool fFound;
////////////////////////////////////////////////////////////////////////////////
//
// Now let's validate that we have enough disk space on the drive
//
{
ULARGE_INTEGER liFree;
ULARGE_INTEGER liTotal;
bool fEnoughSpace = false;
if(SUCCEEDED(MPC::GetDiskSpace( m_strWinDir, liFree, liTotal )))
{
fEnoughSpace = (liFree.QuadPart > (ULONGLONG)10e6);
}
if(fEnoughSpace == false)
{
__MPC_SET_ERROR_AND_EXIT(hr, WriteLog( STG_E_MEDIUMFULL, L"Error insufficient disk space for update operation." ));
}
}
//
// We cannot process a generic package if a database is already in use!!
//
if(m_sess || m_db)
{
__MPC_SET_ERROR_AND_EXIT(hr, WriteLog( E_FAIL, L"Recursive invocation of HCUpdate!" ));
}
m_ts = sku.m_inst.m_ths;
m_sku = &sku;
m_pkg = &pkg;
WriteLog( -1, L"\nProcessing package %s [%s] (Vendor: %s) from package store, %s/%d\n\n", pkg.m_strProductID.c_str() ,
pkg.m_strVersion .c_str() ,
pkg.m_strVendorID .c_str() ,
m_ts.GetSKU() ,
m_ts.GetLanguage() );
////////////////////////////////////////////////////////////////////////////////
//
// Check if it is OEM owner
//
{
__MPC_EXIT_IF_METHOD_FAILS(hr, AcquireDatabase()); fDB = true;
__MPC_EXIT_IF_METHOD_FAILS(hr, m_updater.LocateOwner( m_pkg->m_strVendorID.c_str() ));
if(m_updater.GetOwner() == -1)
{
long idOwner;
// Create the owner without OEM privs
__MPC_EXIT_IF_METHOD_FAILS(hr, m_updater.CreateOwner( idOwner, m_pkg->m_strVendorID.c_str(), /*fIsOEM*/false ));
__MPC_EXIT_IF_METHOD_FAILS(hr, m_updater.LocateOwner( m_pkg->m_strVendorID.c_str() ));
}
}
if(m_updater.IsOEM())
{
WriteLog( S_OK, L"Update package has OEM credentials of %s", m_pkg->m_strVendorID.c_str() );
}
__MPC_EXIT_IF_METHOD_FAILS(hr, m_pkg->ExtractPkgDesc( m_log, oXMLUtil ));
////////////////////////////////////////////////////////////////////////////////
//
// Insert OEMs
//
if(m_updater.IsOEM())
{
CComPtr<IXMLDOMNodeList> poNodeList;
if(FAILED(hr = oXMLUtil.GetNodes( PCH_XQL_OEM, &poNodeList )))
{
PCH_MACRO_DEBUG( L"Error processing package_description xml" );
}
else if(CountNodes(poNodeList) > 0)
{
JetBlue::TransactionHandle transaction;
CComPtr<IXMLDOMNode> poNode;
MPC::wstring strDN;
long ID_owner;
//
// Process all the nodes.
//
HCUPDATE_BEGIN_TRANSACTION(hr,transaction);
for(;SUCCEEDED(hr = poNodeList->nextNode( &poNode )) && poNode != NULL; poNode.Release())
{
HCUPDATE_GETATTRIBUTE(hr, oXMLUtil, PCH_TAG_OEM_DN, strDN, fFound, poNode );
PCH_MACRO_CHECK_ABORT(hr);
if(strDN.size() > 0)
{
WriteLog( S_OK, L"Registering '%s' as OEM", strDN.c_str() );
// insert it into the content owner's table, making it an OEM.
__MPC_EXIT_IF_METHOD_FAILS(hr, m_updater.CreateOwner( ID_owner, strDN.c_str(), true ));
}
}
HCUPDATE_COMMIT_TRANSACTION(hr,transaction);
}
}
////////////////////////////////////////////////////////////////////////////////
//
// Insert Search Engines
//
if(fIsMachineHelp && m_updater.IsOEM())
{
CComPtr<IXMLDOMNodeList> poNodeList;
if(FAILED(hr = oXMLUtil.GetNodes( PCH_XQL_SE, &poNodeList )))
{
PCH_MACRO_DEBUG( L"Error processing package_description xml" );
}
else if(CountNodes(poNodeList) > 0)
{
CComPtr<IXMLDOMNode> poNode;
CComPtr<IXMLDOMNode> poDataNode;
Action idAction;
MPC::wstring strAction;
MPC::wstring strCLSID;
MPC::wstring strID;
CComBSTR bstrData;
SearchEngine::Config cfg;
//
// Process all the nodes.
//
for(;SUCCEEDED(hr = poNodeList->nextNode( &poNode )) && poNode != NULL; poNode.Release())
{
PCH_MACRO_CHECK_ABORT(hr);
HCUPDATE_GETATTRIBUTE(hr, oXMLUtil, PCH_TAG_ACTION , strAction, fFound, poNode );
HCUPDATE_GETATTRIBUTE(hr, oXMLUtil, PCH_TAG_SE_ID , strID , fFound, poNode );
HCUPDATE_GETATTRIBUTE(hr, oXMLUtil, PCH_TAG_SE_CLSID, strCLSID , fFound, poNode );
//
// Get the data element
//
if(FAILED(poNode->selectSingleNode( PCH_TAG_SE_DATA, &poDataNode )))
{
PCH_MACRO_DEBUG2( L"Error getting data for search engine %s", strID.c_str());
}
if(FAILED(poDataNode->get_xml(&bstrData)))
{
PCH_MACRO_DEBUG2( L"Error extracting xml data for search engine %s", strID.c_str());
}
__MPC_EXIT_IF_METHOD_FAILS(hr, LookupAction( strAction.c_str(), idAction ));
//
// Check if it is adding search engines
//
if(idAction == ACTION_ADD)
{
WriteLog( S_OK, L"Adding Search Engine : Name : %s, CLSID : %s", strID.c_str(), strCLSID.c_str() );
// register the search engine
__MPC_EXIT_IF_METHOD_FAILS(hr, cfg.RegisterWrapper( m_ts, strID.c_str(), m_pkg->m_strVendorID.c_str(), strCLSID.c_str(), bstrData ));
}
else if(idAction == ACTION_DELETE)
{
WriteLog( S_OK, L"Deleting Search Engine : Name : %s, CLSID : %s", strID.c_str(), strCLSID.c_str() );
// unregister the search engine
__MPC_EXIT_IF_METHOD_FAILS(hr, cfg.UnRegisterWrapper( m_ts, strID.c_str(), m_pkg->m_strVendorID.c_str() ));
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
//
// Search & process saf config files
//
if(fIsMachineHelp && m_updater.IsOEM())
{
CComPtr<IXMLDOMNodeList> poNodeList;
if(FAILED(hr = oXMLUtil.GetNodes( PCH_XQL_SAF, &poNodeList )))
{
PCH_MACRO_DEBUG( L"Error processing package_description xml" );
}
else if(CountNodes(poNodeList) > 0)
{
CComPtr<IXMLDOMNode> poNode;
Action idAction;
MPC::wstring strAction;
MPC::wstring strFilename;
//
// Process all the nodes.
//
for(;SUCCEEDED(hr = poNodeList->nextNode( &poNode )) && poNode != NULL; poNode.Release())
{
MPC::XmlUtil xmlSAF;
PCH_MACRO_CHECK_ABORT(hr);
HCUPDATE_GETATTRIBUTE(hr, oXMLUtil, PCH_TAG_ACTION, strAction , fFound, poNode);
HCUPDATE_GETATTRIBUTE(hr, oXMLUtil, PCH_TAG_FILE , strFilename, fFound, poNode);
__MPC_EXIT_IF_METHOD_FAILS(hr, LookupAction( strAction.c_str(), idAction ));
// Extract the SAF file into the temp directory
__MPC_EXIT_IF_METHOD_FAILS(hr, m_pkg->ExtractXMLFile( m_log, xmlSAF, Taxonomy::Strings::s_tag_root_SAF, strFilename.c_str() ));
// process the SAF file
__MPC_EXIT_IF_METHOD_FAILS(hr, ProcessSAFFile( idAction, strFilename.c_str(), xmlSAF ));
}
}
}
////////////////////////////////////////////////////////////////////////////////
//
// Search & install help content
//
{
CComPtr<IXMLDOMNodeList> poNodeList;
if(FAILED(hr = oXMLUtil.GetNodes( PCH_XQL_INSTALLFILE, &poNodeList )))
{
PCH_MACRO_DEBUG( L"Error processing package_description xml" );
}
else if(CountNodes(poNodeList) > 0)
{
CComPtr<IXMLDOMNode> poNode;
Action idAction;
MPC::wstring strAction;
MPC::wstring strSource;
MPC::wstring strDest;
MPC::wstring strSys;
MPC::wstring strSysHelp;
bool fSys;
bool fSysHelp;
//
// Process all the nodes.
//
for(;SUCCEEDED(hr = poNodeList->nextNode( &poNode )) && poNode != NULL; poNode.Release())
{
PCH_MACRO_CHECK_ABORT(hr);
HCUPDATE_GETATTRIBUTE (hr, oXMLUtil, PCH_TAG_ACTION , strAction , fFound, poNode);
HCUPDATE_GETATTRIBUTE_OPT(hr, oXMLUtil, PCH_TAG_SOURCE , strSource , fFound, poNode);
HCUPDATE_GETATTRIBUTE (hr, oXMLUtil, PCH_TAG_URI , strDest , fFound, poNode);
HCUPDATE_GETATTRIBUTE_OPT(hr, oXMLUtil, PCH_TAG_SYS , strSys , fFound, poNode);
HCUPDATE_GETATTRIBUTE_OPT(hr, oXMLUtil, PCH_TAG_SYSHELP, strSysHelp, fFound, poNode);
__MPC_EXIT_IF_METHOD_FAILS(hr, LookupAction ( strAction .c_str(), idAction ));
__MPC_EXIT_IF_METHOD_FAILS(hr, LookupBoolean( strSys .c_str(), fSys , false ));
__MPC_EXIT_IF_METHOD_FAILS(hr, LookupBoolean( strSysHelp.c_str(), fSysHelp, false ));
//
// If the package is not the machine SKU, you don't want to install contents other than System Help Files.
//
if(fIsMachineHelp == false)
{
if(fSys == true ) continue;
if(fSysHelp == false) continue;
}
// install the file
__MPC_EXIT_IF_METHOD_FAILS(hr, ProcessInstallFile( idAction, strSource.c_str(), strDest.c_str(), fSys, fSysHelp ));
}
}
}
////////////////////////////////////////////////////////////////////////////////
//
// Search & register trusted content
//
if(fIsMachineHelp && m_updater.IsOEM())
{
CComPtr<IXMLDOMNodeList> poNodeList;
if(FAILED(hr = oXMLUtil.GetNodes( PCH_XQL_TRUSTED, &poNodeList )))
{
PCH_MACRO_DEBUG( L"Error processing package_description xml" );
}
else if(CountNodes(poNodeList) > 0)
{
CComPtr<IXMLDOMNode> poNode;
Action idAction;
MPC::wstring strAction;
MPC::wstring strURI;
//
// Process all the nodes.
//
for(;SUCCEEDED(hr = poNodeList->nextNode( &poNode )) && poNode != NULL; poNode.Release())
{
PCH_MACRO_CHECK_ABORT(hr);
HCUPDATE_GETATTRIBUTE(hr, oXMLUtil, PCH_TAG_ACTION, strAction, fFound, poNode);
HCUPDATE_GETATTRIBUTE(hr, oXMLUtil, PCH_TAG_URI , strURI , fFound, poNode);
__MPC_EXIT_IF_METHOD_FAILS(hr, LookupAction( strAction.c_str(), idAction ));
// register the content
__MPC_EXIT_IF_METHOD_FAILS(hr, ProcessRegisterContent( idAction, strURI.c_str() ));
}
}
}
////////////////////////////////////////////////////////////////////////////////
//
// Search & process hht files
//
{
CComPtr<IXMLDOMNodeList> poNodeList;
if(FAILED(hr = oXMLUtil.GetNodes( PCH_XQL_HHT, &poNodeList)))
{
PCH_MACRO_DEBUG( L"Error processing package_description xml" );
}
else if(CountNodes(poNodeList) > 0)
{
CComPtr<IXMLDOMNode> poNode;
MPC::wstring strFilename;
//
// Process all the nodes.
//
for(;SUCCEEDED(hr = poNodeList->nextNode( &poNode )) && poNode != NULL; poNode.Release())
{
MPC::XmlUtil xmlHHT;
PCH_MACRO_CHECK_ABORT(hr);
// get the filename
HCUPDATE_GETATTRIBUTE(hr, oXMLUtil, PCH_TAG_FILE, strFilename, fFound, poNode);
// Extract the HHT file into the temp directory
__MPC_EXIT_IF_METHOD_FAILS(hr, m_pkg->ExtractXMLFile( m_log, xmlHHT, Taxonomy::Strings::s_tag_root_HHT, strFilename.c_str() ));
// process the HHT file
__MPC_EXIT_IF_METHOD_FAILS(hr, ProcessHHTFile( strFilename.c_str(), xmlHHT ));
}
}
}
////////////////////////////////////////////////////////////////////////////////
//
// Search and add News content
//
{
CComPtr<IXMLDOMNodeList> poNodeList;
if (FAILED(hr = oXMLUtil.GetNodes( PCH_XQL_NEWSROOT, &poNodeList)))
{
PCH_MACRO_DEBUG( L"Error processing package_description.xml" );
}
else
{
if(CountNodes(poNodeList) > 0)
{
CComPtr<IXMLDOMNode> poNodeHeadline;
MPC::wstring strCurrentSKU;
LPCWSTR szCurrentSKU = m_ts.GetSKU ();
long lCurrentLCID = m_ts.GetLanguage();
News::UpdateHeadlines uhUpdate;
MPC::wstring strIcon;
MPC::wstring strTitle;
MPC::wstring strLink;
MPC::wstring strDescription;
MPC::wstring strExpiryDate;
CComBSTR strTimeOutDays;
int nTimeOutDays;
DATE dExpiryDate;
long lIndex;
// Strip off the number from the SKU
{
LPCWSTR szEnd = wcschr( szCurrentSKU, '_' );
size_t len = szEnd ? szEnd - szCurrentSKU : wcslen( szCurrentSKU );
strCurrentSKU.assign( szCurrentSKU, len );
}
// Get all the news items and return them in the reverse order
__MPC_EXIT_IF_METHOD_FAILS(hr, poNodeList->get_length( &lIndex ));
for(--lIndex; lIndex >= 0; --lIndex)
{
if(SUCCEEDED(hr = poNodeList->get_item( lIndex, &poNodeHeadline )) && poNodeHeadline != NULL)
{
PCH_MACRO_CHECK_ABORT(hr);
//// Quick fix for 357806 - ignore the ICON attribute
////__MPC_EXIT_IF_METHOD_FAILS(hr, oXMLUtil.GetAttribute(NULL, PCH_TAG_NEWS_ICON , strIcon , fFound, poNodeHeadline));
__MPC_EXIT_IF_METHOD_FAILS(hr, oXMLUtil.GetAttribute(NULL, PCH_TAG_NEWS_TITLE , strTitle , fFound, poNodeHeadline));
__MPC_EXIT_IF_METHOD_FAILS(hr, oXMLUtil.GetAttribute(NULL, PCH_TAG_NEWS_LINK , strLink , fFound, poNodeHeadline));
__MPC_EXIT_IF_METHOD_FAILS(hr, oXMLUtil.GetAttribute(NULL, PCH_TAG_NEWS_DESCRIPTION, strDescription, fFound, poNodeHeadline));
__MPC_EXIT_IF_METHOD_FAILS(hr, oXMLUtil.GetAttribute(NULL, PCH_TAG_NEWS_TIMEOUT , strTimeOutDays, fFound, poNodeHeadline));
__MPC_EXIT_IF_METHOD_FAILS(hr, oXMLUtil.GetAttribute(NULL, PCH_TAG_NEWS_EXPIRYDATE , strExpiryDate , fFound, poNodeHeadline));
// Make the necessary conversions
if(FAILED(hr = MPC::ConvertStringToDate( strExpiryDate, dExpiryDate, /*fGMT*/false, /*fCIM*/false, -1 )))
{
dExpiryDate = 0;
}
if(strTimeOutDays.Length() > 0)
{
nTimeOutDays = _wtoi(strTimeOutDays);
}
else
{
nTimeOutDays = 0;
}
// Finally add the headlines - make sure that the title and link are not empty strings
if(strTitle.length() > 0 && strLink.length() > 0)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, uhUpdate.Add( lCurrentLCID, strCurrentSKU, strIcon, strTitle, strLink, strDescription, nTimeOutDays, dExpiryDate ));
}
else
{
WriteLog(S_OK, L"Skipping headlines no. %d because attribute TITLE or attribute LINK was not found", lIndex + 1);
}
poNodeHeadline.Release();
}
}
WriteLog(S_OK, L"Headlines were successfully processed");
}
else
{
WriteLog(S_OK, L"No headlines items found");
}
}
}
hr = S_OK;
////////////////////////////////////////////////////////////////////////////////
__HCP_FUNC_CLEANUP;
if(fDB)
{
ReleaseDatabase();
}
////////////////////
__HCP_FUNC_EXIT(hr);
}
HRESULT HCUpdate::Engine::RecreateIndex( /*[in]*/ Taxonomy::InstalledInstance& sku, /*[in]*/ bool fForce )
{
__HCP_FUNC_ENTRY( "HCUpdate::Engine::RecreateIndex" );
HRESULT hr;
m_ts = sku.m_inst.m_ths;
m_sku = &sku;
m_pkg = NULL;
if(FAILED(hr = InternalCreateIndex( fForce ? VARIANT_TRUE : VARIANT_FALSE )))
{
__MPC_SET_ERROR_AND_EXIT(hr, WriteLog( hr, L"Error merging index" ));
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}