📄 ftpobj.cpp
字号:
}
LPWSTR OLESTRAlloc(DWORD cchSize)
{
return (LPWSTR) new WCHAR [cchSize + 1];
}
/*****************************************************************************\
FUNCTION: StgMediumLoadFromStream
DESCRIPTION:
\*****************************************************************************/
HRESULT StgMediumLoadFromStream(IStream *pStm, STGMEDIUM * pMedium)
{
HRESULT hr = E_INVALIDARG;
if (pStm && pMedium)
{
STGMEDIUM_PERSISTSTRUCT smps;
pMedium->pUnkForRelease = NULL;
hr = pStm->Read(&smps, SIZEOF(smps), NULL);
if (EVAL(SUCCEEDED(hr)))
{
pMedium->tymed = smps.dwTymed;
ASSERT(!pMedium->pUnkForRelease);
switch (pMedium->tymed)
{
case TYMED_HGLOBAL:
{
IStream * pstmTemp;
hr = CreateStreamOnHGlobal(NULL, FALSE, &pstmTemp);
if (EVAL(SUCCEEDED(hr)))
{
ULARGE_INTEGER uli = {0};
uli.LowPart = smps.dwExtraSize;
hr = pStm->CopyTo(pstmTemp, uli, NULL, NULL);
if (EVAL(SUCCEEDED(hr)))
{
hr = GetHGlobalFromStream(pstmTemp, &pMedium->hGlobal);
}
pstmTemp->Release();
}
}
break;
case TYMED_FILE:
pMedium->lpszFileName = OLESTRAlloc(smps.dwExtraSize / sizeof(WCHAR));
if (pMedium->lpszFileName)
hr = pStm->Read(pMedium->lpszFileName, smps.dwExtraSize, NULL);
else
hr = E_OUTOFMEMORY;
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.
// Some future version must have done the save, so skip the
// data so we don't leave unread data.
if (0 != smps.dwExtraSize)
{
LARGE_INTEGER li = {0};
li.LowPart = smps.dwExtraSize;
EVAL(SUCCEEDED(pStm->Seek(li, STREAM_SEEK_CUR, NULL)));
}
hr = E_NOTIMPL;
break;
}
}
}
return hr;
}
/*****************************************************************************\
FUNCTION: FORMATETC_STGMEDIUMSaveToStream
DESCRIPTION:
\*****************************************************************************/
HRESULT FORMATETC_STGMEDIUMSaveToStream(IStream *pStm, FORMATETC_STGMEDIUM * pfdops)
{
HRESULT hr = E_INVALIDARG;
if (pStm)
{
hr = FormatEtcSaveToStream(pStm, &pfdops->formatEtc);
if (EVAL(SUCCEEDED(hr)))
hr = StgMediumSaveToStream(pStm, &pfdops->medium);
}
return hr;
}
/*****************************************************************************\
FUNCTION: FORMATETC_STGMEDIUMLoadFromStream
DESCRIPTION:
\*****************************************************************************/
HRESULT FORMATETC_STGMEDIUMLoadFromStream(IStream *pStm, FORMATETC_STGMEDIUM * pfdops)
{
HRESULT hr = E_INVALIDARG;
if (pStm)
{
hr = FormatEtcLoadFromStream(pStm, &pfdops->formatEtc);
if (EVAL(SUCCEEDED(hr)))
hr = StgMediumLoadFromStream(pStm, &pfdops->medium);
}
return hr;
}
/////////////////////////////////
////// IAsynchDataObject Impl
/////////////////////////////////
/*****************************************************************************\
FUNCTION: IAsyncOperation::GetAsyncMode
DESCRIPTION:
\*****************************************************************************/
HRESULT CFtpObj::GetAsyncMode(BOOL * pfIsOpAsync)
{
*pfIsOpAsync = TRUE;
return S_OK;
}
/*****************************************************************************\
FUNCTION: IAsyncOperation::StartOperation
DESCRIPTION:
\*****************************************************************************/
HRESULT CFtpObj::StartOperation(IBindCtx * pbcReserved)
{
ASSERT(!pbcReserved);
m_fDidAsynchStart = TRUE;
return S_OK;
}
/*****************************************************************************\
FUNCTION: IAsyncOperation::InOperation
DESCRIPTION:
\*****************************************************************************/
HRESULT CFtpObj::InOperation(BOOL * pfInAsyncOp)
{
if (m_fDidAsynchStart)
*pfInAsyncOp = TRUE;
else
*pfInAsyncOp = FALSE;
return S_OK;
}
/*****************************************************************************\
FUNCTION: IAsyncOperation::EndOperation
DESCRIPTION:
\*****************************************************************************/
HRESULT CFtpObj::EndOperation(HRESULT hResult, IBindCtx * pbcReserved, DWORD dwEffects)
{
if (SUCCEEDED(hResult) &&
(DROPEFFECT_MOVE == dwEffects))
{
CFtpPidlList * pPidlListNew = CreateRelativePidlList(m_pff, m_pflHfpl);
if (pPidlListNew)
{
Misc_DeleteHfpl(m_pff, GetDesktopWindow(), pPidlListNew);
pPidlListNew->Release();
}
}
m_fDidAsynchStart = FALSE;
return S_OK;
}
/////////////////////////////////
////// IPersistStream Impl
/////////////////////////////////
/*****************************************************************************\
FUNCTION: IPersistStream::Load
DESCRIPTION:
See IPersistStream::Save() for the layout of the stream.
\*****************************************************************************/
HRESULT CFtpObj::Load(IStream *pStm)
{
HRESULT hr = E_INVALIDARG;
if (pStm)
{
FTPDATAOBJ_PERSISTSTRUCT fdoss;
DWORD dwNumPidls;
DWORD dwNumStgMedium;
hr = pStm->Read(&fdoss, SIZEOF(fdoss), NULL); // #1
// If we rev the version, read it now (fdoss.dwVersion)
if (EVAL(SUCCEEDED(hr)))
{
LPITEMIDLIST pidl = NULL; // ILLoadFromStream frees the param
ASSERT(!m_pff);
m_fFGDRendered = fdoss.fFGDRendered;
hr = ILLoadFromStream(pStm, &pidl); // #2
if (EVAL(SUCCEEDED(hr)))
{
hr = SHBindToIDList(pidl, NULL, IID_CFtpFolder, (void **)&m_pff);
if (EVAL(SUCCEEDED(hr)))
m_pfd = m_pff->GetFtpDir();
ASSERT(m_pfd);
ILFree(pidl);
}
}
if (EVAL(SUCCEEDED(hr)))
{
hr = pStm->Read(&dwNumPidls, SIZEOF(dwNumPidls), NULL); // #3
if (EVAL(SUCCEEDED(hr)))
hr = CFtpPidlList_Create(0, NULL, &m_pflHfpl);
}
if (EVAL(SUCCEEDED(hr)))
{
for (int nIndex = 0; (nIndex < (int)dwNumPidls) && SUCCEEDED(hr); nIndex++)
{
LPITEMIDLIST pidl = NULL; // ILLoadFromStream frees the param
hr = ILLoadFromStream(pStm, &pidl); // #4
if (EVAL(SUCCEEDED(hr)))
{
hr = m_pflHfpl->InsertSorted(pidl);
ILFree(pidl);
}
}
}
if (EVAL(SUCCEEDED(hr)))
hr = pStm->Read(&dwNumStgMedium, SIZEOF(dwNumStgMedium), NULL); // #5
if (EVAL(SUCCEEDED(hr)))
{
for (int nIndex = 0; (nIndex < (int)dwNumStgMedium) && SUCCEEDED(hr); nIndex++)
{
FORMATETC_STGMEDIUM fs;
hr = FORMATETC_STGMEDIUMLoadFromStream(pStm, &fs); // #6
if (EVAL(SUCCEEDED(hr)))
DSA_AppendItem(m_hdsaSetData, &fs);
}
}
if (EVAL(SUCCEEDED(hr)))
{
// We may be reading a version newer than us, so skip their data.
if (0 != fdoss.dwExtraSize)
{
LARGE_INTEGER li = {0};
li.LowPart = fdoss.dwExtraSize;
hr = pStm->Seek(li, STREAM_SEEK_CUR, NULL);
}
}
}
return hr;
}
/*****************************************************************************\
FUNCTION: IPersistStream::Save
DESCRIPTION:
The stream will be layed out in the following way:
Version 1:
1. FTPDATAOBJ_PERSISTSTRUCT - Constant sized data.
<PidlList BEGIN>
2. PIDL pidl - Pidl for m_pff. It will be a public pidl (fully qualified
from the shell root)
3. DWORD dwNumPidls - Number of pidls coming.
4. PIDL pidl(n) - Pidl in slot (n) of m_pflHfpl
<PidlList END>
5. DWORD dwNumStgMedium - Number of FORMATETC_STGMEDIUMs coming
6. FORMATETC_STGMEDIUM fmtstg(n) - dwNumStgMedium FORMATETC_STGMEDIUMs.
\*****************************************************************************/
HRESULT CFtpObj::Save(IStream *pStm, BOOL fClearDirty)
{
HRESULT hr = E_INVALIDARG;
if (pStm)
{
FTPDATAOBJ_PERSISTSTRUCT fdoss = {0};
DWORD dwNumPidls = m_pflHfpl->GetCount();
DWORD dwNumStgMedium = DSA_GetItemCount(m_hdsaSetData);
fdoss.dwVersion = 1;
fdoss.fFGDRendered = m_fFGDRendered;
hr = pStm->Write(&fdoss, SIZEOF(fdoss), NULL); // #1
if (EVAL(SUCCEEDED(hr)))
{
ASSERT(m_pff);
hr = ILSaveToStream(pStm, m_pff->GetPublicRootPidlReference()); // #2
}
if (EVAL(SUCCEEDED(hr)))
hr = pStm->Write(&dwNumPidls, SIZEOF(dwNumPidls), NULL); // #3
if (EVAL(SUCCEEDED(hr)))
{
for (int nIndex = 0; (nIndex < (int)dwNumPidls) && SUCCEEDED(hr); nIndex++)
{
LPITEMIDLIST pidlCur = m_pflHfpl->GetPidl(nIndex);
ASSERT(pidlCur);
hr = ILSaveToStream(pStm, pidlCur); // #4
}
}
if (EVAL(SUCCEEDED(hr)))
hr = pStm->Write(&dwNumStgMedium, SIZEOF(dwNumStgMedium), NULL); // #5
if (EVAL(SUCCEEDED(hr)))
{
for (int nIndex = 0; (nIndex < (int)dwNumStgMedium) && SUCCEEDED(hr); nIndex++)
{
FORMATETC_STGMEDIUM fs;
DSA_GetItem(m_hdsaSetData, nIndex, &fs);
hr = FORMATETC_STGMEDIUMSaveToStream(pStm, &fs); // #6
}
}
}
return hr;
}
#define MAX_STREAM_SIZE (500 * 1024) // 500k
/*****************************************************************************\
FUNCTION: IPersistStream::GetSizeMax
DESCRIPTION:
Now this is tough. I can't calculate the real value because I don't know
how big the hglobals are going to be for the user provided data. I will
assume everything fits in
\*****************************************************************************/
HRESULT CFtpObj::GetSizeMax(ULARGE_INTEGER * pcbSize)
{
if (pcbSize)
{
pcbSize->HighPart = 0;
pcbSize->LowPart = MAX_STREAM_SIZE;
}
return E_NOTIMPL;
}
/////////////////////////////////
////// IDataObject Impl
/////////////////////////////////
/*****************************************************************************\
FUNCTION: IDataObject::GetData
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -