635 lines
19 KiB
C++
635 lines
19 KiB
C++
|
#include "shellprv.h"
|
||
|
#pragma hdrstop
|
||
|
#include "shellids.h" // new help ids are stored here
|
||
|
#include "findfilter.h"
|
||
|
#include "netview.h"
|
||
|
#include "prop.h"
|
||
|
#include "ids.h"
|
||
|
|
||
|
STDAPI CNetwork_EnumSearches(IShellFolder2 *psf2, IEnumExtraSearch **ppenum);
|
||
|
|
||
|
class CNetFindEnum;
|
||
|
|
||
|
class CNetFindFilter : public IFindFilter
|
||
|
{
|
||
|
friend CNetFindEnum;
|
||
|
|
||
|
public:
|
||
|
CNetFindFilter();
|
||
|
|
||
|
// IUnknown
|
||
|
STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
|
||
|
STDMETHODIMP_(ULONG) AddRef();
|
||
|
STDMETHODIMP_(ULONG) Release();
|
||
|
|
||
|
// IFindFilter
|
||
|
STDMETHODIMP GetStatusMessageIndex(UINT uContext, UINT *puMsgIndex);
|
||
|
STDMETHODIMP GetFolderMergeMenuIndex(UINT *puBGMainMergeMenu, UINT *puBGPopupMergeMenu);
|
||
|
STDMETHODIMP FFilterChanged();
|
||
|
STDMETHODIMP GenerateTitle(LPTSTR *ppszTile, BOOL fFileName);
|
||
|
STDMETHODIMP PrepareToEnumObjects(HWND hwnd, DWORD * pdwFlags);
|
||
|
STDMETHODIMP ClearSearchCriteria();
|
||
|
STDMETHODIMP EnumObjects(IShellFolder *psf, LPCITEMIDLIST pidlStart, DWORD grfFlags, int iColSort,
|
||
|
LPTSTR pszProgressText, IRowsetWatchNotify *prwn, IFindEnum **ppfindenum);
|
||
|
STDMETHODIMP GetColumnsFolder(IShellFolder2 **ppsf);
|
||
|
STDMETHODIMP_(BOOL) MatchFilter(IShellFolder *psf, LPCITEMIDLIST pidl);
|
||
|
STDMETHODIMP SaveCriteria(IStream * pstm, WORD fCharType);
|
||
|
STDMETHODIMP RestoreCriteria(IStream * pstm, int cCriteria, WORD fCharType);
|
||
|
STDMETHODIMP DeclareFSNotifyInterest(HWND hwndDlg, UINT uMsg);
|
||
|
STDMETHODIMP GetColSaveStream(WPARAM wParam, IStream **ppstm);
|
||
|
STDMETHODIMP GenerateQueryRestrictions(LPWSTR *ppwszQuery, DWORD *pdwGQRFlags);
|
||
|
STDMETHODIMP ReleaseQuery();
|
||
|
STDMETHODIMP UpdateField(LPCWSTR pszField, VARIANT vValue);
|
||
|
STDMETHODIMP ResetFieldsToDefaults();
|
||
|
STDMETHODIMP GetItemContextMenu(HWND hwndOwner, IFindFolder* pff, IContextMenu** ppcm);
|
||
|
STDMETHODIMP GetDefaultSearchGUID(IShellFolder2 *psf2, LPGUID lpGuid);
|
||
|
STDMETHODIMP EnumSearches(IShellFolder2 *psf2, LPENUMEXTRASEARCH *ppenum);
|
||
|
STDMETHODIMP GetSearchFolderClassId(LPGUID lpGuid);
|
||
|
STDMETHODIMP GetNextConstraint(VARIANT_BOOL fReset, BSTR *pName, VARIANT *pValue, VARIANT_BOOL *pfFound);
|
||
|
STDMETHODIMP GetQueryLanguageDialect(ULONG * pulDialect);
|
||
|
STDMETHODIMP GetWarningFlags(DWORD *pdwWarningFlags) { return E_NOTIMPL; }
|
||
|
|
||
|
protected:
|
||
|
|
||
|
LPTSTR _pszCompName; // the one we do compares with
|
||
|
TCHAR _szUserInputCompName[MAX_PATH]; // User input
|
||
|
|
||
|
private:
|
||
|
~CNetFindFilter();
|
||
|
LONG _cRef;
|
||
|
|
||
|
LPITEMIDLIST _pidlStart; // Where to start the search from.
|
||
|
|
||
|
// Data associated with the file name.
|
||
|
};
|
||
|
|
||
|
CNetFindFilter::CNetFindFilter() : _cRef(1)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
CNetFindFilter::~CNetFindFilter()
|
||
|
{
|
||
|
ILFree(_pidlStart);
|
||
|
Str_SetPtr(&_pszCompName, NULL);
|
||
|
}
|
||
|
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::QueryInterface(REFIID riid, void **ppv)
|
||
|
{
|
||
|
static const QITAB qit[] = {
|
||
|
QITABENT(CNetFindFilter, IFindFilter),
|
||
|
{ 0 },
|
||
|
};
|
||
|
return QISearch(this, qit, riid, ppv);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CNetFindFilter::AddRef()
|
||
|
{
|
||
|
return InterlockedIncrement(&_cRef);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CNetFindFilter::Release()
|
||
|
{
|
||
|
ASSERT( 0 != _cRef );
|
||
|
ULONG cRef = InterlockedDecrement(&_cRef);
|
||
|
if ( 0 == cRef )
|
||
|
{
|
||
|
delete this;
|
||
|
}
|
||
|
return cRef;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::GetStatusMessageIndex(UINT uContext, UINT *puMsgIndex)
|
||
|
{
|
||
|
// Currently context is not used
|
||
|
*puMsgIndex = IDS_COMPUTERSFOUND;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::GetFolderMergeMenuIndex(UINT *puBGMainMergeMenu, UINT *puBGPopupMergeMenu)
|
||
|
{
|
||
|
*puBGPopupMergeMenu = 0;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::GetItemContextMenu(HWND hwndOwner, IFindFolder* pff, IContextMenu **ppcm)
|
||
|
{
|
||
|
return CFindItem_Create(hwndOwner, pff, ppcm);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::GetDefaultSearchGUID(IShellFolder2 *psf2, GUID *pGuid)
|
||
|
{
|
||
|
*pGuid = SRCID_SFindComputer;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::EnumSearches(IShellFolder2 *psf2, IEnumExtraSearch **ppenum)
|
||
|
{
|
||
|
return CNetwork_EnumSearches(psf2, ppenum);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::GetSearchFolderClassId(LPGUID lpGuid)
|
||
|
{
|
||
|
*lpGuid = CLSID_ComputerFindFolder;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::GetNextConstraint(VARIANT_BOOL fReset, BSTR *pName, VARIANT *pValue, VARIANT_BOOL *pfFound)
|
||
|
{
|
||
|
*pName = NULL;
|
||
|
*pfFound = FALSE;
|
||
|
VariantClear(pValue);
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::GetQueryLanguageDialect(ULONG * pulDialect)
|
||
|
{
|
||
|
if (pulDialect)
|
||
|
*pulDialect = 0;
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::FFilterChanged()
|
||
|
{
|
||
|
// Currently not saving so who cares?
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::GenerateTitle(LPTSTR *ppszTitle, BOOL fFileName)
|
||
|
{
|
||
|
// Now lets construct the message from the resource
|
||
|
*ppszTitle = ShellConstructMessageString(HINST_THISDLL,
|
||
|
MAKEINTRESOURCE(IDS_FIND_TITLE_COMPUTER), fFileName ? TEXT(" #") : TEXT(":"));
|
||
|
|
||
|
return *ppszTitle ? S_OK : E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::ClearSearchCriteria()
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
STDAPI CreateDefaultComputerFindFilter(IFindFilter **ppff)
|
||
|
{
|
||
|
*ppff = new CNetFindFilter;
|
||
|
return *ppff ? S_OK : E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
|
||
|
class CNetFindEnum : public IFindEnum
|
||
|
{
|
||
|
public:
|
||
|
CNetFindEnum(CNetFindFilter *pnff, IShellFolder *psf, LPTSTR pszDisplayText, DWORD grfFlags, LPITEMIDLIST pidlStart);
|
||
|
|
||
|
// IUnknown
|
||
|
STDMETHODIMP QueryInterface(REFIID riid, void **ppv);
|
||
|
STDMETHODIMP_(ULONG) AddRef();
|
||
|
STDMETHODIMP_(ULONG) Release();
|
||
|
|
||
|
// IFindEnum
|
||
|
STDMETHODIMP Next(LPITEMIDLIST *ppidl, int *pcObjectSearched, int *pcFoldersSearched, BOOL *pfContinue, int *pState);
|
||
|
STDMETHODIMP Skip(int celt) { return E_NOTIMPL; }
|
||
|
STDMETHODIMP Reset() { return E_NOTIMPL; }
|
||
|
STDMETHODIMP StopSearch() { return E_NOTIMPL; }
|
||
|
STDMETHODIMP_(BOOL) FQueryIsAsync();
|
||
|
STDMETHODIMP GetAsyncCount(DBCOUNTITEM *pdwTotalAsync, int *pnPercentComplete, BOOL *pfQueryDone);
|
||
|
STDMETHODIMP GetItemIDList(UINT iItem, LPITEMIDLIST *ppidl);
|
||
|
STDMETHODIMP GetItemID(UINT iItem, DWORD *puWorkID);
|
||
|
STDMETHODIMP SortOnColumn(UINT iCol, BOOL fAscending);
|
||
|
|
||
|
private:
|
||
|
~CNetFindEnum();
|
||
|
HRESULT _FindCompByUNCName(LPITEMIDLIST *ppidl, int *piState);
|
||
|
|
||
|
LONG _cRef;
|
||
|
IFindFolder *_pff; // find folder
|
||
|
|
||
|
// Stuff to use in the search
|
||
|
DWORD _grfFlags; // Flags that control things like recursion
|
||
|
|
||
|
// filter info...
|
||
|
LPTSTR _pszDisplayText; // Place to write feadback text into
|
||
|
CNetFindFilter *_pnetf; // Pointer to the net filter...
|
||
|
|
||
|
// enumeration state
|
||
|
|
||
|
IShellFolder *_psfEnum; // Pointer to shell folder for the object.
|
||
|
IEnumIDList *_penum; // Enumerator in use.
|
||
|
LPITEMIDLIST _pidlFolder; // The idlist of the currently processing
|
||
|
LPITEMIDLIST _pidlStart; // Pointer to the starting point.
|
||
|
int _iFolder; // Which folder are we adding items for?
|
||
|
BOOL _fFindUNC; // Find UNC special case
|
||
|
int _iPassCnt; // Used to control when to reiterat...
|
||
|
};
|
||
|
|
||
|
|
||
|
CNetFindEnum::CNetFindEnum(CNetFindFilter *pnff, IShellFolder *psf, LPTSTR pszDisplayText, DWORD grfFlags, LPITEMIDLIST pidlStart) :
|
||
|
_cRef(1), _pnetf(pnff), _pszDisplayText(pszDisplayText), _grfFlags(grfFlags), _iFolder(-1)
|
||
|
{
|
||
|
ASSERT(0 == _iPassCnt);
|
||
|
|
||
|
_pnetf->AddRef();
|
||
|
|
||
|
psf->QueryInterface(IID_PPV_ARG(IFindFolder, &_pff));
|
||
|
ASSERT(_pff);
|
||
|
|
||
|
if (pidlStart)
|
||
|
SHILClone(pidlStart, &_pidlStart);
|
||
|
else
|
||
|
SHGetDomainWorkgroupIDList(&_pidlStart);
|
||
|
|
||
|
// special case to force us to search for specific UNC
|
||
|
_fFindUNC = _pnetf->_pszCompName && (_pnetf->_pszCompName[0] == TEXT('\\'));
|
||
|
}
|
||
|
|
||
|
CNetFindEnum::~CNetFindEnum()
|
||
|
{
|
||
|
// Release any open enumerator and open IShell folder we may have.
|
||
|
if (_psfEnum)
|
||
|
_psfEnum->Release();
|
||
|
if (_penum)
|
||
|
_penum->Release();
|
||
|
|
||
|
_pff->Release();
|
||
|
_pnetf->Release();
|
||
|
|
||
|
ILFree(_pidlStart);
|
||
|
ILFree(_pidlFolder);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindEnum::QueryInterface(REFIID riid, void **ppv)
|
||
|
{
|
||
|
static const QITAB qit[] = {
|
||
|
// QITABENT(CNetFindEnum, IFindEnum),
|
||
|
{ 0 },
|
||
|
};
|
||
|
return QISearch(this, qit, riid, ppv);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CNetFindEnum::AddRef()
|
||
|
{
|
||
|
return InterlockedIncrement(&_cRef);
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(ULONG) CNetFindEnum::Release()
|
||
|
{
|
||
|
ASSERT( 0 != _cRef );
|
||
|
ULONG cRef = InterlockedDecrement(&_cRef);
|
||
|
if ( 0 == cRef )
|
||
|
{
|
||
|
delete this;
|
||
|
}
|
||
|
return cRef;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::EnumObjects(IShellFolder *psf, LPCITEMIDLIST pidlStart,
|
||
|
DWORD grfFlags, int iColSort, LPTSTR pszDisplayText,
|
||
|
IRowsetWatchNotify *prsn, IFindEnum **ppfindenum)
|
||
|
{
|
||
|
// We need to construct the iterator
|
||
|
*ppfindenum = new CNetFindEnum(this, psf, pszDisplayText, grfFlags, _pidlStart);
|
||
|
return *ppfindenum ? S_OK : E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::PrepareToEnumObjects(HWND hwnd, DWORD *pdwFlags)
|
||
|
{
|
||
|
*pdwFlags = 0;
|
||
|
|
||
|
// Also lets convert the Computer name pattern into the strings
|
||
|
// will do the compares against.
|
||
|
if ((_szUserInputCompName[0] == TEXT('\\')) &&
|
||
|
(_szUserInputCompName[1] == TEXT('\\')))
|
||
|
{
|
||
|
Str_SetPtr(&_pszCompName, _szUserInputCompName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SetupWildCardingOnFileSpec(_szUserInputCompName, &_pszCompName);
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::GetColumnsFolder(IShellFolder2 **ppsf)
|
||
|
{
|
||
|
LPITEMIDLIST pidl;
|
||
|
HRESULT hr = SHGetDomainWorkgroupIDList(&pidl);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = SHBindToObject(NULL, IID_X_PPV_ARG(IShellFolder2, pidl, ppsf));
|
||
|
ILFree(pidl);
|
||
|
}
|
||
|
else
|
||
|
*ppsf = NULL;
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(BOOL) CNetFindFilter::MatchFilter(IShellFolder *psf, LPCITEMIDLIST pidl)
|
||
|
{
|
||
|
if (this->_pszCompName && this->_pszCompName[0])
|
||
|
{
|
||
|
// Although for now not much...
|
||
|
TCHAR szPath[MAX_PATH];
|
||
|
|
||
|
return SUCCEEDED(DisplayNameOf(psf, pidl, SHGDN_NORMAL, szPath, ARRAYSIZE(szPath))) &&
|
||
|
PathMatchSpec(szPath, _pszCompName);
|
||
|
}
|
||
|
|
||
|
return TRUE; // emtpy search, return TRUE (yes)
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::SaveCriteria(IStream *pstm, WORD fCharType)
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::RestoreCriteria(IStream *pstm, int cCriteria, WORD fCharType)
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::GetColSaveStream(WPARAM wparam, IStream **ppstm)
|
||
|
{
|
||
|
*ppstm = NULL;
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::GenerateQueryRestrictions(LPWSTR *ppszQuery, DWORD *pdwFlags)
|
||
|
{
|
||
|
if (ppszQuery)
|
||
|
*ppszQuery = NULL;
|
||
|
*pdwFlags = 0;
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::ReleaseQuery()
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CNetFindFilter::UpdateField(LPCWSTR pszField, VARIANT vValue)
|
||
|
{
|
||
|
HRESULT hr = E_FAIL;
|
||
|
|
||
|
if (0 == StrCmpIW(pszField, L"LookIn"))
|
||
|
{
|
||
|
hr = S_OK; // ignored
|
||
|
}
|
||
|
else if (0 == StrCmpIW(pszField, L"SearchFor"))
|
||
|
{
|
||
|
// Careful! VariantToStr returns a pointer, not an HRESULT
|
||
|
if (VariantToStr(&vValue, _szUserInputCompName, ARRAYSIZE(_szUserInputCompName)))
|
||
|
{
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT CNetFindFilter::ResetFieldsToDefaults()
|
||
|
{
|
||
|
_szUserInputCompName[0] = 0;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindFilter::DeclareFSNotifyInterest(HWND hwndDlg, UINT uMsg)
|
||
|
{
|
||
|
SHChangeNotifyEntry fsne;
|
||
|
|
||
|
fsne.fRecursive = TRUE;
|
||
|
fsne.pidl = _pidlStart;
|
||
|
if (fsne.pidl)
|
||
|
{
|
||
|
SHChangeNotifyRegister(hwndDlg, SHCNRF_NewDelivery | SHCNRF_ShellLevel, SHCNE_DISKEVENTS, uMsg, 1, &fsne);
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
// chop off all of an UNC path except the \\server portion
|
||
|
|
||
|
void _StripToServer(LPTSTR pszUNC)
|
||
|
{
|
||
|
for (pszUNC += 2; *pszUNC; pszUNC = CharNext(pszUNC))
|
||
|
{
|
||
|
if (*pszUNC == TEXT('\\'))
|
||
|
{
|
||
|
// found something after server name, so get rid of it
|
||
|
*pszUNC = 0;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Helper function to the next function to help process find computer
|
||
|
// on returning computers by UNC names...
|
||
|
|
||
|
HRESULT CNetFindEnum::_FindCompByUNCName(LPITEMIDLIST *ppidl, int *piState)
|
||
|
{
|
||
|
*piState = GNF_DONE; // assume we are done
|
||
|
|
||
|
// Two cases, There is a UNC name entered. If so we need to process
|
||
|
// this by extracting everythign off after the server name...
|
||
|
if (_pnetf->_pszCompName && _pnetf->_pszCompName[0])
|
||
|
{
|
||
|
if (PathIsUNC(_pnetf->_pszCompName))
|
||
|
{
|
||
|
_StripToServer(_pnetf->_pszCompName);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// no unc name, but lets try to convert to unc name
|
||
|
TCHAR szTemp[MAX_PATH];
|
||
|
szTemp[0] = TEXT('\\');
|
||
|
szTemp[1] = TEXT('\\');
|
||
|
szTemp[2] = 0;
|
||
|
|
||
|
StrCatBuff(szTemp, _pnetf->_szUserInputCompName, ARRAYSIZE(szTemp));
|
||
|
_StripToServer(szTemp);
|
||
|
|
||
|
Str_SetPtr(&_pnetf->_pszCompName, szTemp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (_pnetf->_pszCompName && _pnetf->_pszCompName[0])
|
||
|
{
|
||
|
// see if we can parse this guy... if so we have a match
|
||
|
LPITEMIDLIST pidl;
|
||
|
if (SUCCEEDED(SHParseDisplayName(_pnetf->_pszCompName, NULL, &pidl, 0, NULL)))
|
||
|
{
|
||
|
LPITEMIDLIST pidlFolder;
|
||
|
LPCITEMIDLIST pidlChild;
|
||
|
if (SUCCEEDED(SplitIDList(pidl, &pidlFolder, &pidlChild)))
|
||
|
{
|
||
|
if (SUCCEEDED(_pff->AddFolder(pidlFolder, FALSE, &_iFolder)))
|
||
|
{
|
||
|
if (SUCCEEDED(_pff->AddDataToIDList(pidlChild, _iFolder, pidlFolder, DFDF_NONE, 0, 0, 0, ppidl)))
|
||
|
*piState = GNF_MATCH;
|
||
|
}
|
||
|
ILFree(pidlFolder);
|
||
|
}
|
||
|
ILFree(pidl);
|
||
|
}
|
||
|
}
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindEnum::Next(LPITEMIDLIST *ppidl, int *pcObjectSearched,
|
||
|
int *pcFoldersSearched, BOOL *pfContinue, int *piState)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
// Special case to find UNC Names quickly
|
||
|
if (_fFindUNC)
|
||
|
{
|
||
|
// If not the first time through return that we are done!
|
||
|
if (_iPassCnt)
|
||
|
{
|
||
|
*piState = GNF_DONE;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
_iPassCnt = 1;
|
||
|
|
||
|
hr = _FindCompByUNCName(ppidl, piState);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
BOOL fContinue = TRUE;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
if (_penum)
|
||
|
{
|
||
|
LPITEMIDLIST pidl;
|
||
|
if (S_OK == _penum->Next(1, &pidl, NULL))
|
||
|
{
|
||
|
// Now see if this is someone we might want to return.
|
||
|
// Our Match function take esither find data or idlist...
|
||
|
// for networks we work off of the idlist,
|
||
|
fContinue = FALSE; // We can exit the loop;
|
||
|
(*pcObjectSearched)++;
|
||
|
|
||
|
if (_pnetf->MatchFilter(_psfEnum, pidl))
|
||
|
{
|
||
|
*piState = GNF_MATCH;
|
||
|
|
||
|
// see if we have to add this folder to our list.
|
||
|
if (-1 == _iFolder)
|
||
|
_pff->AddFolder(_pidlFolder, FALSE, &_iFolder);
|
||
|
|
||
|
if (SUCCEEDED(_pff->AddDataToIDList(pidl, _iFolder, _pidlFolder, DFDF_NONE, 0, 0, 0, ppidl)))
|
||
|
{
|
||
|
if ((_iPassCnt == 1) && _pnetf->_pszCompName && _pnetf->_pszCompName[0])
|
||
|
{
|
||
|
// See if this is an exact match of the name
|
||
|
// we are looking for. If it is we set pass=2
|
||
|
// as to not add the item twice.
|
||
|
TCHAR szName[MAX_PATH];
|
||
|
|
||
|
if (SUCCEEDED(DisplayNameOf(_psfEnum, pidl, SHGDN_NORMAL, szName, ARRAYSIZE(szName))) &&
|
||
|
(0 == lstrcmpi(szName, _pnetf->_szUserInputCompName)))
|
||
|
{
|
||
|
_iPassCnt = 2;
|
||
|
}
|
||
|
}
|
||
|
ILFree(pidl);
|
||
|
pidl = NULL;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*piState = GNF_NOMATCH;
|
||
|
}
|
||
|
ILFree(pidl);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ATOMICRELEASE(_penum); // release and zero
|
||
|
ATOMICRELEASE(_psfEnum);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!_penum)
|
||
|
{
|
||
|
switch (_iPassCnt)
|
||
|
{
|
||
|
case 1:
|
||
|
// We went through all of the items see if there is
|
||
|
// an exact match...
|
||
|
_iPassCnt = 2;
|
||
|
|
||
|
return _FindCompByUNCName(ppidl, piState);
|
||
|
|
||
|
case 2:
|
||
|
// We looped through everything so return done!
|
||
|
*piState = GNF_DONE;
|
||
|
return S_OK;
|
||
|
|
||
|
case 0:
|
||
|
// This is the main pass through here...
|
||
|
// Need to clone the idlist
|
||
|
hr = SHILClone(_pidlStart, &_pidlFolder);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
_iPassCnt = 1;
|
||
|
|
||
|
// We will do the first on in our own thread.
|
||
|
if (SUCCEEDED(SHBindToObject(NULL, IID_X_PPV_ARG(IShellFolder, _pidlFolder, &_psfEnum))))
|
||
|
{
|
||
|
if (S_OK != _psfEnum->EnumObjects(NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &_penum))
|
||
|
{
|
||
|
// Failed to get iterator so release folder.
|
||
|
ATOMICRELEASE(_psfEnum);
|
||
|
ASSERT(NULL == _penum);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*piState = GNF_ERROR;
|
||
|
return hr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
(*pcFoldersSearched)++;
|
||
|
|
||
|
// update progress text
|
||
|
SHGetNameAndFlags(_pidlFolder, SHGDN_NORMAL, _pszDisplayText, MAX_PATH, NULL);
|
||
|
}
|
||
|
} while (fContinue && *pfContinue);
|
||
|
|
||
|
hr = S_OK;
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP_(BOOL) CNetFindEnum::FQueryIsAsync()
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindEnum::GetAsyncCount(DBCOUNTITEM *pdwTotalAsync, int *pnPercentComplete, BOOL *pfQueryDone)
|
||
|
{
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindEnum::GetItemIDList(UINT iItem, LPITEMIDLIST *ppidl)
|
||
|
{
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindEnum::GetItemID(UINT iItem, DWORD *puWorkID)
|
||
|
{
|
||
|
*puWorkID = (UINT)-1;
|
||
|
return E_NOTIMPL;
|
||
|
}
|
||
|
|
||
|
STDMETHODIMP CNetFindEnum::SortOnColumn(UINT iCOl, BOOL fAscending)
|
||
|
{
|
||
|
return E_NOTIMPL;
|
||
|
}
|