📄 ftppl.cpp
字号:
/*****************************************************************************
*
* ftppl.cpp - FTP LPITEMIDLIST List object
*
*****************************************************************************/
#include "priv.h"
#include "ftppl.h"
#include "ftpurl.h"
typedef struct tagINETENUM
{
HINTERNET hint;
BOOL * pfValidhinst;
LPVOID pvData;
LPFNPROCESSITEMCB pfnProcessItemCB;
LPCITEMIDLIST pidlRoot;
HRESULT hr;
} INETENUM;
/*****************************************************************************\
FUNCTION: RecursiveEnum
DESCRIPTION:
This function will pack the parameters needed during the enum.
\*****************************************************************************/
HRESULT CFtpPidlList::RecursiveEnum(LPCITEMIDLIST pidlRoot, LPFNPROCESSITEMCB pfnProcessItemCB, HINTERNET hint, LPVOID pvData)
{
INETENUM inetEnum = {hint, NULL, pvData, pfnProcessItemCB, pidlRoot, S_OK};
Enum(RecursiveProcessPidl, (LPVOID) &inetEnum);
return inetEnum.hr;
}
// lParam can be: 0 == do a case sensitive search. 1 == do a case insensitive search.
int CFtpPidlList::ComparePidlName(LPVOID pvPidl1, LPVOID pvPidl2, LPARAM lParam)
{
DWORD dwFlags = FCMP_NORMAL;
if (lParam)
dwFlags |= FCMP_CASEINSENSE;
// return < 0 for pvPidl1 before pvPidl2.
// return == 0 for pvPidl1 equals pvPidl2.
// return > 0 for pvPidl1 after pvPidl2.
return FtpItemID_CompareIDsInt(COL_NAME, (LPCITEMIDLIST)pvPidl1, (LPCITEMIDLIST)pvPidl2, dwFlags);
}
HRESULT CFtpPidlList::InsertSorted(LPCITEMIDLIST pidl)
{
m_pfl->InsertSorted(ILClone(pidl), CFtpPidlList::ComparePidlName, FALSE /*Case Insensitive*/);
return S_OK;
};
int CFtpPidlList::FindPidlIndex(LPCITEMIDLIST pidlToFind, BOOL fCaseInsensitive)
{
return m_pfl->SortedSearch((LPVOID) pidlToFind, CFtpPidlList::ComparePidlName, (LPARAM)fCaseInsensitive, DPAS_SORTED);
}
LPITEMIDLIST CFtpPidlList::FindPidl(LPCITEMIDLIST pidlToFind, BOOL fCaseInsensitive)
{
LPITEMIDLIST pidlFound = NULL;
int nIndex = FindPidlIndex(pidlToFind, fCaseInsensitive);
if (-1 != nIndex)
{
pidlFound = ILClone(GetPidl(nIndex));
}
return pidlFound;
}
HRESULT CFtpPidlList::CompareAndDeletePidl(LPCITEMIDLIST pidlToDelete)
{
HRESULT hr = S_FALSE;
int nIndex = FindPidlIndex(pidlToDelete, FALSE /*Case Insensitive*/);
if (-1 != nIndex)
{
LPITEMIDLIST pidlCurrent = GetPidl((UINT)nIndex);
if (EVAL(pidlCurrent))
{
ASSERT(0 == FtpItemID_CompareIDsInt(COL_NAME, pidlCurrent, pidlToDelete, FCMP_NORMAL));
m_pfl->DeletePtrByIndex(nIndex);
ILFree(pidlCurrent); // Deallocate the memory
hr = S_OK; // Found and deleted.
}
}
return hr;
}
void CFtpPidlList::Delete(int nIndex)
{
LPITEMIDLIST pidlToDelete = GetPidl(nIndex);
ILFree(pidlToDelete); // Free the memory.
m_pfl->DeletePtrByIndex(nIndex);
}
HRESULT CFtpPidlList::ReplacePidl(LPCITEMIDLIST pidlSrc, LPCITEMIDLIST pidlDest)
{
HRESULT hr = S_FALSE;
int nIndex = FindPidlIndex(pidlSrc, FALSE);
if (-1 != nIndex)
{
LPITEMIDLIST pidlCurrent = GetPidl((UINT)nIndex);
if (EVAL(pidlCurrent))
{
ASSERT(0 == FtpItemID_CompareIDsInt(COL_NAME, pidlCurrent, pidlSrc, FCMP_NORMAL));
ILFree(pidlCurrent); // Deallocate the memory
m_pfl->DeletePtrByIndex(nIndex);
InsertSorted(pidlDest); // This function does the ILClone()
hr = S_OK; // Found and deleted.
}
}
return hr;
}
void CFtpPidlList::AssertSorted(void)
{
#ifdef DEBUG
// For perf reasons, we need to keep this list in order.
// This is mainly because parse display name looks thru
// the list, so we want that to be fast.
for (int nIndex = (GetCount() - 2); (nIndex >= 0); nIndex--)
{
LPITEMIDLIST pidl1 = GetPidl((UINT)nIndex);
LPITEMIDLIST pidl2 = GetPidl((UINT)nIndex + 1);
// Assert that pidl1 comes before pidl2.
if (!EVAL(0 >= FtpItemID_CompareIDsInt(COL_NAME, pidl1, pidl2, FCMP_NORMAL)))
{
TCHAR szPidl1[MAX_PATH];
TCHAR szPidl2[MAX_PATH];
if (FtpID_IsServerItemID(pidl1))
FtpPidl_GetServer(pidl1, szPidl1, ARRAYSIZE(szPidl1));
else
FtpPidl_GetDisplayName(pidl1, szPidl1, ARRAYSIZE(szPidl1));
if (FtpID_IsServerItemID(pidl2))
FtpPidl_GetServer(pidl2, szPidl2, ARRAYSIZE(szPidl2));
else
FtpPidl_GetDisplayName(pidl2, szPidl2, ARRAYSIZE(szPidl2));
TraceMsg(TF_ERROR, "CFtpPidlList::AssertSorted() '%s' & '%s' where found out of order", szPidl1, szPidl2);
}
// We do NOT need to free pidl1 or pidl2 because we get a pointer to someone else's copy.
}
#endif // DEBUG
}
void CFtpPidlList::TraceDump(LPCITEMIDLIST pidl, LPCTSTR pszCaller)
{
#ifdef DEBUG
/*
TCHAR szUrl[MAX_URL_STRING];
UrlCreateFromPidl(pidl, SHGDN_FORPARSING, szUrl, ARRAYSIZE(szUrl), ICU_USERNAME, FALSE);
TraceMsg(TF_PIDLLIST_DUMP, "CFtpPidlList::TraceDump() root is '%s', called from '%s'", szUrl, pszCaller);
// Let's look at the contents.
for (int nIndex = (GetCount() - 1); (nIndex >= 0); nIndex--)
{
LPITEMIDLIST pidlFull = ILCombine(pidl, GetPidl((UINT)nIndex));
if (pidlFull)
{
UrlCreateFromPidl(pidlFull, SHGDN_FORPARSING, szUrl, ARRAYSIZE(szUrl), ICU_USERNAME, FALSE);
TraceMsg(TF_PIDLLIST_DUMP, "CFtpPidlList::TraceDump() Index=%d, url=%s", nIndex, szUrl);
ILFree(pidlFull);
}
}
*/
#endif // DEBUG
}
void CFtpPidlList::UseCachedDirListings(BOOL fUseCachedDirListings)
{
// Normally we do two passes in the tree walker code. The first
// pass is to count up the time required to do the download. We
// normally force WININET to not use cached results because someone
// else could have changed the contents on the server.
// On the second pass, we normally do the work (upload, download, delete)
// and we want to use the cached results to get the perf advantage
// and the results shouldn't be more than a minute out of date.
if (fUseCachedDirListings)
m_dwInetFlags = INTERNET_NO_CALLBACK;
else
m_dwInetFlags = (INTERNET_NO_CALLBACK | INTERNET_FLAG_RESYNCHRONIZE | INTERNET_FLAG_RELOAD);
}
BOOL CFtpPidlList::AreAllFolders(void)
{
BOOL fAllFolder = TRUE;
for (int nIndex = (GetCount() - 1); fAllFolder && (nIndex >= 0); nIndex--)
{
LPITEMIDLIST pidl = GetPidl((UINT)nIndex);
if (EVAL(pidl))
fAllFolder = FtpPidl_IsDirectory(pidl, TRUE);
// We do NOT need to free pidl because we get a pointer to someone else's copy.
}
return fAllFolder;
}
BOOL CFtpPidlList::AreAllFiles(void)
{
BOOL fAllFiles = TRUE;
for (int nIndex = (GetCount() - 1); fAllFiles && (nIndex >= 0); nIndex--)
{
LPITEMIDLIST pidl = GetPidl((UINT)nIndex);
if (EVAL(pidl))
fAllFiles = !FtpPidl_IsDirectory(pidl, TRUE);
// We do NOT need to free pidl because we get a pointer to someone else's copy.
}
return fAllFiles;
}
/*****************************************************************************
*
* CFtpPidlList::_Fill
*
* Fill a list with an array.
*
* The elements in the array are copied rather than stolen.
*
*****************************************************************************/
HRESULT CFtpPidlList::_Fill(int cpidl, LPCITEMIDLIST rgpidl[])
{
HRESULT hres = S_OK;
for (int ipidl = 0; (ipidl < cpidl) && SUCCEEDED(hres); ipidl++)
{
ASSERT(IsValidPIDL(rgpidl[ipidl]));
hres = InsertSorted(rgpidl[ipidl]);
}
return hres;
}
/*****************************************************************************
*
* CFtpPidlList::GetPidlList
*
*****************************************************************************/
LPCITEMIDLIST * CFtpPidlList::GetPidlList(void)
{
LPITEMIDLIST * ppidl;
ppidl = (LPITEMIDLIST *) LocalAlloc(LPTR, sizeof(LPITEMIDLIST) * GetCount());
if (ppidl)
{
int nIndex;
for (nIndex = 0; nIndex < GetCount(); nIndex++)
{
// Later we can make this user ILClone() if we want to be able to wack on the
// pidl list while this list is being used.
ppidl[nIndex] = GetPidl(nIndex);
}
}
return (LPCITEMIDLIST *) ppidl;
}
/*****************************************************************************
*
* CFtpPidlList::FreePidlList
*
*****************************************************************************/
void CFtpPidlList::FreePidlList(LPCITEMIDLIST * ppidl)
{
LocalFree(ppidl);
}
/*****************************************************************************
*
* CFtpPidlList_Create
*
* Start up a new pv list, with a recommended initial size and other
* callback info.
*
*****************************************************************************/
HRESULT CFtpPidlList_Create(int cpidl, LPCITEMIDLIST rgpidl[], CFtpPidlList ** ppflpidl)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -