📄 ftpdrop.cpp
字号:
hr = _CopyOneHdrop(szFSSource, szFtpDest);
if (EVAL(m_ppd))
EVAL(SUCCEEDED(m_ppd->SetProgress64(m_uliBytesCompleted.QuadPart, m_uliBytesTotal.QuadPart)));
// Did we fail to copy the file?
if (FAILED(hr) && (HRESULT_FROM_WIN32(ERROR_CANCELLED) != hr))
{
if (!IsValidFtpAnsiFileName(szFSSource) || !IsValidFtpAnsiFileName(szFtpDest))
int nResult = DisplayWininetError(m_hwnd, TRUE, HRESULT_CODE(hr), IDS_FTPERR_TITLE_ERROR, IDS_FTPERR_INVALIDFTPNAME, IDS_FTPERR_WININET, MB_OK, m_ppd);
else
int nResult = DisplayWininetError(m_hwnd, TRUE, HRESULT_CODE(hr), IDS_FTPERR_TITLE_ERROR, IDS_FTPERR_FILECOPY, IDS_FTPERR_WININET, MB_OK, m_ppd);
hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
}
if (S_FALSE == hr)
{
// _CopyOneHdrop() returning S_FALSE means we hit the end of the iteration,
// in this case, _ConfirmCopy() only meant to skip this one file, so
// change to S_OK to continue with the rest of the files.
hr = S_OK;
}
}
}
Str_SetPtr((LPTSTR *) &m_pszzFSSource, NULL);
Str_SetPtr((LPTSTR *) &m_pszzFtpDest, NULL);
return hr;
}
HRESULT CDropOperation::_ConfirmCopy(LPCWSTR pszLocal, LPCWSTR pszFtpName, BOOL * pfFireChangeNotify)
{
return ConfirmCopy(pszLocal, pszFtpName, &m_ops, m_hwnd, m_pff, m_pfd, NULL, m_cobj, pfFireChangeNotify);
}
/*****************************************************************************\
CopyCB
Callback procedure that copies a single hdrop / map.
\*****************************************************************************/
HRESULT CDropOperation::CopyCB(HINTERNET hint, HINTPROCINFO * phpi, LPVOID pv, BOOL * pfReleaseHint)
{
LPCOPYONEHDROPINFO pcohi = (LPCOPYONEHDROPINFO) pv;
pcohi->progInfo.hint = hint;
HRESULT hr;
InternetSetStatusCallbackWrap(hint, TRUE, FtpProgressInternetStatusCB);
hr = CopyFileSysItem(hint, phpi, pcohi);
if (!pcohi->progInfo.hint)
*pfReleaseHint = FALSE; // We had to close hint to get the cancel.
return hr;
}
HRESULT CDropOperation::_CopyOneHdrop(LPCWSTR pszFSSource, LPCWSTR pszFtpDest)
{
HRESULT hr;
BOOL fFireChangeNotify = TRUE;
pszFtpDest = PathFindFileName(pszFtpDest);
hr = _ConfirmCopy(pszFSSource, pszFtpDest, &fFireChangeNotify);
if (S_OK == hr)
{
WCHAR wzTo[MAX_PATH];
COPYONEHDROPINFO cohi = {0};
cohi.pff = m_pff;
cohi.pszFSSource = pszFSSource;
cohi.pszFtpDest = pszFtpDest;
cohi.pszDir = wzTo;
cohi.dwOperation = COHDI_COPY_FILES;
cohi.ops = m_ops;
cohi.fIsRoot = TRUE;
cohi.pmlc = &m_mlc;
cohi.pidlServer = FtpCloneServerID(m_pff->GetPrivatePidlReference());
cohi.fFireChangeNotify = fFireChangeNotify;
cohi.progInfo.ppd = m_ppd;
cohi.progInfo.uliBytesCompleted.QuadPart = m_uliBytesCompleted.QuadPart;
cohi.progInfo.uliBytesTotal.QuadPart = m_uliBytesTotal.QuadPart;
EVAL(SUCCEEDED(m_pfd->GetDisplayPath(wzTo, ARRAYSIZE(wzTo))));
// TODO: have CopyCB also update the dialog.
hr = m_pfd->WithHint(NULL, m_hwnd, CopyCB, &cohi, NULL, m_pff);
if (SUCCEEDED(hr) && (m_de == DROPEFFECT_MOVE))
{
// We delete the file with SHFileOperation to keep the
// disk free space statistics up to date.
//
// BUGBUG -- If coming from a file name map, maybe it's
// being dragged from the recycle bin, in which case, doing
// an FO_DELETE will put it back in!
SHFILEOPSTRUCT sfo = {0};
sfo.hwnd = NULL, // No HWND so NO UI.
sfo.wFunc = FO_DELETE;
sfo.pFrom = pszFSSource; // Multiple files in list.
sfo.fFlags = (FOF_SILENT | FOF_NOCONFIRMATION /*| FOF_MULTIDESTFILES*/); // No HWND so NO UI.
int nResult = SHFileOperation(&sfo);
if (0 != nResult)
TraceMsg(TF_ALWAYS, "In CDropOperation::_CopyOneHdrop() and caller wanted MOVE but we couldn't delete the files after the copy.");
}
m_uliBytesCompleted = cohi.progInfo.uliBytesCompleted;
m_uliBytesTotal = cohi.progInfo.uliBytesTotal;
m_ops = cohi.ops;
}
else
{
if (S_FALSE == hr)
{
// _CopyOneHdrop() returning S_FALSE means we hit the end of the iteration,
// in this case, _ConfirmCopy() only meant to skip this one file, so
// change to S_OK to continue with the rest of the files.
hr = S_OK;
}
}
return hr;
}
/*****************************************************************************
FUNCTION: SetEffect
DESCRIPTION:
Set the appropriate drop effect feedback.
In the absence of keyboard modifiers, use CTRL (copy), unless
DROPEFFECT_COPY is not available, in which case we use SHIFT (move).
If anything else is set, then panic out to DROPEFFECT_NONE.
Note that we do *not* use g_cfPreferredDe. The only things
we support are DROPEFFECT_COPY and DROPEFFECT_MOVE, and we always prefer DROPEFFECT_COPY.
BUGBUG -- ignoring g_cfPreferredDe messes up cut/paste, though.
*****************************************************************************/
HRESULT CFtpDrop::SetEffect(DROPEFFECT * pde)
{
DWORD de; // Preferred drop effect
// Don't even think about effects that we don't support
*pde &= m_grfksAvail;
switch (m_grfks & (MK_SHIFT | MK_CONTROL))
{
case 0: // No modifier, use COPY if possible
if (*pde & DROPEFFECT_COPY)
{
case MK_CONTROL:
de = DROPEFFECT_COPY;
}
else
{
case MK_SHIFT:
de = DROPEFFECT_MOVE;
}
break;
default:
de = 0;
break; // Cannot link
}
*pde &= de;
TraceMsg(TF_FTPDRAGDROP, "CFtpDrop::SetEffect(DROPEFFECT=%08x) m_grfksAvail=%08x", *pde, m_grfksAvail);
return S_OK;
}
BOOL CFtpDrop::_IsFTPOperationAllowed(IDataObject * pdto)
{
#ifdef FEATURE_FTP_TO_FTP_COPY
BOOL fIsFTPOperationAllowed = TRUE;
// There are a few things we don't allow.
// Is the Drop FTP Location the same
// folder that the dragged items are already in?
if (0)
{
// TODO:
}
return fIsFTPOperationAllowed;
#else // FEATURE_FTP_TO_FTP_COPY
// Disallow all FTP Operations
return !_HasData(pdto, &g_dropTypes[DROP_FTP_PRIVATE]);
#endif // FEATURE_FTP_TO_FTP_COPY
}
/*****************************************************************************\
GetEffectsAvail
Look at the object to see what drop effects are available.
If we have a file group descriptor or an HDROP,
then file contents are available. (We assume that if you have
a FGD, then a Contents isn't far behind.)
In a perfect world, we would also validate the contents of
each file in the group descriptor, to ensure that the contents
are droppable. We skimp on that because it's too expensive.
\*****************************************************************************/
DWORD CFtpDrop::GetEffectsAvail(IDataObject * pdto)
{
DWORD grfksAvail = 0;
// Is this from an Ftp Shell Extension?
if (_IsFTPOperationAllowed(pdto))
{
// No or it's allowed, then we will accept it. We reject everything
// else because we can't do Ftp1->Ftp2 copying without
// using the local machine as a temp location. (Ftp1->Local->Ftp2)
if (_HasData(pdto, &g_dropTypes[DROP_Hdrop]) ||
_HasData(pdto, &g_dropTypes[DROP_FGDW]) ||
_HasData(pdto, &g_dropTypes[DROP_FGDA]))
{
TraceMsg(TF_FTPDRAGDROP, "CFtpDrop::GetEffectsAvail() SUCCEEDED");
grfksAvail = DROPEFFECT_COPY + DROPEFFECT_MOVE;
}
else
{
TraceMsg(TF_FTPDRAGDROP, "CFtpDrop::GetEffectsAvail() FAILED");
#ifdef DEBUG
STGMEDIUM sm;
HRESULT hres = pdto->GetData(&g_dropTypes[DROP_URL], &sm);
if (SUCCEEDED(hres))
{
TraceMsg(TF_FTPDRAGDROP, "CFtpDrop::GetEffectsAvail(%08x) URL: %hs", pdto, GlobalLock(sm.hGlobal));
GlobalUnlock(sm.hGlobal);
ReleaseStgMedium(&sm);
}
else
{
TraceMsg(TF_FTPDRAGDROP, "CFtpDrop::GetEffectsAvail(%08x) No URL", pdto);
}
#endif // DEBUG
}
}
return grfksAvail;
}
/*****************************************************************************\
GetEffect
Return the drop effect to use.
If this is a nondefault drag/drop, then put up a menu. Else,
just go with the default.
m_de = default effect
m_pde -> possible effects (and receives result)
\*****************************************************************************/
DROPEFFECT CFtpDrop::GetEffect(POINTL pt)
{
TraceMsg(TF_FTPDRAGDROP, "CFtpDrop::GetEffect() m_de=%08x. m_grfks=%08x", m_de, m_grfks);
if (m_de && (m_grfks & MK_RBUTTON))
{
HMENU hmenuMain = LoadMenu(g_hinst, MAKEINTRESOURCE(IDM_DROPCONTEXT));
HMENU hmenu = GetSubMenu(hmenuMain, 0);
DROPEFFECT de;
ASSERT(*m_pde & m_de);
SetMenuDefaultItem(hmenu, m_de, 0);
if (!(*m_pde & DROPEFFECT_COPY))
DeleteMenu(hmenu, DROPEFFECT_COPY, MF_BYCOMMAND);
if (!(*m_pde & DROPEFFECT_MOVE))
DeleteMenu(hmenu, DROPEFFECT_MOVE, MF_BYCOMMAND);
// _UNOBVIOUS_: Defview is incestuous with itself.
// If the drop target originated from Shell32.dll, then
// it leaves the image of the dropped object on the screen
// while the menu is up, which is nice. Otherwise, it removes
// the image of the dropped object before the drop target
// receives its IDropTarget::Drop.
// Which means that outside shell extensions can't take
// advantage of the "pretty drop UI" feature.
// _UNOBVIOUS_: Have to force foregroundness, else the input
// gets screwed up.
if (m_hwnd)
SetForegroundWindow(m_hwnd);
de = TrackPopupMenuEx(hmenu,
TPM_RETURNCMD | TPM_RIGHTBUTTON | TPM_VERTICAL |
TPM_LEFTALIGN | TPM_TOPALIGN, pt.x, pt.y,
m_hwnd, 0);
DestroyMenu(hmenuMain);
m_de = de;
}
*m_pde = m_de;
TraceMsg(TF_FTPDRAGDROP, "CFtpDrop::GetEffect(%08x) -> %08x", this, m_de);
return m_de;
}
/****************************************************\
FUNCTION: _StartBackgroundInteration
DESCRIPTION:
\****************************************************/
HRESULT CFtpDrop::_StartBackgroundInteration(void)
{
CDropOperation * pDropOperation;
HRESULT hr = CDropOperation_Create(m_pff, m_hwnd, m_pszzFSSource, m_pszzFtpDest, &pDropOperation, m_de, m_ops, m_cobj);
// Did it succeed?
if (EVAL(SUCCEEDED(hr)))
{
// Yes, so NULL out m_pszzFSSource, m_pszzFtpDest because we gave them our copies.
// Ugly but allocation is uglier.
m_pszzFSSource = NULL;
m_pszzFtpDest = NULL;
EVAL(SUCCEEDED(hr = pDropOperation->DoOperation(TRUE)));
pDropOperation->Release();
}
return hr;
}
/****************************************************\
FUNCTION: _DoCountIteration
DESCRIPTION:
\****************************************************/
HRESULT CFtpDrop::_DoCountIteration(void)
{
HRESULT hr = S_OK;
LPCTSTR pszzFSSource = m_pszzFSSource;
LPCTSTR pszzFtpDest = m_pszzFtpDest;
while (S_OK == hr)
{
TCHAR szFSSource[MAX_PATH];
TCHAR szFtpDest[MAX_PATH];
hr = _EnumOneHdrop(&pszzFSSource, &pszzFtpDest, szFSSource, ARRAYSIZE(szFSSource), szFtpDest, ARRAYSIZE(szFtpDest));
if (S_OK == hr)
m_cobj++;
}
if (hr == S_FALSE)
hr = S_OK; // Enumerated to completion
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -