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.
 
 
 
 
 
 

413 lines
10 KiB

/******************************************************************************
Copyright (c) 1999 Microsoft Corporation
Module Name:
QueryResultCollection.cpp
Abstract:
This file contains the implementation of the CPCHQueryResultCollection class,
which is used to store results of queries.
Revision History:
Davide Massarenti (Dmassare) 07/26/99
created
******************************************************************************/
#include "stdafx.h"
////////////////////////////////////////////////////////////////////////////////
static const DWORD l_dwVersion = 0x02425251; // QRC 02
////////////////////////////////////////////////////////////////////////////////
struct ElementHolder
{
CPCHQueryResult* obj;
long pos;
};
class ElementSorter
{
CPCHQueryResultCollection::SortMode m_mode;
public:
ElementSorter( /*[in]*/ CPCHQueryResultCollection::SortMode mode ) : m_mode(mode) {}
bool operator()( ElementHolder& left, ElementHolder& right )
{
const CPCHQueryResult::Payload& leftData = left .obj->GetData();
const CPCHQueryResult::Payload& rightData = right.obj->GetData();
int iCmp = 0;
//
// Priority is sorted from highest to lowest, so negate iCmp;
//
switch(m_mode)
{
case CPCHQueryResultCollection::SORT_BYCONTENTTYPE: iCmp = ( leftData.m_lType - rightData.m_lType ); break;
case CPCHQueryResultCollection::SORT_BYPRIORITY : iCmp = -( leftData.m_lPriority - rightData.m_lPriority ); break;
case CPCHQueryResultCollection::SORT_BYURL : iCmp = MPC::StrICmp( leftData.m_bstrTopicURL, rightData.m_bstrTopicURL ); break;
case CPCHQueryResultCollection::SORT_BYTITLE : iCmp = MPC::StrICmp( leftData.m_bstrTitle , rightData.m_bstrTitle ); break;
}
if(iCmp < 0) return true;
if(iCmp > 0) return false;
return (left.pos < right.pos);
}
};
////////////////////////////////////////////////////////////////////////////////
CPCHQueryResultCollection::CPCHQueryResultCollection()
{
// List m_results;
}
CPCHQueryResultCollection::~CPCHQueryResultCollection()
{
Erase();
}
////////////////////////////////////////
HRESULT CPCHQueryResultCollection::MakeLocalCopyIfPossible( /*[in]*/ IPCHCollection* pRemote ,
/*[out]*/ IPCHCollection* *pLocal )
{
__HCP_FUNC_ENTRY( "CPCHQueryResultCollection::MakeLocalCopyIfPossible" );
HRESULT hr;
CComPtr<CPCHQueryResultCollection> pColl;
CComPtr<IPersistStream> persistRemote;
CComPtr<IPersistStream> persistLocal;
CComPtr<IStream> stream;
MPC::Serializer_IStream ser;
__MPC_PARAMCHECK_BEGIN(hr)
__MPC_PARAMCHECK_NOTNULL(pRemote);
__MPC_PARAMCHECK_POINTER_AND_SET(pLocal,NULL);
__MPC_PARAMCHECK_END();
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &pColl ));
__MPC_EXIT_IF_METHOD_FAILS(hr, pRemote->QueryInterface( IID_IPersistStream, (void**)&persistRemote ));
__MPC_EXIT_IF_METHOD_FAILS(hr, pColl ->QueryInterface( IID_IPersistStream, (void**)&persistLocal ));
__MPC_EXIT_IF_METHOD_FAILS(hr, ser.GetStream ( &stream ));
//
// Convert from stream to live object.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, persistRemote->Save( stream, FALSE ));
__MPC_EXIT_IF_METHOD_FAILS(hr, ser.Reset ( )); // Rewind stream.
__MPC_EXIT_IF_METHOD_FAILS(hr, persistLocal ->Load( stream ));
*pLocal = pColl.Detach();
hr = S_OK;
__HCP_FUNC_CLEANUP;
//
// In case of failure, use the remote copy...
//
if(FAILED(hr) && pRemote && pLocal)
{
(*pLocal = pRemote)->AddRef();
}
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////
STDMETHODIMP CPCHQueryResultCollection::GetClassID( /*[out]*/ CLSID *pClassID )
{
return E_NOTIMPL;
}
STDMETHODIMP CPCHQueryResultCollection::IsDirty()
{
return S_FALSE;
}
STDMETHODIMP CPCHQueryResultCollection::Load( /*[in]*/ IStream *pStm )
{
MPC::Serializer_IStream stream ( pStm );
MPC::Serializer_Buffering stream2( stream );
return pStm ? Load( stream2 ) : E_POINTER;
}
STDMETHODIMP CPCHQueryResultCollection::Save( /*[in]*/ IStream *pStm, /*[in]*/ BOOL fClearDirty )
{
HRESULT hr;
MPC::Serializer_IStream stream ( pStm );
MPC::Serializer_Buffering stream2( stream );
if(pStm)
{
if(SUCCEEDED(hr = Save( stream2 ))) hr = stream2.Flush();
}
else
{
hr = E_POINTER;
}
return hr;
}
STDMETHODIMP CPCHQueryResultCollection::GetSizeMax( /*[out]*/ ULARGE_INTEGER *pcbSize )
{
return E_NOTIMPL;
}
////////////////////////////////////////
int CPCHQueryResultCollection::Size() const
{
return m_results.size();
}
void CPCHQueryResultCollection::Erase()
{
CPCHBaseCollection::Erase();
MPC::ReleaseAll( m_results );
}
HRESULT CPCHQueryResultCollection::Load( /*[in]*/ MPC::Serializer& streamIn )
{
__HCP_FUNC_ENTRY( "CPCHQueryResultCollection::Load" );
HRESULT hr;
CComPtr<CPCHQueryResult> item;
DWORD dwVer;
int iCount;
Erase();
if(FAILED(streamIn >> dwVer ) || dwVer != l_dwVersion) __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
if(FAILED(streamIn >> iCount) ) __MPC_SET_ERROR_AND_EXIT(hr, S_OK);
for(int i=0; i<iCount; i++)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, CreateItem( &item ));
__MPC_EXIT_IF_METHOD_FAILS(hr, item->Load( streamIn ));
item.Release();
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT CPCHQueryResultCollection::Save( /*[in]*/ MPC::Serializer& streamOut ) const
{
__HCP_FUNC_ENTRY( "CPCHQueryResultCollection::Save" );
HRESULT hr;
Iter it;
DWORD dwVer = l_dwVersion;
int iCount = m_results.size();
__MPC_EXIT_IF_METHOD_FAILS(hr, streamOut << dwVer );
__MPC_EXIT_IF_METHOD_FAILS(hr, streamOut << iCount );
for(it = m_results.begin(); it != m_results.end(); it++)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, (*it)->Save( streamOut ));
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
////////////////////////////////////////////////////////////////////////////////
HRESULT CPCHQueryResultCollection::CreateItem( /*[out]*/ CPCHQueryResult* *item )
{
__HCP_FUNC_ENTRY( "CPCHQueryResultCollection::CreateItem" );
HRESULT hr;
CComPtr<CPCHQueryResult> hpcqr;
__MPC_PARAMCHECK_BEGIN(hr)
__MPC_PARAMCHECK_POINTER_AND_SET(item,NULL);
__MPC_PARAMCHECK_END();
//
// Create a new item and link it to the system.
//
__MPC_EXIT_IF_METHOD_FAILS(hr, MPC::CreateInstance( &hpcqr )); (*item = hpcqr)->AddRef();
__MPC_EXIT_IF_METHOD_FAILS(hr, AddItem( hpcqr ));
m_results.push_back( hpcqr.Detach() );
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT CPCHQueryResultCollection::GetItem( /*[in]*/ long lPos, /*[out]*/ CPCHQueryResult* *item )
{
__HCP_FUNC_ENTRY( "CPCHQueryResultCollection::GetItem" );
HRESULT hr;
Iter it;
__MPC_PARAMCHECK_BEGIN(hr)
__MPC_PARAMCHECK_POINTER_AND_SET(item,NULL);
__MPC_PARAMCHECK_END();
it = m_results.begin();
while(1)
{
if(it == m_results.end())
{
__MPC_SET_ERROR_AND_EXIT(hr, E_FAIL);
}
if(lPos-- == 0) break;
it++;
}
(*item = *it)->AddRef();
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
/////////////////////////////////////////////////////////////////////////////
HRESULT CPCHQueryResultCollection::LoadFromCache( /*[in]*/ IStream* stream )
{
__HCP_FUNC_ENTRY( "CPCHQueryResultCollection::LoadFromCache" );
HRESULT hr;
MPC::Serializer_IStream streamReal( stream );
MPC::Serializer_Buffering streamBuf ( streamReal );
Erase();
__MPC_EXIT_IF_METHOD_FAILS(hr, Load( streamBuf ));
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT CPCHQueryResultCollection::SaveToCache( /*[in]*/ IStream* stream ) const
{
__HCP_FUNC_ENTRY( "CPCHQueryResultCollection::SaveToCache" );
HRESULT hr;
MPC::Serializer_IStream streamReal( stream );
MPC::Serializer_Buffering streamBuf ( streamReal );
__MPC_EXIT_IF_METHOD_FAILS(hr, Save( streamBuf ));
__MPC_EXIT_IF_METHOD_FAILS(hr, streamBuf.Flush());
hr = S_OK;
__HCP_FUNC_CLEANUP;
__HCP_FUNC_EXIT(hr);
}
HRESULT CPCHQueryResultCollection::Sort( /*[in]*/ SortMode mode, /*[in]*/ int iLimit )
{
__HCP_FUNC_ENTRY( "CPCHQueryResultCollection::Sort" );
HRESULT hr;
ElementHolder* ptr;
ElementHolder* rgBuf = NULL;
int iSize = m_results.size();
int i;
if(iSize > 1)
{
ElementSorter sorted( mode );
Iter it;
__MPC_EXIT_IF_ALLOC_FAILS(hr, rgBuf, new ElementHolder[iSize]);
for(i=0, ptr=rgBuf, it=m_results.begin(); i<iSize && it!=m_results.end(); i++, ptr++, it++)
{
CPCHQueryResult* obj = *it;
ptr->obj = obj; obj->AddRef();
ptr->pos = i;
}
std::sort( rgBuf, ptr, sorted );
if(iLimit < 0 || iLimit > iSize) iLimit = iSize;
Erase();
for(i=0, ptr=rgBuf; i<iLimit; i++, ptr++)
{
__MPC_EXIT_IF_METHOD_FAILS(hr, AddItem( ptr->obj ));
m_results.push_back( ptr->obj ); ptr->obj = NULL;
}
}
hr = S_OK;
__HCP_FUNC_CLEANUP;
if(rgBuf)
{
for(i=0, ptr=rgBuf; i<iSize; i++, ptr++)
{
if(ptr->obj) ptr->obj->Release();
}
delete [] rgBuf;
}
__HCP_FUNC_EXIT(hr);
}