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.
 
 
 
 
 
 

1746 lines
56 KiB

/******************************************************************************
Copyright (c) 2000 Microsoft Corporation
Module Name:
SetOfHelpTopics.cpp
Abstract:
This file contains the implementation of the CPCHSetOfHelpTopics class,
that models the set of help file for a particular SKU/Language pair.
Revision History:
Davide Massarenti (Dmassare) 07/01/2000
created
******************************************************************************/
#include "stdafx.h"
#include <MergedHhk.h>
#include <algorithm>
static const WCHAR c_SetupImage [] = L"PCHDT_";
static const WCHAR c_CabExtension [] = L".cab";
static const WCHAR c_ListPrefix [] = L"[SourceDisksFiles]";
static const WCHAR c_ListPrefixX86 [] = L"[SourceDisksFiles.x86]";
static const WCHAR c_ListPrefixIA64[] = L"[SourceDisksFiles.";
////////////////////////////////////////////////////////////////////////////////
static HRESULT Local_ParseLayoutInf( /*[in ]*/ LPCWSTR szFile ,
/*[out]*/ MPC::WStringUCLookup* mapAll ,
/*[out]*/ MPC::WStringUCLookup* mapX86 ,
/*[out]*/ MPC::WStringUCLookup* mapIA64 )
{
__HCP_FUNC_ENTRY( "Local_ParseLayoutInf" );
HRESULT hr;
HHK::Reader* reader = NULL;
MPC::wstring strLine;
MPC::WStringUCLookup* mapActive = NULL;
__MPC_EXIT_IF_ALLOC_FAILS(hr, reader, new HHK::Reader);
__MPC_EXIT_IF_METHOD_FAILS(hr, reader->Init( szFile ));
while(reader->GetLine( &strLine ))
{
LPCWSTR szPtr = strLine.c_str();
if(szPtr[0] == '[')
{
if (!_wcsnicmp( szPtr, c_ListPrefix , MAXSTRLEN( c_ListPrefix ) )) mapActive = mapAll;
else if(!_wcsnicmp( szPtr, c_ListPrefixX86 , MAXSTRLEN( c_ListPrefixX86 ) )) mapActive = mapX86;
else if(!_wcsnicmp( szPtr, c_ListPrefixIA64, MAXSTRLEN( c_ListPrefixIA64 ) )) mapActive = mapIA64;
else mapActive = NULL;
}
if(mapActive)
{
std::vector<MPC::wstring> vec1;
//
// <Source filename> = <diskid>,<subdir>,<size>,<checksum>,<spare>,<spare>,<bootmedia>,<targetdir>,<upgradedisp>,<cleandisp>,<targetname>
//
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::SplitAtDelimiter( vec1, szPtr, L" \t", false, true ));
if(vec1.size() >= 3)
{
std::vector<MPC::wstring> vec2;
LPCWSTR szCDName = vec1[0].c_str();
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::SplitAtDelimiter( vec2, vec1[2].c_str(), L",", false, false ));
if(vec2.size() >= 11)
{
(*mapActive)[vec2[10]] = szCDName;
}
else
{
(*mapActive)[szCDName] = szCDName;
}
}
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
delete reader;
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////////////////////////////////////////////
#define FAIL_IF_RUNNING() \
{ \
if(Thread_IsRunning()) \
{ \
switch(m_shtStatus) \
{ \
case SHT_QUERIED : \
case SHT_INSTALLED : \
case SHT_UNINSTALLED: \
case SHT_ABORTED : \
case SHT_FAILED : \
break; \
\
default: \
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_BUSY); \
} \
} \
}
#define EXIT_IF_ABORTED() \
{ \
if(Thread_IsAborted()) \
{ \
(void)put_Status( SHT_ABORTING, NULL ); \
__MPC_SET_ERROR_AND_EXIT(hr, E_ABORT); \
} \
}
#define CHANGE_STATE(x,y) \
{ \
EXIT_IF_ABORTED(); \
__MPC_EXIT_IF_METHOD_FAILS(hr, put_Status( x, y )); \
}
#define CHECK_WRITE_PERMISSIONS() __MPC_EXIT_IF_METHOD_FAILS(hr, VerifyWritePermissions());
////////////////////////////////////////////////////////////////////////////////
CPCHSetOfHelpTopics::CPCHSetOfHelpTopics()
{
// Taxonomy::Settings m_ts;
// Taxonomy::Instance m_inst;
// CComPtr<IDispatch> m_sink_onStatusChange;
m_shtStatus = SHT_NOTACTIVE; // SHT_STATUS m_shtStatus;
m_hrErrorCode = S_OK; // HRESULT m_hrErrorCode;
m_fReadyForCommands = false; // bool m_fReadyForCommands;
//
// MPC::Impersonation m_imp;
//
m_fInstalled = false; // bool m_fInstalled;
//
m_fConnectedToDisk = false; // bool m_fConnectedToDisk;
// MPC::wstring m_strDirectory;
// MPC::wstring m_strCAB;
// MPC::wstring m_strLocalCAB;
//
m_fConnectedToServer = false; // bool m_fConnectedToServer;
// MPC::wstring m_strServer;
// CComPtr<IPCHSetOfHelpTopics> m_sku;
// CComPtr<IPCHService> m_svc;
//
m_fActAsCollection = false; // bool m_fActAsCollection;
// CComPtr<CPCHCollection> m_coll;
}
CPCHSetOfHelpTopics::~CPCHSetOfHelpTopics()
{
(void)Close( true );
}
HRESULT CPCHSetOfHelpTopics::Close( /*[in]*/ bool fCleanup )
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::Close" );
HRESULT hr;
//
// Do the final cleanup.
//
if(fCleanup)
{
Thread_Wait();
(void)MPC::RemoveTemporaryFile( m_strLocalCAB );
m_fConnectedToDisk = false; // bool m_fConnectedToDisk;
m_strDirectory = L""; // MPC::wstring m_strDirectory;
m_strCAB = L""; // MPC::wstring m_strCAB;
// MPC::wstring m_strLocalCAB;
m_fConnectedToServer = false; // bool m_fConnectedToServer;
m_strServer = L""; // MPC::wstring m_strServer;
m_sku.Release(); // CComPtr<IPCHSetOfHelpTopics> m_sku;
m_svc.Release(); // CComPtr<IPCHService> m_svc;
}
hr = S_OK;
__HCP_FUNC_EXIT(hr);
}
void CPCHSetOfHelpTopics::CleanupWorkerThread( /*[in]*/ HRESULT hr )
{
(void)EndImpersonation();
(void)Close( false );
if(FAILED(hr))
{
m_hrErrorCode = hr;
(void)put_Status( (hr == E_ABORT) ? SHT_ABORTED : SHT_FAILED, NULL );
}
(void)Thread_Abort();
}
HRESULT CPCHSetOfHelpTopics::PrepareSettings()
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::PrepareSettings" );
HRESULT hr;
m_ts = m_inst.m_ths;
m_fReadyForCommands = true;
hr = S_OK;
__HCP_FUNC_EXIT(hr);
}
////////////////////
HRESULT CPCHSetOfHelpTopics::ImpersonateCaller()
{
return m_imp.Impersonate();
}
HRESULT CPCHSetOfHelpTopics::EndImpersonation()
{
return m_imp.RevertToSelf();
}
////////////////////
HRESULT CPCHSetOfHelpTopics::GetListOfFilesFromDatabase( /*[in]*/ const MPC::wstring& strDB ,
/*[out]*/ MPC::WStringList& lst )
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::GetListOfFilesFromDatabase" );
USES_CONVERSION;
HRESULT hr;
LPCSTR szDB = W2A( strDB.c_str() );
JetBlue::SessionHandle sess;
JetBlue::Database* db;
Taxonomy::Updater updater;
__MPC_EXIT_IF_METHOD_FAILS(hr, JetBlue::SessionPool::s_GLOBAL->GetSession( sess ));
__MPC_EXIT_IF_METHOD_FAILS(hr, sess->GetDatabase( szDB, db, /*fCreate*/false, /*fRepair*/false, /*fReadOnly*/true ));
__MPC_EXIT_IF_METHOD_FAILS(hr, updater.Init( m_ts, db ));
__MPC_EXIT_IF_METHOD_FAILS(hr, updater.ListAllTheHelpFiles( lst ));
hr = S_OK;
__HCP_FUNC_CLEANUP;
(void)updater.Close();
sess.Release();
JetBlue::SessionPool::s_GLOBAL->ReleaseDatabase( szDB );
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////////////////////////////////////////////
HRESULT CPCHSetOfHelpTopics::PopulateFromDisk( /*[in]*/ CPCHSetOfHelpTopics* pParent ,
/*[in]*/ const MPC::wstring& strDirectory )
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::PopulateFromDisk" );
HRESULT hr;
__MPC_PARAMCHECK_BEGIN(hr)
__MPC_PARAMCHECK_NOTNULL(pParent);
__MPC_PARAMCHECK_END();
__MPC_EXIT_IF_METHOD_FAILS(hr, Close( true ));
m_imp = pParent->m_imp;
////////////////////////////////////////
m_fConnectedToDisk = true;
m_strDirectory = strDirectory;
////////////////////////////////////////
//
// Find SKUs, recursively enumerating folders.
//
{
MPC::wstring strLayout( m_strDirectory ); strLayout += L"\\layout.inf";
MPC::WStringUCLookup mapLayout;
MPC::WStringUCLookupIter itLayout;
LPCWSTR szCAB_first = NULL;
LPCWSTR szCAB_srv = NULL;
EXIT_IF_ABORTED();
__MPC_EXIT_IF_METHOD_FAILS(hr, ImpersonateCaller ( ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Local_ParseLayoutInf( strLayout.c_str(), &mapLayout, NULL, NULL ));
__MPC_EXIT_IF_METHOD_FAILS(hr, EndImpersonation ( ));
for(itLayout = mapLayout.begin(); itLayout != mapLayout.end(); itLayout++)
{
LPCWSTR szName = itLayout->first.c_str();
if(!wcsncmp( szName, c_SetupImage, MAXSTRLEN(c_SetupImage) ))
{
LPCWSTR szFile = itLayout->second.c_str();
if(!szCAB_first) szCAB_first = szFile;
//
// Special case for Server: it also contains the AdvancedServer stuff.
//
if(!wcscmp( szName, L"PCHDT_S3.CAB" )) szCAB_srv = szFile;
if(!wcscmp( szName, L"PCHDT_S6.CAB" )) szCAB_srv = szFile;
}
}
if(!szCAB_first)
{
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_FILE_NOT_FOUND);
}
m_strCAB = m_strDirectory; m_strCAB += L"\\"; m_strCAB += (szCAB_srv ? szCAB_srv : szCAB_first);
}
//
// Make a local copy of the data archive, using the user credentials.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetTemporaryFileName ( m_strLocalCAB ));
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::CopyOrExtractFileWhileImpersonating( m_strCAB.c_str(), m_strLocalCAB.c_str(), m_imp ));
EXIT_IF_ABORTED();
//
// Extract the database to a temporary file.
//
{
Installer::Package pkg;
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Init( m_strLocalCAB.c_str() ));
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Load( ));
__MPC_EXIT_IF_METHOD_FAILS(hr, m_inst.InitializeFromBase( pkg.GetData(), /*fSystem*/false, /*fMUI*/false ));
}
EXIT_IF_ABORTED();
////////////////////////////////////////////////////////////////////////////////
__MPC_EXIT_IF_METHOD_FAILS(hr, PrepareSettings());
m_shtStatus = SHT_QUERIED;
hr = S_OK;
__HCP_FUNC_CLEANUP;
CleanupWorkerThread( hr );
__HCP_FUNC_EXIT(hr);
}
HRESULT CPCHSetOfHelpTopics::PopulateFromServer( /*[in]*/ CPCHSetOfHelpTopics* pParent, /*[in]*/ IPCHSetOfHelpTopics* sku, /*[in]*/ IPCHService* svc )
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::PopulateFromServer" );
HRESULT hr;
MPC::SmartLock<_ThreadModel> lock( this );
CComBSTR bstrDB_SKU;
long lDB_LCID;
CComBSTR bstrDB_DisplayName;
__MPC_PARAMCHECK_BEGIN(hr)
__MPC_PARAMCHECK_NOTNULL(pParent);
__MPC_PARAMCHECK_NOTNULL(sku);
__MPC_PARAMCHECK_NOTNULL(svc);
__MPC_PARAMCHECK_END();
__MPC_EXIT_IF_METHOD_FAILS(hr, Close( true ));
m_imp = pParent->m_imp;
////////////////////////////////////////
m_fConnectedToServer = true;
m_strServer = pParent->m_strServer;
m_sku = sku;
m_svc = svc;
////////////////////////////////////////////////////////////////////////////////
__MPC_EXIT_IF_METHOD_FAILS(hr, sku->get_SKU ( &bstrDB_SKU ));
__MPC_EXIT_IF_METHOD_FAILS(hr, sku->get_Language ( & lDB_LCID ));
__MPC_EXIT_IF_METHOD_FAILS(hr, sku->get_DisplayName( &bstrDB_DisplayName ));
m_inst.m_ths.m_strSKU = SAFEBSTR( bstrDB_SKU );
m_inst.m_ths.m_lLCID = lDB_LCID ;
m_inst.m_strDisplayName = SAFEBSTR( bstrDB_DisplayName );
////////////////////////////////////////////////////////////////////////////////
__MPC_EXIT_IF_METHOD_FAILS(hr, PrepareSettings());
m_shtStatus = SHT_QUERIED;
hr = S_OK;
__HCP_FUNC_CLEANUP;
CleanupWorkerThread( hr );
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////////////////////////////////////////////
HRESULT CPCHSetOfHelpTopics::VerifyWritePermissions()
{
return MPC::CheckCallerAgainstPrincipal( /*fImpersonate*/true, NULL, MPC::IDENTITY_SYSTEM |
MPC::IDENTITY_ADMIN |
MPC::IDENTITY_ADMINS |
MPC::IDENTITY_POWERUSERS );
}
////////////////////////////////////////////////////////////////////////////////
HRESULT CPCHSetOfHelpTopics::RunInitFromDisk()
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::RunInitFromDisk" );
HRESULT hr;
MPC::WStringList lst;
//
// There's a possible race condition between the call to ConnectToDisk and the firing of the QUERIED event,
// in case the directory doesn't exist at all: QUERIED is fired before the method returns a pointer to the object...
//
::SetThreadPriority( ::GetCurrentThread(), THREAD_PRIORITY_LOWEST ); ::Sleep( 10 );
__MPC_TRY_BEGIN();
CHANGE_STATE( SHT_QUERYING, NULL );
////////////////////////////////////////////////////////////////////////////////
lst.push_back( m_strDirectory );
while(lst.size())
{
MPC::wstring strDir = lst.front(); lst.pop_front();
//
// Look for subfolders.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, ImpersonateCaller());
{
MPC::FileSystemObject fso( strDir.c_str() );
MPC::FileSystemObject::List fso_lst;
MPC::FileSystemObject::IterConst fso_it;
if(SUCCEEDED(fso.Scan ( )) &&
SUCCEEDED(fso.EnumerateFolders( fso_lst )) )
{
for(fso_it=fso_lst.begin(); fso_it != fso_lst.end(); fso_it++)
{
MPC::wstring strSubFolder;
if(SUCCEEDED((*fso_it)->get_Path( strSubFolder )))
{
lst.push_back( strSubFolder );
}
EXIT_IF_ABORTED();
}
}
}
__MPC_EXIT_IF_METHOD_FAILS(hr, EndImpersonation());
EXIT_IF_ABORTED();
{
CComPtr<CPCHSetOfHelpTopics> obj;
//
// Create an object to analyze the directory.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj ));
{
CPCHSetOfHelpTopics* pObj = obj; // Working around ATL template problem...
if(SUCCEEDED(pObj->PopulateFromDisk( this, strDir )))
{
__MPC_EXIT_IF_METHOD_FAILS(hr, m_coll->AddItem( pObj ));
CHANGE_STATE( SHT_QUERYING, NULL );
}
}
}
}
EXIT_IF_ABORTED();
////////////////////////////////////////////////////////////////////////////////
CHANGE_STATE( SHT_QUERIED, NULL );
hr = S_OK;
__HCP_FUNC_CLEANUP;
__MPC_TRY_CATCHALL(hr);
CleanupWorkerThread( hr );
__HCP_FUNC_EXIT(hr);
}
HRESULT CPCHSetOfHelpTopics::RunInitFromServer()
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::RunInitFromServer" );
HRESULT hr;
IPCHService* svc;
COSERVERINFO si; ::ZeroMemory( &si, sizeof( si ) );
MULTI_QI qi; ::ZeroMemory( &qi, sizeof( qi ) );
CComPtr<IPCHCollection> serverSKUs;
//
// There's a possible race condition between the call to ConnectToServer and the firing of the QUERIED event,
// in case the server doesn't exist at all: QUERIED is fired before the method returns a pointer to the object...
//
::SetThreadPriority( ::GetCurrentThread(), THREAD_PRIORITY_LOWEST ); ::Sleep( 10 );
__MPC_TRY_BEGIN();
CHANGE_STATE( SHT_QUERYING, NULL );
////////////////////////////////////////
__MPC_EXIT_IF_METHOD_FAILS(hr, ImpersonateCaller());
si.pwszName = (LPWSTR)m_strServer.c_str();
qi.pIID = &IID_IPCHService;
__MPC_EXIT_IF_METHOD_FAILS(hr, ::CoCreateInstanceEx( CLSID_PCHService, NULL, CLSCTX_REMOTE_SERVER, &si, 1, &qi ));
__MPC_EXIT_IF_METHOD_FAILS(hr, qi.hr);
__MPC_EXIT_IF_METHOD_FAILS(hr, EndImpersonation());
////////////////////////////////////////
svc = (IPCHService*)qi.pItf;
__MPC_EXIT_IF_METHOD_FAILS(hr, svc->get_RemoteSKUs( &serverSKUs ));
//
// Copy the items in the remote collection.
//
{
long lCount;
long lPos;
__MPC_EXIT_IF_METHOD_FAILS(hr, serverSKUs->get_Count( &lCount ));
for(lPos=1; lPos<=lCount; lPos++)
{
CComVariant v;
CComPtr<IPCHSetOfHelpTopics> sku;
CComPtr<CPCHSetOfHelpTopics> obj;
__MPC_EXIT_IF_METHOD_FAILS(hr, serverSKUs->get_Item( lPos, &v ));
__MPC_EXIT_IF_METHOD_FAILS(hr, v.ChangeType( VT_DISPATCH ));
__MPC_EXIT_IF_METHOD_FAILS(hr, v.pdispVal->QueryInterface( IID_IPCHSetOfHelpTopics, (LPVOID*)&sku ));
//
// Make a proxy of the remote SKU.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &obj ));
{
CPCHSetOfHelpTopics* pObj = obj; // Working around ATL template problem...
__MPC_EXIT_IF_METHOD_FAILS(hr, pObj->PopulateFromServer( this, sku, svc ));
__MPC_EXIT_IF_METHOD_FAILS(hr, m_coll->AddItem( pObj ));
CHANGE_STATE( SHT_QUERYING, NULL );
}
}
}
////////////////////////////////////////////////////////////////////////////////
CHANGE_STATE( SHT_QUERIED, NULL );
hr = S_OK;
__HCP_FUNC_CLEANUP;
__MPC_TRY_CATCHALL(hr);
MPC::Release( qi.pItf );
CleanupWorkerThread( hr );
__HCP_FUNC_EXIT(hr);
}
////////////////////
HRESULT CPCHSetOfHelpTopics::RunInstall()
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::RunInstall" );
HRESULT hr;
Installer::Package pkg;
__MPC_TRY_BEGIN();
CHANGE_STATE( SHT_COPYING_DB, NULL );
////////////////////////////////////////////////////////////////////////////////
//
// Phase Zero: get the database.
//
if(m_fConnectedToServer)
{
CComPtr<IPCHRemoteHelpContents> rhc;
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetTemporaryFileName( m_strLocalCAB ));
__MPC_EXIT_IF_METHOD_FAILS(hr, m_svc->RemoteHelpContents( CComBSTR( m_inst.m_ths.GetSKU() ), m_inst.m_ths.GetLanguage(), &rhc ));
if(rhc == NULL) __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
//
// Get the data archive.
//
{
CComPtr<IUnknown> unkSrc;
CComQIPtr<IStream> streamSrc;
CComPtr<IStream> streamDst;
__MPC_EXIT_IF_METHOD_FAILS(hr, rhc->GetDatabase( &unkSrc )); streamSrc = unkSrc;
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::OpenStreamForWrite( m_strLocalCAB.c_str(), &streamDst ));
EXIT_IF_ABORTED();
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::BaseStream::TransferData( streamSrc, streamDst ));
EXIT_IF_ABORTED();
}
EXIT_IF_ABORTED();
}
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Init( m_strLocalCAB.c_str() ));
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Load( ));
__MPC_EXIT_IF_METHOD_FAILS(hr, DirectInstall( pkg, /*fSetup*/false, /*fSystem*/false, /*fMUI*/false ));
hr = S_OK;
__HCP_FUNC_CLEANUP;
__MPC_TRY_CATCHALL(hr);
CleanupWorkerThread( hr );
//
// In case of failure, remote everything...
//
if(FAILED(hr))
{
(void)DirectUninstall();
}
__HCP_FUNC_EXIT(hr);
}
HRESULT CPCHSetOfHelpTopics::RunUninstall()
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::RunUninstall" );
HRESULT hr;
__MPC_TRY_BEGIN();
CHANGE_STATE( SHT_UNINSTALLING, NULL );
__MPC_EXIT_IF_METHOD_FAILS(hr, DirectUninstall());
CHANGE_STATE( SHT_UNINSTALLED, NULL );
hr = S_OK;
__HCP_FUNC_CLEANUP;
__MPC_TRY_CATCHALL(hr);
CleanupWorkerThread( hr );
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////
HRESULT CPCHSetOfHelpTopics::Fire_onStatusChange( IPCHSetOfHelpTopics* obj, SHT_STATUS lStatus, long hrErrorCode, BSTR bstrFile )
{
CComPtr<IDispatch> func;
CComVariant pvars[4];
//
// Only lock this!
//
{
MPC::SmartLock<_ThreadModel> lock( this );
func = m_sink_onStatusChange;
}
pvars[3] = obj;
pvars[2] = lStatus;
pvars[1] = hrErrorCode;
pvars[0] = bstrFile;
return FireAsync_Generic( DISPID_PCH_SHTE__ONSTATUSCHANGE, pvars, ARRAYSIZE( pvars ), func );
}
HRESULT CPCHSetOfHelpTopics::put_Status( /*[in]*/ SHT_STATUS newVal, /*[in]*/ BSTR bstrFile )
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::put_Status" );
HRESULT hr;
long hrErrorCode;
MPC::SmartLock<_ThreadModel> lock( this );
m_shtStatus = newVal;
hrErrorCode = m_hrErrorCode;
lock = NULL; // Unlock before firing events.
__MPC_EXIT_IF_METHOD_FAILS(hr, Fire_onStatusChange( this, newVal, hrErrorCode, bstrFile ));
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
////////////////////
HRESULT CPCHSetOfHelpTopics::Init( /*[in]*/ const Taxonomy::Instance& inst )
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::Init" );
HRESULT hr;
MPC::SmartLock<_ThreadModel> lock( this );
__MPC_EXIT_IF_METHOD_FAILS(hr, Close( true ));
////////////////////////////////////////
m_fInstalled = true;
m_inst = inst;
m_shtStatus = SHT_INSTALLED;
__MPC_EXIT_IF_METHOD_FAILS(hr, PrepareSettings());
hr = S_OK;
__HCP_FUNC_CLEANUP;
CleanupWorkerThread( hr );
__HCP_FUNC_EXIT(hr);
}
HRESULT CPCHSetOfHelpTopics::InitFromDisk( /*[in]*/ LPCWSTR szDirectory, /*[in]*/ CPCHCollection* pColl )
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::InitFromDisk" );
HRESULT hr;
MPC::SmartLock<_ThreadModel> lock( NULL );
__MPC_PARAMCHECK_BEGIN(hr)
__MPC_PARAMCHECK_STRING_NOT_EMPTY(szDirectory);
__MPC_PARAMCHECK_NOTNULL(pColl);
__MPC_PARAMCHECK_END();
Thread_Wait(); lock = this;
__MPC_EXIT_IF_METHOD_FAILS(hr, Close( true ));
__MPC_EXIT_IF_METHOD_FAILS(hr, m_imp.Initialize());
////////////////////////////////////////
m_fActAsCollection = true;
m_coll = pColl;
m_strDirectory = szDirectory;
__MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, RunInitFromDisk, NULL ));
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT CPCHSetOfHelpTopics::InitFromServer( /*[in]*/ LPCWSTR szServerName, /*[in]*/ CPCHCollection* pColl )
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::InitFromServer" );
HRESULT hr;
MPC::SmartLock<_ThreadModel> lock( NULL );
__MPC_PARAMCHECK_BEGIN(hr)
__MPC_PARAMCHECK_STRING_NOT_EMPTY(szServerName);
__MPC_PARAMCHECK_NOTNULL(pColl);
__MPC_PARAMCHECK_END();
Thread_Wait(); lock = this;
__MPC_EXIT_IF_METHOD_FAILS(hr, Close( true ));
__MPC_EXIT_IF_METHOD_FAILS(hr, m_imp.Initialize());
////////////////////////////////////////
m_fActAsCollection = true;
m_coll = pColl;
m_strServer = szServerName;
__MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, RunInitFromServer, NULL ));
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CPCHSetOfHelpTopics::get_SKU( /*[out, retval]*/ BSTR *pVal )
{
__HCP_BEGIN_PROPERTY_GET("CPCHSetOfHelpTopics::get_SKU",hr,pVal);
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetBSTR( m_inst.m_ths.m_strSKU.c_str(), pVal ));
__HCP_END_PROPERTY(hr);
}
STDMETHODIMP CPCHSetOfHelpTopics::get_Language( /*[out, retval]*/ long *pVal )
{
__HCP_BEGIN_PROPERTY_GET2("CPCHSetOfHelpTopics::get_Language",hr,pVal,m_inst.m_ths.GetLanguage());
__HCP_END_PROPERTY(hr);
}
STDMETHODIMP CPCHSetOfHelpTopics::get_DisplayName( /*[out, retval]*/ BSTR *pVal )
{
__HCP_BEGIN_PROPERTY_GET("CPCHSetOfHelpTopics::get_DisplayName",hr,pVal);
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetBSTR( m_inst.m_strDisplayName.c_str(), pVal ));
__HCP_END_PROPERTY(hr);
}
STDMETHODIMP CPCHSetOfHelpTopics::get_ProductID( /*[out, retval]*/ BSTR *pVal )
{
__HCP_BEGIN_PROPERTY_GET("CPCHSetOfHelpTopics::get_ProductID",hr,pVal);
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetBSTR( m_inst.m_strProductID.c_str(), pVal ));
__HCP_END_PROPERTY(hr);
}
STDMETHODIMP CPCHSetOfHelpTopics::get_Version( /*[out, retval]*/ BSTR *pVal )
{
__HCP_BEGIN_PROPERTY_GET("CPCHSetOfHelpTopics::get_Version",hr,pVal);
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetBSTR( m_inst.m_strVersion.c_str(), pVal ));
__HCP_END_PROPERTY(hr);
}
////////////////////////////////////////
STDMETHODIMP CPCHSetOfHelpTopics::get_Location( /*[out, retval]*/ BSTR *pVal )
{
__HCP_BEGIN_PROPERTY_GET("CPCHSetOfHelpTopics::get_Location",hr,pVal);
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetBSTR( m_inst.m_strHelpFiles.c_str(), pVal ));
__HCP_END_PROPERTY(hr);
}
////////////////////////////////////////
STDMETHODIMP CPCHSetOfHelpTopics::get_Exported( /*[out, retval]*/ VARIANT_BOOL *pVal )
{
__HCP_BEGIN_PROPERTY_GET2("CPCHSetOfHelpTopics::get_Exported",hr,pVal,m_inst.m_fExported);
__HCP_END_PROPERTY(hr);
}
STDMETHODIMP CPCHSetOfHelpTopics::put_Exported( /*[in]*/ VARIANT_BOOL newVal )
{
__HCP_BEGIN_PROPERTY_PUT("CPCHSetOfHelpTopics::put_Exported",hr);
CHECK_WRITE_PERMISSIONS();
FAIL_IF_RUNNING();
m_inst.m_fExported = (newVal == VARIANT_TRUE);
if(m_fInstalled)
{
Taxonomy::LockingHandle handle;
Taxonomy::InstalledInstanceIter it;
bool fFound;
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->GrabControl( handle ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->SKU_Find ( m_inst.m_ths, fFound, it ));
if(fFound)
{
it->m_inst.m_fExported = m_inst.m_fExported;
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->SKU_Updated( it ));
}
}
__HCP_END_PROPERTY(hr);
}
////////////////////////////////////////
STDMETHODIMP CPCHSetOfHelpTopics::put_onStatusChange( /*[in]*/ IDispatch* function )
{
__HCP_BEGIN_PROPERTY_PUT("CPCHSetOfHelpTopics::put_onStatusChange",hr);
m_sink_onStatusChange = function;
__HCP_END_PROPERTY(hr);
}
STDMETHODIMP CPCHSetOfHelpTopics::get_Status( /*[out, retval]*/ SHT_STATUS *pVal )
{
__HCP_BEGIN_PROPERTY_GET2("CPCHSetOfHelpTopics::get_Status",hr,pVal,m_shtStatus);
__HCP_END_PROPERTY(hr);
}
STDMETHODIMP CPCHSetOfHelpTopics::get_ErrorCode( /*[out, retval]*/ long *pVal )
{
__HCP_BEGIN_PROPERTY_GET2("CPCHSetOfHelpTopics::get_ErrorCode",hr,pVal,m_hrErrorCode);
__HCP_END_PROPERTY(hr);
}
////////////////////////////////////////
STDMETHODIMP CPCHSetOfHelpTopics::get_IsMachineHelp( /*[out, retval]*/ VARIANT_BOOL *pVal )
{
__HCP_BEGIN_PROPERTY_GET2("CPCHSetOfHelpTopics::get_IsMachineHelp",hr,pVal,VARIANT_FALSE);
if(m_fReadyForCommands)
{
if(m_ts.IsMachineHelp())
{
*pVal = VARIANT_TRUE;
}
}
__HCP_END_PROPERTY(hr);
}
STDMETHODIMP CPCHSetOfHelpTopics::get_IsInstalled( /*[out, retval]*/ VARIANT_BOOL *pVal )
{
__HCP_BEGIN_PROPERTY_GET2("CPCHSetOfHelpTopics::get_IsInstalled",hr,pVal,VARIANT_FALSE);
if(m_fReadyForCommands)
{
Taxonomy::LockingHandle handle;
Taxonomy::InstalledInstanceIter it;
bool fFound;
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->GrabControl( handle ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->SKU_Find ( m_inst.m_ths, fFound, it ));
if(fFound)
{
*pVal = VARIANT_TRUE;
}
}
__HCP_END_PROPERTY(hr);
}
STDMETHODIMP CPCHSetOfHelpTopics::get_CanInstall( /*[out, retval]*/ VARIANT_BOOL *pVal )
{
__HCP_BEGIN_PROPERTY_GET2("CPCHSetOfHelpTopics::get_CanInstall",hr,pVal,VARIANT_FALSE);
if(m_fReadyForCommands && SUCCEEDED(VerifyWritePermissions()))
{
Taxonomy::LockingHandle handle;
Taxonomy::InstalledInstanceIter it;
bool fFound;
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->GrabControl( handle ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->SKU_Find ( m_inst.m_ths, fFound, it ));
//
// You can install a SKU only if it's not already installed...
//
if(fFound == false)
{
*pVal = VARIANT_TRUE;
}
}
__HCP_END_PROPERTY(hr);
}
STDMETHODIMP CPCHSetOfHelpTopics::get_CanUninstall( /*[out, retval]*/ VARIANT_BOOL *pVal )
{
__HCP_BEGIN_PROPERTY_GET2("CPCHSetOfHelpTopics::get_CanUninstall",hr,pVal,VARIANT_FALSE);
if(m_fReadyForCommands && SUCCEEDED(VerifyWritePermissions()))
{
//
// You can only uninstall a SKU that is installed.
//
if(m_fInstalled)
{
Taxonomy::LockingHandle handle;
Taxonomy::InstalledInstanceIter it;
bool fFound;
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->GrabControl( handle ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->SKU_Find ( m_ts, fFound, it ));
//
// You cannot uninstall a SKU in use.
//
if(fFound && it->m_inst.m_fSystem == false && it->m_inst.m_fMUI == false && it->InUse() == false)
{
*pVal = VARIANT_TRUE;
}
}
}
__HCP_END_PROPERTY(hr);
}
////////////////////////////////////////
STDMETHODIMP CPCHSetOfHelpTopics::Install()
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::Install" );
HRESULT hr;
VARIANT_BOOL fRes;
MPC::SmartLock<_ThreadModel> lock( this );
FAIL_IF_RUNNING();
CHECK_WRITE_PERMISSIONS();
__MPC_EXIT_IF_METHOD_FAILS(hr, get_CanInstall( &fRes ));
if(fRes == VARIANT_FALSE)
{
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_ALREADY_EXISTS);
}
////////////////////
__MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, RunInstall, NULL ));
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
STDMETHODIMP CPCHSetOfHelpTopics::Uninstall()
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::Uninstall" );
HRESULT hr;
VARIANT_BOOL fRes;
MPC::SmartLock<_ThreadModel> lock( this );
FAIL_IF_RUNNING();
CHECK_WRITE_PERMISSIONS();
__MPC_EXIT_IF_METHOD_FAILS(hr, get_CanUninstall( &fRes ));
if(fRes == VARIANT_FALSE)
{
__MPC_SET_ERROR_AND_EXIT(hr, E_ACCESSDENIED);
}
////////////////////
__MPC_EXIT_IF_METHOD_FAILS(hr, Thread_Start( this, RunUninstall, NULL ));
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
STDMETHODIMP CPCHSetOfHelpTopics::Abort()
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::Abort" );
HRESULT hr;
Thread_Abort();
if(m_fActAsCollection)
{
MPC::SmartLock<_ThreadModel> lock( this );
long lCount;
long lPos;
__MPC_EXIT_IF_METHOD_FAILS(hr, m_coll->get_Count( &lCount ));
for(lPos=1; lPos<=lCount; lPos++)
{
CComVariant v;
CComPtr<IPCHSetOfHelpTopics> sku;
__MPC_EXIT_IF_METHOD_FAILS(hr, m_coll->get_Item( lPos, &v ));
__MPC_EXIT_IF_METHOD_FAILS(hr, v.ChangeType( VT_DISPATCH ));
__MPC_EXIT_IF_METHOD_FAILS(hr, v.pdispVal->QueryInterface( IID_IPCHSetOfHelpTopics, (LPVOID*)&sku ));
(void)sku->Abort();
}
}
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(S_OK);
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CPCHSetOfHelpTopics::GetClassID( /*[out]*/ CLSID *pClassID )
{
return E_NOTIMPL;
}
STDMETHODIMP CPCHSetOfHelpTopics::IsDirty()
{
return S_FALSE;
}
STDMETHODIMP CPCHSetOfHelpTopics::Load( /*[in]*/ IStream *pStm )
{
return m_inst.LoadFromStream( pStm );
}
STDMETHODIMP CPCHSetOfHelpTopics::Save( /*[in]*/ IStream *pStm, /*[in]*/ BOOL fClearDirty )
{
return m_inst.SaveToStream( pStm );
}
STDMETHODIMP CPCHSetOfHelpTopics::GetSizeMax( /*[out]*/ ULARGE_INTEGER *pcbSize )
{
return E_NOTIMPL;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
HRESULT CPCHSetOfHelpTopics::CreateIndex()
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::CreateIndex" );
HRESULT hr;
CComObject<HCUpdate::Engine>* hc = NULL;
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &hc ));
__MPC_EXIT_IF_METHOD_FAILS(hr, hc->SetSkuInfo( m_ts.GetSKU(), m_ts.GetLanguage() ));
__MPC_EXIT_IF_METHOD_FAILS(hr, hc->InternalCreateIndex( VARIANT_FALSE ));
hr = S_OK;
__HCP_FUNC_CLEANUP;
if(hc) hc->Release();
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////////////////////////////////////////////
HRESULT CPCHSetOfHelpTopics::RegisterPackage( /*[in]*/ const MPC::wstring& strFile ,
/*[in]*/ bool fBuiltin )
{
Taxonomy::PackageIter it;
bool fFound;
return Taxonomy::InstalledInstanceStore::s_GLOBAL->Package_Add( strFile.c_str(), NULL, fBuiltin ? &m_ts : NULL, /*fInsertAtTop*/false, fFound, it );
}
HRESULT CPCHSetOfHelpTopics::DirectInstall( /*[in]*/ Installer::Package& pkg ,
/*[in]*/ bool fSetup ,
/*[in]*/ bool fSystem ,
/*[in]*/ bool fMUI )
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::DirectInstall" );
HRESULT hr;
Taxonomy::LockingHandle handle;
Taxonomy::InstanceBase& base = pkg.GetData();
Taxonomy::InstanceIter itInstance;
Taxonomy::InstalledInstanceIter itSKU;
bool fFound;
if(fSetup) fSystem = true;
////////////////////////////////////////////////////////////////////////////////
//
// Phase One: get the database.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->GrabControl( handle ));
__MPC_EXIT_IF_METHOD_FAILS(hr, m_inst.InitializeFromBase( pkg.GetData(), fSystem, fMUI ));
__MPC_EXIT_IF_METHOD_FAILS(hr, PrepareSettings());
//
// Loop through the installed instances and remove any duplicates or, if during setup, any SYSTEM or MUI instances.
//
while(1)
{
Taxonomy::InstanceIterConst itBegin;
Taxonomy::InstanceIterConst itEnd;
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->Instance_GetList( itBegin, itEnd ));
for(;itBegin != itEnd; itBegin++)
{
const Taxonomy::Instance& inst = *itBegin;
if( inst.m_ths == m_inst.m_ths || // Duplicate
(fSetup && (inst.m_fSystem || inst.m_fMUI)) ) // System and MUI (setup-only)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->Instance_Find( inst.m_ths, fFound, itInstance ));
if(fFound)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->Instance_Remove( itInstance ));
//
// Uninstalling an instance could change the system settings, reapply them.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, m_inst.InitializeFromBase( pkg.GetData(), fSystem, fMUI ));
__MPC_EXIT_IF_METHOD_FAILS(hr, PrepareSettings());
break;
}
}
}
if(itBegin == itEnd) break;
}
////////////////////////////////////////////////////////////////////////////////
//
// Phase Two: clean up previous situation, set up permissions.
//
if(fSetup)
{
CPCHSecurityDescriptorDirect sdd;
MPC::wstring strGroupName;
//
// Remove old data from our directories.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_ROOT_HELPSVC_CONFIG , NULL, /*fRemove*/true, /*fRecreate*/true ));
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_ROOT_HELPSVC_DATACOLL , NULL, /*fRemove*/true, /*fRecreate*/true ));
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_ROOT_HELPSVC_LOGS , NULL, /*fRemove*/true, /*fRecreate*/true ));
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_ROOT_HELPSVC_TEMP , NULL, /*fRemove*/true, /*fRecreate*/true ));
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_ROOT_HELPSVC_OFFLINECACHE , NULL, /*fRemove*/true, /*fRecreate*/true ));
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_HELPSET_ROOT HC_HELPSET_SUB_INSTALLEDSKUS, NULL, /*fRemove*/true, /*fRecreate*/true ));
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_ROOT_HELPSVC_BATCH , NULL, /*fRemove*/false, /*fRecreate*/true ));
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::RemoveAndRecreateDirectory( HC_ROOT_HELPSVC_PKGSTORE, NULL, /*fRemove*/false, /*fRecreate*/true ));
//
// Change the ACL for system directories.
//
__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() ));
//
// Config, Database and Datacoll directories:
//
// LOCAL SYSTEM, Admin, Admins : any access.
//
__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, SVC::ChangeSD( sdd, HC_ROOT_HELPSVC_CONFIG ));
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, HC_ROOT_HELPSVC_DATACOLL ));
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, HC_ROOT_HELPSVC_PKGSTORE ));
//
// Binaries, System, Batch, Temp
//
// LOCAL SYSTEM, Admin, Admins : any access.
// Everyone : read and execute.
//
//
__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, HC_ROOT_HELPSVC_BATCH ));
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, HC_ROOT_HELPSVC_BINARIES ));
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, HC_ROOT_HELPSVC_LOGS ));
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, HC_ROOT_HELPSVC_OFFLINECACHE ));
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, HC_ROOT_HELPSVC_TEMP ));
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::ChangeSD( sdd, HC_HELPSET_ROOT HC_HELPSET_SUB_INSTALLEDSKUS ));
{
static const Installer::PURPOSE c_allowed[] =
{
Installer::PURPOSE_OTHER ,
Installer::PURPOSE_INVALID,
};
__MPC_EXIT_IF_METHOD_FAILS(hr, pkg.Install( c_allowed, NULL ));
}
}
////////////////////////////////////////////////////////////////////////////////
//
// Phase Three: register instance.
//
//
// Install instance.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->Instance_Add( pkg.GetFile(), m_inst, fFound, itInstance ));
//
// Add the SKU to the list of installed ones.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->SKU_Add( m_inst, fFound, itSKU ));
////////////////////////////////////////////////////////////////////////////////
//
// Phase Four: copy the Help files.
//
if(m_fConnectedToDisk)
{
MPC::WStringUCLookup mapLayout;
MPC::WStringUCLookup mapLayoutX86;
MPC::WStringUCLookup mapLayoutIA64;
MPC::WStringList lst;
MPC::WStringIterConst it;
MPC::wstring strDir_HelpFiles( m_inst.m_strHelpFiles ); MPC::SubstituteEnvVariables( strDir_HelpFiles );
MPC::wstring strFile_Database( m_inst.m_strDatabaseFile ); MPC::SubstituteEnvVariables( strFile_Database );
bool fX86 = (wcsstr( m_inst.m_ths.GetSKU(), L"_32" ) != NULL);
//
// Parse the layout.inf file, to create the map of CD files.
//
{
MPC::wstring strLayout( m_strDirectory ); strLayout += L"\\layout.inf";
__MPC_EXIT_IF_METHOD_FAILS(hr, ImpersonateCaller ( ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Local_ParseLayoutInf( strLayout.c_str(), &mapLayout, &mapLayoutX86, &mapLayoutIA64 ));
__MPC_EXIT_IF_METHOD_FAILS(hr, EndImpersonation ( ));
}
__MPC_EXIT_IF_METHOD_FAILS(hr, GetListOfFilesFromDatabase( strFile_Database, lst ));
for(it = lst.begin(); it != lst.end(); it++)
{
const MPC::wstring& strHelpFile = *it;
MPC::WStringUCLookupIterConst it2;
it2 = mapLayout.find( strHelpFile );
if(it2 == mapLayout.end())
{
if(fX86)
{
it2 = mapLayoutX86.find( strHelpFile ); if(it2 == mapLayoutX86.end()) continue;
}
else
{
it2 = mapLayoutIA64.find( strHelpFile ); if(it2 == mapLayoutIA64.end()) continue;
}
}
if(it2->second.empty() == false)
{
MPC::wstring strSrcFile;
MPC::wstring strDstFile;
strSrcFile = m_strDirectory ; strSrcFile += L"\\"; strSrcFile += it2->second;
strDstFile = strDir_HelpFiles; strDstFile += L"\\"; strDstFile += strHelpFile;
CHANGE_STATE( SHT_COPYING_FILES, CComBSTR( strHelpFile.c_str() ) );
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MakeDir( strDstFile ));
if(FAILED(hr = SVC::CopyOrExtractFileWhileImpersonating( strSrcFile.c_str(), strDstFile.c_str(), m_imp )))
{
if(hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) __MPC_FUNC_LEAVE;
continue;
}
EXIT_IF_ABORTED();
}
}
}
if(m_fConnectedToServer)
{
CComPtr<IPCHRemoteHelpContents> rhc;
CComVariant v;
MPC::WStringList lst;
MPC::WStringIterConst it;
__MPC_EXIT_IF_METHOD_FAILS(hr, m_svc->RemoteHelpContents( CComBSTR( m_inst.m_ths.GetSKU() ), m_inst.m_ths.GetLanguage(), &rhc ));
if(rhc == NULL) __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
__MPC_EXIT_IF_METHOD_FAILS(hr, rhc->get_ListOfFiles ( &v ));
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertSafeArrayToList( v, lst ));
for(it = lst.begin(); it != lst.end(); it++)
{
CComPtr<IUnknown> unkSrc;
CComBSTR bstrSrcFile( it->c_str() );
MPC::wstring strDstFile;
strDstFile = m_inst.m_strHelpFiles; MPC::SubstituteEnvVariables( strDstFile );
strDstFile += L"\\";
strDstFile += it->c_str();
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MakeDir( strDstFile ));
if(SUCCEEDED(hr = rhc->GetFile( bstrSrcFile, &unkSrc )))
{
CComQIPtr<IStream> streamSrc = unkSrc; // TransferData checks for NULL.
CComPtr<IStream> streamDst;
CHANGE_STATE( SHT_COPYING_FILES, bstrSrcFile );
__MPC_EXIT_IF_METHOD_FAILS(hr, SVC::OpenStreamForWrite( strDstFile.c_str(), &streamDst ));
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::BaseStream::TransferData( streamSrc, streamDst ));
}
else
{
if(hr != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) __MPC_FUNC_LEAVE;
}
}
}
////////////////////////////////////////////////////////////////////////////////
CHANGE_STATE( SHT_INSTALLING, NULL );
__MPC_EXIT_IF_METHOD_FAILS(hr, ScanBatch());
////////////////////////////////////////////////////////////////////////////////
CHANGE_STATE( SHT_INSTALLED, NULL );
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT CPCHSetOfHelpTopics::DirectUninstall( /*[in]*/ const Taxonomy::HelpSet* ths )
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::DirectUninstall" );
HRESULT hr;
Taxonomy::LockingHandle handle;
Taxonomy::InstanceIter itInstance;
bool fFound;
if(ths) m_ts = *ths;
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->GrabControl( handle ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->Instance_Find( m_ts, fFound, itInstance ));
if(fFound)
{
//
// System SKU cannot be uninstalled!!
//
if(itInstance->m_fSystem)
{
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_ACCESS_DENIED);
}
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->Instance_Remove( itInstance ));
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT CPCHSetOfHelpTopics::ScanBatch()
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::ScanBatch" );
HRESULT hr;
MPC::wstring strBatchPath( HC_ROOT_HELPSVC_BATCH ); MPC::SubstituteEnvVariables( strBatchPath );
MPC::FileSystemObject fso( strBatchPath.c_str() );
CComObject<HCUpdate::Engine>* hc = NULL;
Taxonomy::LockingHandle handle;
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &hc ));
{
Taxonomy::Logger& log = hc->GetLogger();
bool fLogStarted = false;
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->GrabControl( handle, &log ));
if(SUCCEEDED(fso.Scan()))
{
MPC::FileSystemObject::List fso_lst;
MPC::FileSystemObject::IterConst fso_it;
std::vector<MPC::wstringUC> vec;
std::vector<MPC::wstringUC>::iterator it;
//
// Delete any subdirectory.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, fso.EnumerateFolders( fso_lst ));
for(fso_it=fso_lst.begin(); fso_it != fso_lst.end(); fso_it++)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, (*fso_it)->Delete( true, false ));
}
fso_lst.clear();
//
// For each file, process it if it's a cabinet and then delete!
//
__MPC_EXIT_IF_METHOD_FAILS(hr, fso.EnumerateFiles( fso_lst ));
for(fso_it=fso_lst.begin(); fso_it != fso_lst.end(); fso_it++)
{
MPC::FileSystemObject* fsoFile = *fso_it;
MPC::wstring strPath;
LPCWSTR szExt;
__MPC_EXIT_IF_METHOD_FAILS(hr, fsoFile->get_Path( strPath ));
if((szExt = wcsrchr( strPath.c_str(), '.' )) && !_wcsicmp( szExt, c_CabExtension ))
{
vec.push_back( strPath );
}
}
std::sort( vec.begin(), vec.end() );
for(it=vec.begin(); it<vec.end(); it++)
{
MPC::wstring& strPath = *it;
Taxonomy::PackageIter it2;
bool fFound;
if(!fLogStarted)
{
(void)hc->StartLog();
fLogStarted = true;
}
hr = Taxonomy::InstalledInstanceStore::s_GLOBAL->Package_Add( strPath.c_str(), NULL, NULL, /*fInsertAtTop*/false, fFound, it2 );
if(FAILED(hr))
{
; // Ignore any failure....
}
}
//
// Remove files.
//
for(fso_it=fso_lst.begin(); fso_it != fso_lst.end(); fso_it++)
{
MPC::FileSystemObject* fsoFile = *fso_it;
__MPC_EXIT_IF_METHOD_FAILS(hr, (*fso_it)->Delete( true, false ));
}
fso_lst.clear();
}
handle.Release();
hr = hc->InternalUpdatePkg( NULL, /*fImpersonate*/false );
if(FAILED(hr))
{
; // Ignore any failure....
}
if(fLogStarted)
{
(void)hc->EndLog();
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
if(hc) hc->Release();
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////////////////////////////////////////////
HRESULT CPCHSetOfHelpTopics::RebuildSKU( /*[in]*/ const Taxonomy::HelpSet& ths )
{
__HCP_FUNC_ENTRY( "CPCHSetOfHelpTopics::RebuildSKU" );
HRESULT hr;
CComObject<HCUpdate::Engine>* hc = NULL;
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &hc ));
{
Taxonomy::LockingHandle handle;
bool fUseLogger = SUCCEEDED(hc->StartLog()); // It could be already in use.
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->GrabControl( handle, fUseLogger ? &(hc->GetLogger()) : NULL ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Taxonomy::InstalledInstanceStore::s_GLOBAL->State_InvalidateSKU( ths, /*fAlsoDatabase*/true ));
__MPC_EXIT_IF_METHOD_FAILS(hr, hc->InternalUpdatePkg( NULL, /*fImpersonate*/false ));
if(fUseLogger) (void)hc->EndLog();
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
if(hc) hc->Release();
__HCP_FUNC_EXIT(hr);
}