📄 ftpobj.cpp
字号:
HRESULT CFtpObj::_SetProgressDialogValues(int nIndex)
{
HRESULT hr = S_OK;
m_nStartIndex = nIndex;
if (EVAL(m_ppd))
{
// Calculate m_nEndIndex
while (nIndex < m_pflHfpl->GetCount())
{
if (!FtpPidl_IsDirectory(m_pflHfpl->GetPidl(nIndex), FALSE))
m_nEndIndex = nIndex;
nIndex++;
}
for (nIndex = 0; nIndex < m_pflHfpl->GetCount(); nIndex++)
{
LPCITEMIDLIST pidl = m_pflHfpl->GetPidl(nIndex);
m_uliTotal.QuadPart += FtpPidl_GetFileSize(pidl);
}
// Reset because the above for loop can take a long time and the estimated time
// is based on the time between ::StartProgressDialog() and the first
// ::SetProgress() call.
EVAL(SUCCEEDED(m_ppd->Timer(PDTIMER_RESET, NULL)));
}
return hr;
}
HRESULT CFtpObj::_CloseProgressDialog(void)
{
m_nStartIndex = -1; // Indicate we haven't inited yet.
if (m_ppd)
{
EVAL(SUCCEEDED(m_ppd->StopProgressDialog()));
IUnknown_Set((IUnknown **)&m_ppd, NULL);
}
return S_OK;
}
HRESULT CFtpObj::_RefThread(void)
{
if (NULL == m_punkThreadRef)
{
// This is valid to fail from some hosts who won't go away,
// so they don't need to support ref counting threads.
SHGetThreadRef(&m_punkThreadRef);
}
return S_OK;
}
HRESULT CFtpObj::_RenderFileContents(LPFORMATETC pfe, LPSTGMEDIUM pstg)
{
HRESULT hr = E_INVALIDARG;
// callers have a bad habit of asking for lindex == -1 because
// that means 'all' data. But how can you hand out one IStream* for
// all files?
if (-1 != pfe->lindex)
{
LPITEMIDLIST pidl = m_pflHfpl->GetPidl(pfe->lindex);
// FileContents are always regenerated afresh.
pstg->pUnkForRelease = 0;
pstg->tymed = TYMED_ISTREAM;
if (EVAL(pidl))
{
hr = _DoProgressForLegacySystemsStart(pidl, pfe->lindex);
if (SUCCEEDED(hr))
{
// Is it a directory?
if (FtpPidl_IsDirectory(pidl, FALSE))
{
// Yes, so pack the name and attributes
hr = DV_E_LINDEX;
AssertMsg(0, TEXT("Someone is asking for a FILECONTENTs for a directory item."));
}
else
{
// No, so give them the stream.
// shell32 v5 will display progress dialogs, but we need to
// display progress dialogs for shell32 v3 or v4. We do this
// by creating the progress dialog when the caller asks for the
// first stream. We then need to find out when they call for
// the last stream and then hand off the IProgressDialog to the
// CFtpStm. The CFtpStm will then close down the dialog when the
// caller closes it.
hr = CFtpStm_Create(m_pfd, pidl, GENERIC_READ, &pstg->pstm, m_uliCompleted, m_uliTotal, m_ppd, (pfe->lindex == m_nEndIndex));
EVAL(SUCCEEDED(_DoProgressForLegacySystemsPost(pidl, (pfe->lindex == m_nEndIndex))));
}
}
else
{
// The user may have cancelled
ASSERT(HRESULT_FROM_WIN32(ERROR_CANCELLED) == hr);
}
}
if (FAILED(hr))
_CloseProgressDialog();
}
//TraceMsg(TF_FTPDRAGDROP, "CFtpObj::GetData() CFtpStm_Create() returned hr=%#08lx", hr);
return hr;
}
/*****************************************************************************\
FUNCTION: IsEqualFORMATETC
DESCRIPTION:
The two fields of a FORMATETC that need to match to be equivalent are:
cfFormat and lindex.
\*****************************************************************************/
BOOL IsEqualFORMATETC(FORMATETC * pfe1, FORMATETC * pfe2)
{
BOOL fIsEqual = FALSE;
if ((pfe1->cfFormat == pfe2->cfFormat) && (pfe1->lindex == pfe2->lindex))
{
fIsEqual = TRUE;
}
return fIsEqual;
}
/*****************************************************************************\
FUNCTION: _FreeExtraData
DESCRIPTION:
\*****************************************************************************/
int CFtpObj::_DSA_FreeCB(LPVOID pvItem, LPVOID pvlparam)
{
FORMATETC_STGMEDIUM * pfs = (FORMATETC_STGMEDIUM *) pvItem;
if (EVAL(pfs))
ReleaseStgMedium(&(pfs->medium));
return 1;
}
/*****************************************************************************\
FUNCTION: _FindSetDataIndex
DESCRIPTION:
\*****************************************************************************/
int CFtpObj::_FindExtraDataIndex(FORMATETC *pfe)
{
int nIndex;
for (nIndex = (DSA_GetItemCount(m_hdsaSetData) - 1); nIndex >= 0; nIndex--)
{
FORMATETC_STGMEDIUM * pfs = (FORMATETC_STGMEDIUM *) DSA_GetItemPtr(m_hdsaSetData, nIndex);
if (IsEqualFORMATETC(pfe, &pfs->formatEtc))
{
return nIndex;
}
}
return -1;
}
/*****************************************************************************\
FUNCTION: _SetExtraData
DESCRIPTION:
We don't render the data, but we will carry it because someone may need
or want it. This is the case with the drag source's defview pushing in
the icon points via CFSTR_SHELLIDLISTOFFSET for the drop target.
\*****************************************************************************/
HRESULT CFtpObj::_SetExtraData(FORMATETC *pfe, STGMEDIUM *pstg, BOOL fRelease)
{
HRESULT hr;
int nIndex = _FindExtraDataIndex(pfe);
// Do we already have someone's copy?
if (-1 == nIndex)
{
FORMATETC_STGMEDIUM fs;
fs.formatEtc = *pfe;
// If there is a pointer, copy the data because we can't maintain the lifetime
// of the pointer.
if (fs.formatEtc.ptd)
{
fs.dvTargetDevice = *(pfe->ptd);
fs.formatEtc.ptd = &fs.dvTargetDevice;
}
hr = CopyStgMediumWrap(pstg, &fs.medium);
if (EVAL(SUCCEEDED(hr)))
{
// No, so just append it to the end.
DSA_AppendItem(m_hdsaSetData, &fs);
}
}
else
{
FORMATETC_STGMEDIUM fs;
DSA_GetItem(m_hdsaSetData, nIndex, &fs);
// Free the previous guy.
ReleaseStgMedium(&fs.medium);
// Yes, so Replace it.
hr = CopyStgMediumWrap(pstg, &fs.medium);
if (EVAL(SUCCEEDED(hr)))
{
// Replace the data.
DSA_SetItem(m_hdsaSetData, nIndex, &fs);
}
}
return hr;
}
typedef struct
{
DWORD dwVersion;
DWORD dwExtraSize; // After pidl list
BOOL fFGDRendered;
DWORD dwReserved1;
DWORD dwReserved2;
} FTPDATAOBJ_PERSISTSTRUCT;
/*****************************************************************************\
FUNCTION: FormatEtcSaveToStream
DESCRIPTION:
\*****************************************************************************/
HRESULT FormatEtcSaveToStream(IStream *pStm, FORMATETC * pFormatEtc)
{
HRESULT hr = E_INVALIDARG;
if (pStm)
{
// We don't support ptd because where would the allocation be
// on the load?
if (EVAL(NULL == pFormatEtc->ptd))
{
WCHAR szFormatName[MAX_PATH];
if (EVAL(GetClipboardFormatNameW(pFormatEtc->cfFormat, szFormatName, ARRAYSIZE(szFormatName))))
{
DWORD cbFormatNameSize = ((lstrlenW(szFormatName) + 1) * sizeof(szFormatName[0]));
hr = pStm->Write(pFormatEtc, SIZEOF(*pFormatEtc), NULL);
if (EVAL(SUCCEEDED(hr)))
{
hr = pStm->Write(&cbFormatNameSize, SIZEOF(cbFormatNameSize), NULL);
if (EVAL(SUCCEEDED(hr)))
{
hr = pStm->Write(szFormatName, cbFormatNameSize, NULL);
}
}
}
else
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
return hr;
}
/*****************************************************************************\
FUNCTION: FormatEtcLoadFromStream
DESCRIPTION:
\*****************************************************************************/
HRESULT FormatEtcLoadFromStream(IStream *pStm, FORMATETC * pFormatEtc)
{
HRESULT hr = E_INVALIDARG;
if (pStm)
{
hr = pStm->Read(pFormatEtc, SIZEOF(*pFormatEtc), NULL);
ASSERT(NULL == pFormatEtc->ptd); // We don't support this.
if (EVAL(SUCCEEDED(hr)))
{
DWORD cbFormatNameSize;
hr = pStm->Read(&cbFormatNameSize, SIZEOF(cbFormatNameSize), NULL);
if (EVAL(SUCCEEDED(hr)))
{
WCHAR szFormatName[MAX_PATH];
hr = pStm->Read(szFormatName, cbFormatNameSize, NULL);
if (EVAL(SUCCEEDED(hr)))
{
pFormatEtc->cfFormat = (CLIPFORMAT)RegisterClipboardFormatW(szFormatName);
}
}
}
else
hr = HRESULT_FROM_WIN32(GetLastError());
}
return hr;
}
typedef struct
{
DWORD dwVersion;
DWORD dwExtraSize; // After this struct
DWORD dwTymed; // What type of data is stored?
BOOL fUnkForRelease; // Did we save the object after this?
DWORD dwReserved1; //
DWORD dwReserved2; //
} STGMEDIUM_PERSISTSTRUCT;
/*****************************************************************************\
FUNCTION: StgMediumSaveToStream
DESCRIPTION:
\*****************************************************************************/
HRESULT StgMediumSaveToStream(IStream *pStm, STGMEDIUM * pMedium)
{
HRESULT hr = E_INVALIDARG;
if (pStm)
{
STGMEDIUM_PERSISTSTRUCT smps = {0};
smps.dwVersion = 1;
smps.dwTymed = pMedium->tymed;
switch (pMedium->tymed)
{
case TYMED_HGLOBAL:
{
IStream * pstmHGlobal;
hr = CreateStreamOnHGlobal(pMedium->hGlobal, FALSE, &pstmHGlobal);
if (EVAL(SUCCEEDED(hr)))
{
STATSTG statStg;
hr = pstmHGlobal->Stat(&statStg, STATFLAG_NONAME);
if (EVAL(SUCCEEDED(hr)))
{
ASSERT(!statStg.cbSize.HighPart);
smps.dwExtraSize = statStg.cbSize.LowPart;
hr = pStm->Write(&smps, SIZEOF(smps), NULL);
if (EVAL(SUCCEEDED(hr)))
hr = pstmHGlobal->CopyTo(pStm, statStg.cbSize, NULL, NULL);
}
pstmHGlobal->Release();
}
}
break;
case TYMED_FILE:
smps.dwExtraSize = ((lstrlenW(pMedium->lpszFileName) + 1) * sizeof(WCHAR));
hr = pStm->Write(&smps, SIZEOF(smps), NULL);
if (EVAL(SUCCEEDED(hr)))
{
hr = pStm->Write(pMedium->lpszFileName, smps.dwExtraSize, NULL);
ASSERT(SUCCEEDED(hr));
}
break;
case TYMED_GDI:
case TYMED_MFPICT:
case TYMED_ENHMF:
case TYMED_ISTORAGE:
case TYMED_ISTREAM:
default:
ASSERT(0); // What are you doing? Impl this if you need it.
hr = E_NOTIMPL;
break;
}
}
return hr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -