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.
 
 
 
 
 
 

494 lines
13 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: I E N U M I D L . C P P
//
// Contents: IEnumIDList implementation for CConnectionFolderEnum
//
// Notes:
//
// Author: jeffspr 22 Sep 1997
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "foldinc.h" // Standard shell\folder includes
#include "ncnetcon.h"
#include "webview.h"
//+---------------------------------------------------------------------------
//
// Member: CConnectionFolderEnum::CConnectionFolderEnum
//
// Purpose: Constructor for the enumerator
//
// Arguments:
// (none)
//
// Returns:
//
// Author: jeffspr 18 Mar 1998
//
// Notes:
//
CConnectionFolderEnum::CConnectionFolderEnum()
{
TraceFileFunc(ttidShellFolderIface);
m_pidlFolder.Clear();
m_dwFlags = 0;
m_fTray = FALSE;
m_dwEnumerationType = CFCOPT_ENUMALL; // all connection types
}
//+---------------------------------------------------------------------------
//
// Function: CConnectionFolderEnum
//
// Purpose: Destructor for the enumerator. Standard cleanup.
//
// Arguments:
// (none)
//
// Returns:
//
// Author: jeffspr 18 Mar 1998
//
// Notes:
//
CConnectionFolderEnum::~CConnectionFolderEnum()
{
TraceFileFunc(ttidShellFolderIface);
m_pidlFolder.Clear();
}
//+---------------------------------------------------------------------------
//
// Function: CConnectionFolderEnum::PidlInitialize
//
// Purpose: Initialization for the enumerator object
//
// Arguments:
// fTray [in] Are we owned by the tray
// pidlFolder [in] Pidl for the folder itself
// dwEnumerationType [in] Enumeration type (inbound/outbound/all)
//
// Returns:
//
// Author: jeffspr 18 Mar 1998
//
// Notes:
//
VOID CConnectionFolderEnum::PidlInitialize(
BOOL fTray,
const PCONFOLDPIDLFOLDER& pidlFolder,
DWORD dwEnumerationType)
{
TraceFileFunc(ttidShellFolderIface);
NETCFG_TRY
m_fTray = fTray;
m_pidlFolder = pidlFolder;
m_dwEnumerationType = dwEnumerationType;
NETCFG_CATCH_AND_RETHROW
}
//+---------------------------------------------------------------------------
//
// Member: CConnectionFolderEnum::CreateInstance
//
// Purpose: Create an instance of the CConnectionFolderEnum object, and
// returns the requested interface
//
// Arguments:
// riid [in] Interface requested
// ppv [out] Pointer to receive the requested interface
//
// Returns: Standard OLE HRESULT
//
// Author: jeffspr 5 Nov 1997
//
// Notes:
//
HRESULT CConnectionFolderEnum::CreateInstance(
REFIID riid,
void** ppv)
{
TraceFileFunc(ttidShellFolderIface);
HRESULT hr = E_OUTOFMEMORY;
CConnectionFolderEnum * pObj = NULL;
pObj = new CComObject <CConnectionFolderEnum>;
if (pObj)
{
// Do the standard CComCreator::CreateInstance stuff.
//
pObj->SetVoid (NULL);
pObj->InternalFinalConstructAddRef ();
hr = pObj->FinalConstruct ();
pObj->InternalFinalConstructRelease ();
if (SUCCEEDED(hr))
{
hr = pObj->QueryInterface (riid, ppv);
}
if (FAILED(hr))
{
delete pObj;
}
}
TraceHr(ttidError, FAL, hr, FALSE, "CConnectionFolderEnum::CreateInstance");
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: CConnectionFolderEnum::Next
//
// Purpose: Retrieves the specified number of item identifiers in the
// enumeration sequence and advances the current position
// by the number of items retrieved.
//
// Arguments:
// celt [] Max number requested
// rgelt [] Array to fill
// pceltFetched [] Return count for # filled.
//
// Returns: S_OK if successful, S_FALSE if there are no more items
// in the enumeration sequence, or an OLE-defined error value
// otherwise.
//
// Author: jeffspr 5 Nov 1997
//
// Notes:
//
STDMETHODIMP CConnectionFolderEnum::Next(
ULONG celt,
LPITEMIDLIST * rgelt,
ULONG * pceltFetched)
{
TraceFileFunc(ttidShellFolderIface);
HRESULT hr = S_OK;
Assert(celt >= 1);
Assert(rgelt);
Assert(pceltFetched || (celt == 1));
// If the caller asks for the fetch count, zero it out for now.
//
if (pceltFetched)
{
*pceltFetched = 0;
}
// Init the output list pointer
//
*rgelt = NULL;
// If there's not currently a list, build one.
//
if (m_apidl.empty())
{
hr = Reset();
// This will have returned either S_FALSE (no wizard? weird!), an
// error (meaning creating the wizard failed), or S_OK, meaning
// that (at least) the wizard creation succeeded. Enum of the connections
// failing will get filtered by Reset().
}
if (SUCCEEDED(hr))
{
// If there are NOW items in the list
//
if (!m_apidl.empty() )
{
BOOL fMatchFound = FALSE;
// Check that we've set the current pointer to at least the root
//
// Normalize the return code
hr = S_OK;
while ((S_OK == hr) && !fMatchFound)
{
// If there are no remaining entries, return S_FALSE.
//
if ( m_iterPidlCurrent == m_apidl.end() )
{
hr = S_FALSE;
}
else
{
const PCONFOLDPIDL& pcfp = *m_iterPidlCurrent;
// Else, Return the first entry, then increment the current
// pointer
//
Assert(!pcfp.empty());
// Check to see if we want to return this type, based on
// the enumeration type & connection type. The wizard
// should always be included.
//
if ( WIZARD_NOT_WIZARD != pcfp->wizWizard )
{
if (HrIsWebViewEnabled() == S_OK)
{
m_iterPidlCurrent++; // skip over this item
continue;
}
else
{
fMatchFound = TRUE;
}
}
else
{
switch(m_dwEnumerationType)
{
case CFCOPT_ENUMALL:
fMatchFound = TRUE;
break;
case CFCOPT_ENUMINCOMING:
fMatchFound = (pcfp->dwCharacteristics & NCCF_INCOMING_ONLY);
break;
case CFCOPT_ENUMOUTGOING:
fMatchFound = !(pcfp->dwCharacteristics & NCCF_INCOMING_ONLY);
break;
}
}
// If we've found one that needn't be filtered out,
// then fill in the return param, etc.
//
if (fMatchFound)
{
// Copy the pidl for return
//
rgelt[0] = m_iterPidlCurrent->TearOffItemIdList();
if (!rgelt[0])
{
hr = E_OUTOFMEMORY;
}
else
{
// If they requested a return count, fill it in.
//
if (pceltFetched)
{
*pceltFetched = 1;
}
// ISSUE:
// IsValidPIDL is debug code. However, we're doing this in release mode until we
// find the bug from NTRAID#NTBUG9-125787-2000/07/26-deonb.
#ifdef DBG_VALIDATE_PIDLS
if (!IsValidPIDL(rgelt[0]))
{
return E_ABORT;
}
#endif
}
}
// Move the pointer to the next pidl in the list.
//
m_iterPidlCurrent++;
}
}
}
else
{
// There are no items in the list, return S_FALSE
//
hr = S_FALSE;
}
}
#ifdef DBG
if (pceltFetched)
{
TraceTag(ttidShellFolderIface, "IEnumIDList::Next generated PIDL: 0x%08x", rgelt[0]);
}
#endif
TraceHr(ttidError, FAL, hr, (S_FALSE == hr), "CConnectionFolderEnum::Next");
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: CConnectionFolderEnum::Skip
//
// Purpose: Skips over the specified number of elements in the
// enumeration sequence.
//
// Arguments:
// celt [in] Number of item identifiers to skip.
//
// Returns: Returns S_OK if successful, or an OLE-defined error
// value otherwise.
//
// Author: jeffspr 5 Nov 1997
//
// Notes:
//
STDMETHODIMP CConnectionFolderEnum::Skip(
ULONG celt)
{
TraceFileFunc(ttidShellFolderIface);
HRESULT hr = S_OK;
NYI("CConnectionFolderEnum::Skip");
// Currently, do nothing
//
TraceHr(ttidError, FAL, hr, FALSE, "CConnectionFolderEnum::Skip");
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CConnectionFolderEnum::Reset
//
// Purpose: Returns to the beginning of the enumeration sequence. For us,
// this means do all of the actual enumeration
//
// Arguments:
// (none)
//
// Returns: Returns S_OK if successful, or an OLE-defined error
// value otherwise.
//
// Author: jeffspr 5 Nov 1997
//
// Notes:
//
STDMETHODIMP CConnectionFolderEnum::Reset()
{
TraceFileFunc(ttidShellFolderIface);
HRESULT hr = S_OK;
// If there's already a list, free it and rebuild.
//
if (!m_apidl.empty())
{
m_apidl.clear();
m_iterPidlCurrent = m_apidl.end();
}
// Yes, I know that the code below looks strange, as both cases do the same thing,
// but it makes it a bit easier to debug, and it makes the comments more obvious.
//
hr = HrRetrieveConManEntries();
if (SUCCEEDED(hr))
{
// Normalize the return code. HrRetrieveConManEntries... may have returned
// S_FALSE, meaning that there we no connections (fine).
//
hr = S_OK;
m_iterPidlCurrent = m_apidl.begin();
}
else
{
// Actually, we're still going to return noerror here after tracing the problem,
// as we don't want to keep the enumerator from returning an error
// if the wizard is present (no connections, but hey, better than nothing).
//
TraceHr(ttidError, FAL, hr, FALSE,
"CConnectionsFolderEnum failed in call to HrRetrieveConManEntries");
hr = S_FALSE;
}
TraceHr(ttidError, FAL, hr, FALSE, "CConnectionFolderEnum::Reset");
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: CConnectionFolderEnum::Clone
//
// Purpose: Creates a new item enumeration object with the same contents
// and state as the current one.
//
// Arguments:
// ppenum [out] Return a clone of the current internal PIDL
//
// Returns: Returns S_OK if successful, or an OLE-defined error
// value otherwise.
//
// Author: jeffspr 5 Nov 1997
//
// Notes:
//
STDMETHODIMP CConnectionFolderEnum::Clone(
IEnumIDList ** ppenum)
{
TraceFileFunc(ttidShellFolderIface);
NYI("CConnectionFolderEnum::Clone");
*ppenum = NULL;
return E_NOTIMPL;
}
//+---------------------------------------------------------------------------
//
// Member: CConnectionFolderEnum::HrRetrieveConManEntries
//
// Purpose: Enumerate all connections from the ConnectionManagers, and
// add them to our IDL.
//
// Arguments:
// (none)
//
// Returns:
//
// Author: jeffspr 8 Oct 1997
//
// Notes:
//
HRESULT CConnectionFolderEnum::HrRetrieveConManEntries()
{
TraceFileFunc(ttidShellFolderIface);
HRESULT hr = S_OK;
NETCFG_TRY
PCONFOLDPIDLVEC apidlNew;
hr = g_ccl.HrRetrieveConManEntries(apidlNew);
if (SUCCEEDED(hr))
{
m_apidl.clear();
m_apidl = apidlNew;
}
TraceHr(ttidError, FAL, hr, FALSE, "CConnectionFolder::HrRetrieveConManEntries");
NETCFG_CATCH(hr)
return hr;
}