Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

546 lines
12 KiB

/******************************************************************************
Copyright (c) 2000 Microsoft Corporation
Module Name:
Favorites.cpp
Abstract:
This file contains the implementation of the CPCHFavorites class,
which is used to store the list of favorite contents.
Revision History:
Davide Massarenti (Dmassare) 05/10/2000
created
******************************************************************************/
#include "stdafx.h"
/////////////////////////////////////////////////////////////////////////////
const WCHAR c_szPersistFile[] = HC_ROOT_HELPCTR L"\\Favorites.stream";
static const DWORD l_dwVersion = 0x01564146; // FAV 01
/////////////////////////////////////////////////////////////////////////////
HRESULT CPCHFavorites::Entry::Init()
{
__HCP_FUNC_ENTRY( "CPCHFavorites::Entry::Init" );
HRESULT hr;
if(m_Data == NULL)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &m_Data ));
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT CPCHFavorites::Entry::Load( /*[in]*/ MPC::Serializer& streamIn )
{
__HCP_FUNC_ENTRY( "CPCHFavorites::Entry::Load" );
HRESULT hr;
__MPC_PARAMCHECK_BEGIN(hr)
__MPC_PARAMCHECK_NOTNULL(m_Data);
__MPC_PARAMCHECK_END();
__MPC_EXIT_IF_METHOD_FAILS(hr, m_Data->Load( streamIn ));
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT CPCHFavorites::Entry::Save( /*[in]*/ MPC::Serializer& streamOut )
{
__HCP_FUNC_ENTRY( "CPCHFavorites::Entry::Save" );
HRESULT hr;
if(m_Data)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, m_Data->Save( streamOut, true ));
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CPCHFavorites::CPCHFavorites()
{
__HCP_FUNC_ENTRY( "CPCHFavorites::CPCHFavorites" );
// List m_lstFavorites;
m_fLoaded = false; // bool m_fLoaded;
}
CPCHFavorites::~CPCHFavorites()
{
__HCP_FUNC_ENTRY( "CPCHFavorites::~CPCHFavorites" );
}
////////////////////
CPCHFavorites* CPCHFavorites::s_GLOBAL( NULL );
HRESULT CPCHFavorites::InitializeSystem()
{
if(s_GLOBAL) return S_OK;
return MPC::CreateInstance( &CPCHFavorites::s_GLOBAL );
}
void CPCHFavorites::FinalizeSystem()
{
if(s_GLOBAL)
{
s_GLOBAL->Release(); s_GLOBAL = NULL;
}
}
////////////////////////////////////////////////////////////////////////////////
HRESULT CPCHFavorites::FindEntry( /*[in]*/ IPCHHelpSessionItem* pItem, /*[out]*/ Iter& it )
{
__HCP_FUNC_ENTRY( "CPCHFavorites::FindEntry" );
HRESULT hr;
//
// First of all, look if the page is already present.
//
for(it = m_lstFavorites.begin(); it != m_lstFavorites.end(); it++)
{
if(it->m_Data == pItem)
{
__MPC_SET_ERROR_AND_EXIT(hr, S_OK);
}
}
hr = HRESULT_FROM_WIN32( ERROR_NOT_FOUND );
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////////////////////////////////////////////
HRESULT CPCHFavorites::Erase()
{
__HCP_FUNC_ENTRY( "CPCHFavorites::Erase" );
HRESULT hr;
MPC::SmartLock<_ThreadModel> lock(this);
CPCHFavorites_Parent::Erase();
m_lstFavorites.clear();
m_fLoaded = false;
hr = S_OK;
__HCP_FUNC_EXIT(hr);
}
HRESULT CPCHFavorites::Load()
{
__HCP_FUNC_ENTRY( "CPCHFavorites::Load" );
HRESULT hr;
MPC::SmartLock<_ThreadModel> lock(this);
HANDLE hFile = INVALID_HANDLE_VALUE;
if(m_fLoaded == false)
{
MPC::wstring szFile;
//
// Open file and read it.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetUserWritablePath( szFile, c_szPersistFile ));
__MPC_EXIT_IF_INVALID_HANDLE(hr, hFile, ::CreateFileW( szFile.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ));
{
MPC::Serializer_File streamReal( hFile );
MPC::Serializer_Buffering streamBuf ( streamReal );
DWORD dwVer;
__MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf >> dwVer); if(dwVer != l_dwVersion) __MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
while(1)
{
Iter it = m_lstFavorites.insert( m_lstFavorites.end() );
__MPC_EXIT_IF_METHOD_FAILS(hr, it->Init());
if(FAILED(it->Load( streamBuf )))
{
m_lstFavorites.erase( it );
break;
}
}
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
if(FAILED(hr)) Erase();
if(hFile != INVALID_HANDLE_VALUE) ::CloseHandle( hFile );
m_fLoaded = true; // Anyway, flag the object as loaded.
__HCP_FUNC_EXIT(S_OK); // Never fail.
}
HRESULT CPCHFavorites::Save()
{
__HCP_FUNC_ENTRY( "CPCHFavorites::Save" );
HRESULT hr;
MPC::SmartLock<_ThreadModel> lock(this);
HANDLE hFile = INVALID_HANDLE_VALUE;
if(m_fLoaded)
{
MPC::wstring szFile;
Iter it;
//
// Create the new file.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::GetUserWritablePath( szFile, c_szPersistFile ));
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MakeDir ( szFile ));
__MPC_EXIT_IF_INVALID_HANDLE(hr, hFile, ::CreateFileW( szFile.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ));
{
MPC::Serializer_File streamReal( hFile );
MPC::Serializer_Buffering streamBuf ( streamReal );
__MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf << l_dwVersion);
for(it = m_lstFavorites.begin(); it != m_lstFavorites.end(); it++)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, it->Save( streamBuf ));
}
__MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf.Flush());
}
__MPC_EXIT_IF_METHOD_FAILS(hr, Synchronize( false ));
__MPC_EXIT_IF_METHOD_FAILS(hr, CPCHHelpCenterExternal::s_GLOBAL->Events().FireEvent_FavoritesUpdate());
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
if(hFile != INVALID_HANDLE_VALUE)
{
::FlushFileBuffers( hFile );
::CloseHandle ( hFile );
}
__HCP_FUNC_EXIT(hr);
}
/////////////////////////////////////////////////////////////////////////////
HRESULT CPCHFavorites::Synchronize( /*[in]*/ bool fForce )
{
__HCP_FUNC_ENTRY( "CPCHFavorites::Synchronize" );
HRESULT hr;
MPC::SmartLock<_ThreadModel> lock(this);
if(fForce) Erase();
__MPC_EXIT_IF_METHOD_FAILS(hr, Load());
if(m_fLoaded)
{
Iter it;
const Taxonomy::HelpSet& ths = CPCHHelpCenterExternal::s_GLOBAL->UserSettings()->THS();
//
// We actually have two lists, the real one, m_lstFavorites, and the enumerator's one, m_coll.
// So, whenever the real one changes, we need to rebuild the one held by the enumerator.
//
CPCHFavorites_Parent::Erase();
for(it = m_lstFavorites.begin(); it != m_lstFavorites.end(); it++)
{
CPCHHelpSessionItem* data = it->m_Data;
if(data->SameSKU( ths ))
{
__MPC_EXIT_IF_METHOD_FAILS(hr, AddItem( data ));
}
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
/////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CPCHFavorites::IsDuplicate( /*[in]*/ BSTR bstrURL ,
/*[out, retval]*/ VARIANT_BOOL *pfDup )
{
__HCP_FUNC_ENTRY( "CPCHFavorites::IsDuplicate" );
HRESULT hr;
MPC::SmartLock<_ThreadModel> lock(this);
const Taxonomy::HelpSet& ths = CPCHHelpCenterExternal::s_GLOBAL->UserSettings()->THS();
Iter it;
__MPC_PARAMCHECK_BEGIN(hr)
__MPC_PARAMCHECK_POINTER_AND_SET(pfDup,VARIANT_FALSE);
__MPC_PARAMCHECK_END();
__MPC_EXIT_IF_METHOD_FAILS(hr, Load());
for(it = m_lstFavorites.begin(); it != m_lstFavorites.end(); it++)
{
CPCHHelpSessionItem* data = it->m_Data;
if(data->SameSKU( ths ) &&
data->SameURL( bstrURL ) )
{
*pfDup = VARIANT_TRUE;
break;
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
STDMETHODIMP CPCHFavorites::Add( /*[in]*/ BSTR bstrURL ,
/*[in,optional]*/ VARIANT vTitle ,
/*[out, retval]*/ IPCHHelpSessionItem* *ppItem )
{
__HCP_FUNC_ENTRY( "CPCHFavorites::Add" );
HRESULT hr;
MPC::SmartLock<_ThreadModel> lock(this);
CPCHProxy_IPCHUserSettings2* us = CPCHHelpCenterExternal::s_GLOBAL->UserSettings();
CPCHHelpSessionItem* data;
CComBSTR bstrTitleInfer;
BSTR bstrTitle;
Iter it;
__MPC_PARAMCHECK_BEGIN(hr)
__MPC_PARAMCHECK_STRING_NOT_EMPTY(bstrURL);
__MPC_PARAMCHECK_END();
__MPC_EXIT_IF_METHOD_FAILS(hr, Load());
if(vTitle.vt == VT_BSTR)
{
bstrTitle = vTitle.bstrVal;
}
else
{
__MPC_EXIT_IF_METHOD_FAILS(hr, CPCHHelpCenterExternal::s_GLOBAL->HelpSession()->LookupTitle( bstrURL, bstrTitleInfer, /*fUseCache*/false ));
bstrTitle = bstrTitleInfer;
}
if(bstrTitle == NULL || bstrTitle[0] == 0) bstrTitle = bstrURL; // We need some sort of title.
it = m_lstFavorites.insert( m_lstFavorites.end() );
__MPC_EXIT_IF_METHOD_FAILS(hr, it->Init());
data = it->m_Data;
data->put_THS( us->THS() );
__MPC_EXIT_IF_METHOD_FAILS(hr, data->put_URL ( bstrURL ));
__MPC_EXIT_IF_METHOD_FAILS(hr, data->put_Title( bstrTitle ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Save());
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
STDMETHODIMP CPCHFavorites::Rename( /*[in]*/ BSTR bstrTitle ,
/*[in]*/ IPCHHelpSessionItem* pItem )
{
__HCP_FUNC_ENTRY( "CPCHFavorites::Rename" );
HRESULT hr;
MPC::SmartLock<_ThreadModel> lock(this);
Iter it;
__MPC_PARAMCHECK_BEGIN(hr)
__MPC_PARAMCHECK_STRING_NOT_EMPTY(bstrTitle);
__MPC_PARAMCHECK_END();
__MPC_EXIT_IF_METHOD_FAILS(hr, Load());
__MPC_EXIT_IF_METHOD_FAILS(hr, FindEntry( pItem, it ));
__MPC_EXIT_IF_METHOD_FAILS(hr, it->m_Data->put_Title( bstrTitle ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Save());
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
STDMETHODIMP CPCHFavorites::Move( /*[in]*/ IPCHHelpSessionItem* pInsertBefore ,
/*[in]*/ IPCHHelpSessionItem* pItem )
{
__HCP_FUNC_ENTRY( "CPCHFavorites::Move" );
HRESULT hr;
MPC::SmartLock<_ThreadModel> lock(this);
CPCHHelpSessionItem* data = NULL;
Iter itBefore;
Iter itOld;
Iter itNew;
__MPC_EXIT_IF_METHOD_FAILS(hr, Load());
//
// If an element is passed, then we insert before it, otherwise we insert at the end.
//
if(pInsertBefore)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, FindEntry( pInsertBefore, itBefore ));
}
else
{
itBefore = m_lstFavorites.end();
}
__MPC_EXIT_IF_METHOD_FAILS(hr, FindEntry( pItem, itOld ));
//
// Trying to move the element on itself.
//
if(itOld == itBefore)
{
__MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG);
}
//
// Save pointer to data, erase old item, create a new one and restore pointer.
//
data = itOld->m_Data; data->AddRef();
m_lstFavorites.erase ( itOld );
itNew = m_lstFavorites.insert( itBefore );
itNew->m_Data = data; data = NULL;
__MPC_EXIT_IF_METHOD_FAILS(hr, Save());
hr = S_OK;
__HCP_FUNC_CLEANUP;
MPC::Release( data );
__HCP_FUNC_EXIT(hr);
}
STDMETHODIMP CPCHFavorites::Delete( /*[in]*/ IPCHHelpSessionItem* pItem )
{
__HCP_FUNC_ENTRY( "CPCHFavorites::Delete" );
HRESULT hr;
MPC::SmartLock<_ThreadModel> lock(this);
Iter it;
__MPC_EXIT_IF_METHOD_FAILS(hr, Load());
__MPC_EXIT_IF_METHOD_FAILS(hr, FindEntry( pItem, it ));
m_lstFavorites.erase( it );
__MPC_EXIT_IF_METHOD_FAILS(hr, Synchronize( false ));
__MPC_EXIT_IF_METHOD_FAILS(hr, Save());
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}