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.
 
 
 
 
 
 

731 lines
21 KiB

/** Copyright (c) 2000 Microsoft Corporation
******************************************************************************
** Module Name:
**
** NewsHeadlines.cpp
**
** Astract:
**
** Implementation of CNewsHeadlines
**
** Author:
**
** Martha Arellano (t-alopez) 03-Oct-2000
**
**
** Revision History:
**
** Martha Arellano (t-alopez) 05-Oct-2000 Added timestamp, frequency and link
** to xml file format
**
** Added get_Provider_Frequency() to interface
**
** 06-Oct-2000 Added Delete_Provider(nBlockIndex) to interface
**
** Added get_Provider_URL(nBlockIndex) to interface
**
** 11-Oct-2000 Added date in newsver and timestamp in provider
**
** 15-Nov-2000 Added Provider Icon, Position and Headline Expires attr
**
** 07-Dec-2000 Added Get_UpdateHeadlines to get_Stream()
**
******************************************************************************
**/
#include "stdafx.h"
/////////////////////////////////////////////////////////////////////////////
// CONFIG MAP
/////////////////////////////////////////////////////////////////////////////
/*
<NEWSHEADLINES TIMESTAMP="10/3/2000" DATE="10/4/2000">
<NEWSBLOCK PROVIDER="Windows Family" LINK="http://www.microsoft.com/family" ICON="logo.gif"
POSITION="horizontal" FREQUENCY=5 TIMESTAMP="10/4/2000" >
<HEADLINE ICON="" TITLE="Visit the Windows Family home page for current headlines"
LINK="http://www.microsoft.com/windows" DESCRIPTION="Some description (if necessary)" />
</NEWSBLOCK>
</NEWSHEADLINES>
*/
CFG_BEGIN_FIELDS_MAP(News::Headlines::Headline)
CFG_ATTRIBUTE( L"ICON" , wstring, m_strIcon ),
CFG_ATTRIBUTE( L"TITLE" , wstring, m_strTitle ),
CFG_ATTRIBUTE( L"LINK" , wstring, m_strLink ),
CFG_ATTRIBUTE( L"DESCRIPTION" , wstring, m_strDescription ),
CFG_ATTRIBUTE( L"EXPIRES" , DATE_CIM, m_dtExpires ),
CFG_ATTRIBUTE( L"UPDATEHEADLINES" , bool , m_fUpdateHeadlines ),
CFG_END_FIELDS_MAP()
CFG_BEGIN_CHILD_MAP(News::Headlines::Headline)
CFG_END_CHILD_MAP()
DEFINE_CFG_OBJECT(News::Headlines::Headline, L"HEADLINE")
DEFINE_CONFIG_METHODS__NOCHILD(News::Headlines::Headline)
////////////////////
CFG_BEGIN_FIELDS_MAP(News::Headlines::Newsblock)
CFG_ATTRIBUTE( L"PROVIDER" , wstring , m_strProvider ),
CFG_ATTRIBUTE( L"LINK" , wstring , m_strLink ),
CFG_ATTRIBUTE( L"ICON" , wstring , m_strIcon ),
CFG_ATTRIBUTE( L"POSITION" , wstring , m_strPosition ),
CFG_ATTRIBUTE( L"TIMESTAMP", DATE_CIM, m_dtTimestamp ),
CFG_ATTRIBUTE( L"FREQUENCY", int , m_nFrequency ),
CFG_END_FIELDS_MAP()
CFG_BEGIN_CHILD_MAP(News::Headlines::Newsblock)
CFG_CHILD(News::Headlines::Headline)
CFG_END_CHILD_MAP()
DEFINE_CFG_OBJECT(News::Headlines::Newsblock,L"NEWSBLOCK")
DEFINE_CONFIG_METHODS_CREATEINSTANCE_SECTION(News::Headlines::Newsblock,tag,defSubType)
if(tag == _cfg_table_tags[0])
{
defSubType = &(*(m_vecHeadlines.insert( m_vecHeadlines.end() )));
return S_OK;
}
DEFINE_CONFIG_METHODS_SAVENODE_SECTION(News::Headlines::Newsblock,xdn)
hr = MPC::Config::SaveList( m_vecHeadlines, xdn );
DEFINE_CONFIG_METHODS_END(News::Headlines::Newsblock)
////////////////////
CFG_BEGIN_FIELDS_MAP(News::Headlines)
CFG_ATTRIBUTE( L"TIMESTAMP" , DATE_CIM, m_dtTimestamp ),
CFG_ATTRIBUTE( L"DATE" , DATE_CIM, m_dtDate ),
CFG_END_FIELDS_MAP()
CFG_BEGIN_CHILD_MAP(News::Headlines)
CFG_CHILD(News::Headlines::Newsblock)
CFG_END_CHILD_MAP()
DEFINE_CFG_OBJECT(News::Headlines,L"NEWSHEADLINES")
DEFINE_CONFIG_METHODS_CREATEINSTANCE_SECTION(News::Headlines,tag,defSubType)
if(tag == _cfg_table_tags[0])
{
defSubType = &(*(m_vecNewsblocks.insert( m_vecNewsblocks.end() )));
return S_OK;
}
DEFINE_CONFIG_METHODS_SAVENODE_SECTION(News::Headlines,xdn)
hr = MPC::Config::SaveList( m_vecNewsblocks, xdn );
DEFINE_CONFIG_METHODS_END(News::Headlines)
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// Convert a date from CIM format to number of milliseconds since January 1, 1970.
//
static HRESULT local_ConvertDate( /*[in]*/ MPC::XmlUtil& xml ,
/*[in]*/ LPCWSTR szTag ,
/*[in]*/ LPCWSTR szAttrib ,
/*[in]*/ IXMLDOMNode* pxdnNode )
{
__HCP_FUNC_ENTRY( "local_ConvertDate" );
HRESULT hr;
bool fFound;
MPC::wstring strValue;
DATE dDate;
DATE dDateBase;
CComVariant v;
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetAttribute( szTag, szAttrib, strValue, fFound, pxdnNode ));
if(fFound)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertStringToDate( strValue, dDate, /*fGMT*/false, /*fCIM*/true, 0 ));
{
SYSTEMTIME st;
st.wYear = (WORD)1970;
st.wMonth = (WORD)1;
st.wDay = (WORD)1;
st.wHour = (WORD)0;
st.wMinute = (WORD)0;
st.wSecond = (WORD)0;
st.wMilliseconds = (WORD)0;
::SystemTimeToVariantTime( &st, &dDateBase );
}
v = (dDate - dDateBase) * 86400.0 * 1000.0; __MPC_EXIT_IF_METHOD_FAILS(hr, v.ChangeType( VT_BSTR ));
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.ModifyAttribute( szTag, szAttrib, v.bstrVal, fFound, pxdnNode ));
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
/////////////////////////////////////////////////////////////////////////////
News::Headlines::Headline::Headline()
{
// MPC::wstring m_strIcon;
// MPC::wstring m_strTitle;
// MPC::wstring m_strLink;
// MPC::wstring m_strDescription;
m_dtExpires = 0; // DATE m_dtExpires;
m_fUpdateHeadlines = false; // bool m_fUpdateHeadlines;
}
News::Headlines::Headline::Headline( /*[in]*/ const MPC::wstring& strIcon ,
/*[in]*/ const MPC::wstring& strTitle ,
/*[in]*/ const MPC::wstring& strLink ,
/*[in]*/ const MPC::wstring& strDescription ,
/*[in]*/ DATE dtExpires ,
/*[in]*/ bool fUpdateHeadlines)
{
m_strIcon = strIcon; // MPC::wstring m_strIcon;
m_strTitle = strTitle; // MPC::wstring m_strTitle;
m_strLink = strLink; // MPC::wstring m_strLink;
m_strDescription = strDescription; // MPC::wstring m_strDescription;
m_dtExpires = dtExpires; // DATE m_dtExpires;
m_fUpdateHeadlines = fUpdateHeadlines; // bool m_fUpdateHeadlines;
}
////////////////////
News::Headlines::Newsblock::Newsblock()
{
// MPC::wstring m_strProvider;
// MPC::wstring m_strLink;
// MPC::wstring m_strIcon;
// MPC::wstring m_strPosition;
m_dtTimestamp = 0; // DATE m_dtTimestamp;
m_nFrequency = 0; // int m_nFrequency;
//
// HeadlineList m_vecHeadlines;
}
//
// Routine Description:
//
// Determines if its time to update or not, the newsblock
//
// Arguments:
//
// nBlockIndex Newsblock index
//
// Return Value:
//
// returns TRUE if its time to update the newsblock
//
//
bool News::Headlines::Newsblock::TimeToUpdate()
{
if(m_nFrequency)
{
DATE dtNow = MPC::GetLocalTime() - m_nFrequency;
// then we check if its time to download newsver.xml
if(dtNow >= m_dtTimestamp) return true;
}
return false;
}
HRESULT News::Headlines::Newsblock::Copy( /*[in]*/ const Newsblock& block ,
/*[in]*/ const MPC::wstring& strLangSKU ,
/*[in]*/ int nProvID )
{
__HCP_FUNC_ENTRY( "News::Headlines::Newsblock::Copy" );
HRESULT hr;
//
// copy the member variables
*this = block;
//
// set the time we are modifying the Newsblock
m_dtTimestamp = MPC::GetLocalTime();
// check when we have incomplete information and we won't download the icon
// when there is no Icon
// when there is no Provider's name
// when the Icon URL is missing a '/'
if(!m_strIcon .empty() &&
!m_strProvider.empty() )
{
MPC::wstring szEnd;
GetFileName( m_strIcon, szEnd);
if(!szEnd.empty())
{
MPC::wstring strPath = HC_HELPSET_ROOT HC_HELPSET_SUB_SYSTEM L"\\News\\";
MPC::wstring strOthers;
MPC::wstring strImgPath;
WCHAR wzProvID[64];
bool fUseIcon = false;
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::SubstituteEnvVariables( strPath ));
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::MakeDir ( strPath ));
// add Lang and SKU
strOthers = strLangSKU + L'_';
strOthers += _itow( nProvID, wzProvID, 10 ); // add Provider's ID
strOthers += L'_';
strOthers += szEnd; // add the icon's name
// form the path to this image file
strImgPath = strPath;
strImgPath += strOthers;
// we check if we have that file already
if(MPC::FileSystemObject::IsFile( strImgPath.c_str() ))
{
fUseIcon = true;
}
else
{
CComPtr<IStream> streamIn;
// then, we download the new image
if(SUCCEEDED(News::LoadFileFromServer( m_strIcon.c_str(), streamIn )))
{
CComPtr<MPC::FileStream> streamImg;
if(SUCCEEDED(MPC::CreateInstance ( &streamImg )) &&
SUCCEEDED(streamImg->InitForWrite( strImgPath.c_str() )) )
{
if(SUCCEEDED(MPC::BaseStream::TransferData( streamIn, streamImg )))
{
fUseIcon = true;
}
}
}
}
if(fUseIcon)
{
m_strIcon = L"hcp://system/news/";
m_strIcon += strOthers;
}
else
{
m_strIcon .erase();
m_strPosition.erase();
}
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
void News::Headlines::Newsblock::GetFileName( MPC::wstring strURL, MPC::wstring& strFileName )
{
MPC::wstring::size_type pos;
if(!strURL.empty())
{
if((pos = strURL.find_last_of( '/' )) == strURL.length() - 1)
{
strURL.resize( strURL.length() - 1 );
pos = strURL.find_last_of( '/' );
}
if(pos != MPC::wstring::npos)
{
strFileName.assign( strURL, pos, strURL.length() - pos );
// Go thro the string and delete all invalid characters
pos = 0;
while(!strFileName.empty() && pos < strFileName.length())
{
if((strFileName[pos] == '\\') || (strFileName[pos] == '/') || (strFileName[pos] == ':') ||
(strFileName[pos] == '*') || (strFileName[pos] == '?') || (strFileName[pos] == '"') ||
(strFileName[pos] == '<') || (strFileName[pos] == '>') || (strFileName[pos] == '|'))
{
strFileName.erase( pos, 1 );
}
else
{
pos++;
}
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
News::Headlines::Headlines()
{
m_dtTimestamp = 0; // DATE m_dtTimestamp;
m_dtDate = 0; // DATE m_dtDate;
//
// NewsblockList m_vecNewsblocks;
}
//
// Routine Description:
//
// Clears the News::Headlines Class' variables and lists, so it can be loaded againg
//
// Arguments:
//
// None
//
//
HRESULT News::Headlines::Clear()
{
__HCP_FUNC_ENTRY( "News::Headlines::Clear" );
HRESULT hr;
m_dtTimestamp = 0;
m_dtDate = 0;
m_vecNewsblocks.clear();
hr = S_OK;
__HCP_FUNC_EXIT(hr);
}
//
// Routine Description:
//
// Loads the specified file and validates it (from the local disk or from the server)
//
// Arguments:
//
// strPath the path for the news headlines file (or newsblock)
//
//
HRESULT News::Headlines::Load( /*[in]*/ const MPC::wstring& strPath )
{
__HCP_FUNC_ENTRY( "News::Headlines::Load" );
HRESULT hr;
CComPtr<IStream> stream;
// we load the file
__MPC_EXIT_IF_METHOD_FAILS(hr, News::LoadXMLFile( strPath.c_str(), stream ));
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::Config::LoadStream( this, stream ));
//validate file
//
if(m_vecNewsblocks.size() == 0)
{
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_INVALID_DATA);
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
//
// Routine Description:
//
// The newsheadlines file is saved in the local user disk
//
// the timestamp is updated
//
// Arguments:
//
// strPath the path and name of the newsheadlines file
//
//
HRESULT News::Headlines::Save( /*[in]*/ const MPC::wstring& strPath )
{
__HCP_FUNC_ENTRY( "News::Headlines::Save" );
HRESULT hr;
// the date is updated every time it is saved
m_dtDate = MPC::GetLocalTime();
// we save the file
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::Config::SaveFile( this, strPath.c_str() ));
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
//
// Routine Description:
//
// Reloads the newsheadlines file and then returns it as a stream
//
// We check the Expires attribute in each headline, if it has expired then its deleted
// if a provider loses all its headlines, then the provider (newsblock) is deleted too
//
// If all Newsblocks are deleted, we return ERROR_INVALID_DATA, to display the offline message
//
// We save the changes in the News Headlines file
//
// Arguments:
//
// strPath path for the newsheadlines file
//
// Return Value:
//
// pVal IStream with the newsheadlines xml content
//
//
HRESULT News::Headlines:: get_Stream( /*[in ]*/ long lLCID ,
/*[in ]*/ const MPC::wstring& strSKU ,
/*[in ]*/ const MPC::wstring& strPath ,
/*[out]*/ IUnknown* *pVal )
{
__HCP_FUNC_ENTRY( "News::Headlines::get_Stream" );
HRESULT hr;
MPC::XmlUtil xml;
UpdateHeadlines uhUpdate;
CComPtr<IStream> stream;
bool fModified = false;
DATE dtNow = MPC::GetLocalTime();
NewsblockIter itNewsblock;
// we clear the object
Clear();
// we load the News Headlines file
__MPC_EXIT_IF_METHOD_FAILS(hr, News::LoadXMLFile( strPath.c_str(), stream ));
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::Config::LoadStream( this, stream ));
// ****** delete expired headlines
// for each newsblock
itNewsblock = m_vecNewsblocks.begin();
while(itNewsblock != m_vecNewsblocks.end())
{
Newsblock& nb = *itNewsblock;
HeadlineIter itHeadline = nb.m_vecHeadlines.begin();
while(itHeadline != nb.m_vecHeadlines.end())
{
// check each headline if it has expired
if(itHeadline->m_dtExpires < dtNow)
{
// if expired, deleted
nb.m_vecHeadlines.erase( itHeadline );
fModified = true;
}
else
{
// we go to the next headline
itHeadline++;
}
}
// if the Newsblock has no headlines valid
if(itNewsblock->m_vecHeadlines.empty())
{
// we delete it
m_vecNewsblocks.erase( itNewsblock );
}
else
{
// we go to the next Newsblock
itNewsblock++;
}
}
if(fModified)
{
// if we deleted headlines or newsblocks we save the News Headlines file
__MPC_EXIT_IF_METHOD_FAILS(hr, Save( strPath ));
}
// if there aren't Newsblocks left, we return an error
if(m_vecNewsblocks.empty())
{
__MPC_SET_WIN32_ERROR_AND_EXIT(hr, ERROR_INVALID_DATA);
}
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::Config::SaveXmlUtil( this, xml ));
__MPC_EXIT_IF_METHOD_FAILS(hr, local_ConvertDate( xml, NULL, L"TIMESTAMP", NULL ));
__MPC_EXIT_IF_METHOD_FAILS(hr, local_ConvertDate( xml, NULL, L"DATE" , NULL ));
__MPC_EXIT_IF_METHOD_FAILS(hr, xml.SaveAsStream( pVal ));
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
//
// Routine Description:
//
// Checks to see if there atleast a single Newsblock which has an icon
//
// Arguments:
//
// None
//
// Return Value:
//
// true or false
//
bool News::Headlines::CheckIfImagesExist()
{
// Note that this function does NOT check to see if a headline has an icon. This is because headline icons are not
// being processed (even though the ICON attribute exists in the HEADLINE tag).
NewsblockIter itNewsblock;
itNewsblock = m_vecNewsblocks.begin();
while(itNewsblock != m_vecNewsblocks.end())
{
if(!itNewsblock->m_strIcon.empty())
{
return true;
}
else
{
itNewsblock++;
}
}
return false;
}
//
// Routine Description:
//
// Sets the News Headlines timestamp to the current time
// This method should be called when all the newsblocks are retrieved
//
// Arguments:
//
// None
//
// Return Value:
//
// None
//
//
void News::Headlines::set_Timestamp()
{
m_dtTimestamp = MPC::GetLocalTime();
}
News::Headlines::Newsblock* News::Headlines::get_Newsblock( /*[in]*/ size_t nBlockIndex )
{
if(nBlockIndex >= m_vecNewsblocks.size()) return NULL;
return &(m_vecNewsblocks[ nBlockIndex ]);
}
////////////////////////////////////////
//
// Routine Description:
//
// From the provided newsblock this method gets the first two headlines
// and adds it to the first newsblock
//
// Arguments:
//
// None
//
// Return Value:
//
// None
//
//
HRESULT News::Headlines::AddHomepageHeadlines( /*[in]*/ const Headlines::Newsblock& block )
{
__HCP_FUNC_ENTRY( "News::Headlines::AddHomepageHeadlines" );
HRESULT hr;
size_t nIndex = 0;
NewsblockIter itNewsblock;
HeadlineIter itHeadline;
// Add 2 headlines to the first newsblock
itNewsblock = m_vecNewsblocks.begin();
while ( itNewsblock && ( ++nIndex <= NUMBER_OF_OEM_HEADLINES ) )
{
// If a headline already exists delete it before adding a new one
if ( nIndex < itNewsblock->m_vecHeadlines.size() )
{
itHeadline = itNewsblock->m_vecHeadlines.begin();
std::advance( itHeadline, nIndex );
// Delete the existing headline before adding it
itNewsblock->m_vecHeadlines.erase( itHeadline );
// Add the headline
itNewsblock->m_vecHeadlines.insert( itHeadline, block.m_vecHeadlines[nIndex - 1] );
}
else
{
// Insert the headline to the end of the list
itNewsblock->m_vecHeadlines.insert( itNewsblock->m_vecHeadlines.end(), block.m_vecHeadlines[nIndex - 1] );
}
}
hr = S_OK;
return S_OK;
}
////////////////////////////////////////
HRESULT News::Headlines::AddNewsblock( /*[in]*/ const Headlines::Newsblock& block ,
/*[in]*/ const MPC::wstring& strLangSKU )
{
__HCP_FUNC_ENTRY( "News::Headlines::AddNewsblock" );
HRESULT hr;
NewsblockIter itNewsblock;
itNewsblock = m_vecNewsblocks.insert( m_vecNewsblocks.end() );
__MPC_EXIT_IF_METHOD_FAILS(hr, itNewsblock->Copy( block, strLangSKU, m_vecNewsblocks.size()-1 ));
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}