windows-nt/Source/XPSP1/NT/shell/ext/ftp/ftpdrop.h
2020-09-26 16:20:57 +08:00

188 lines
8.4 KiB
C++

/*****************************************************************************\
FILE: ftpdrop.h - IDropTarget interface
Remarks:
Note that you cannot create a shortcut on an FTP site. Although
there's nothing technically preventing it, it's not done because
the shortcut won't be of much use on an FTP site. (It points to
your local machine, which doesn't help much for people not on the
same network!)
If you really want to put a shortcut file on an FTP site, create
it on the desktop, then drag the shortcut onto the FTP site.
The default verb for FTP sites is always "Copy". This is true
even if an intra-site drag-drop is being done.
DESCRIPTION:
DefView will cache the IDropTarget pointer (CFtpDrop) for a shell extension.
When it calls CFtpDrop::Drop(), the work needs to be done on a background
thread in order to not block the UI thread. The problem is that if the user
does another drag to the same Ftp Window, CFtpDrop::Drop() will be called again.
For this reasons, CFtpDrop::Drop() cannot have any state after it returns.
In order to accomplish this with the asynch background thread, we have
CFtpDrop::Drop() call CDropOperation_Create(), and then CDropOperation->DoOperation().
And then it will orphan (call Release()) the CDropOperation. The CDropOperation
will then destroy itself when the copy is finishes. This enables subsequent calls
to CFtpDrop::Drop() to spawn separate CDropOperation objects so each can maintain
the state for that specifc operation and CFtpDrop remains stateless.
\*****************************************************************************/
#ifndef _FTPDROP_H
#define _FTPDROP_H
#include "util.h"
typedef enum OPS
{ // Overwrite prompt status
opsPrompt, // Prompt each collision
opsYesToAll, // Overwrite unconditionally
opsNoToAll, // Never overwrite
opsCancel, // Stop the operation
} OPS;
#define COHDI_FILESIZE_COUNT 5
#define COHDI_COPY_FILES 6
typedef struct tagCOPYONEHDROPINFO
{
CFtpFolder * pff;
LPCWSTR pszFSSource;
LPCWSTR pszFtpDest;
LPCWSTR pszDir;
DWORD dwOperation; // COHDI_FILESIZE_COUNT, COHDI_COPY_FILES, etc.
OPS ops;
BOOL fIsRoot;
CMultiLanguageCache * pmlc;
LPITEMIDLIST pidlServer;
BOOL fFireChangeNotify; // Don't fire change notify on BrowserOnly when replacing a file.
PROGRESSINFO progInfo;
} COPYONEHDROPINFO, * LPCOPYONEHDROPINFO;
typedef HRESULT (*STREAMCOPYPROC)(IStream * pstm, DWORD dwFlags, DWORD dwFileSizeHigh, DWORD dwFileSizeLow, LPVOID pv, ULARGE_INTEGER *pqw);
#ifdef UNICODE
#define _EnumOneHdrop _EnumOneHdropW
#else // UNICODE
#define _EnumOneHdrop _EnumOneHdropA
#endif // UNICODE
/*****************************************************************************\
CFtpDrop
de and pde are rather gnarly.
pde is where the output drop effect is kept. A drop handler
can force the effect to be DROPEFFECT_COPY if it encounters a
situation that indicates that the source shouldn't be deleted.
(E.g., if a file is not copied due to an illegal file name.)
de is where the current effect is kept. A drop handler
should consult de to decide whether or not the source
should be deleted. (Used by the HDROP handler, because it is
the drop target's responsibility to delete the source of an
HDROP if applicable.)
You should read from de and write to *pde. Don't
write to de or read from *pde.
The overwrite prompting state tells us how to handle
the case where an incoming file collides with an existing file.
DESCRIPTION:
DefView will cache the IDropTarget pointer (CFtpDrop) for a shell extension.
When it calls CFtpDrop::Drop(), the work needs to be done on a background
thread in order to not block the UI thread. The problem is that if the user
does another drag to the same Ftp Window, CFtpDrop::Drop() will be called again.
For this reasons, CFtpDrop::Drop() cannot have any state after it returns.
In order to accomplish this with the asynch background thread, we have
CFtpDrop::Drop() call CDropOperation_Create(), and then CDropOperation->DoOperation().
And then it will orphan (call Release()) the CDropOperation. The CDropOperation
will then destroy itself when the copy is finishes. This enables subsequent calls
to CFtpDrop::Drop() to spawn separate CDropOperation objects so each can maintain
the state for that specifc operation and CFtpDrop remains stateless.
\*****************************************************************************/
class CFtpDrop : public IDropTarget
{
public:
//////////////////////////////////////////////////////
// Public Interfaces
//////////////////////////////////////////////////////
// *** IUnknown ***
virtual STDMETHODIMP_(ULONG) AddRef(void);
virtual STDMETHODIMP_(ULONG) Release(void);
virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
// *** IDropTarget ***
virtual STDMETHODIMP DragEnter(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
virtual STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
virtual STDMETHODIMP DragLeave(void);
virtual STDMETHODIMP Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
public:
CFtpDrop();
~CFtpDrop(void);
// Public Member Functions
DWORD GetEffectsAvail(IDataObject * pdto);
STDMETHODIMP EnumHdrop(HGLOBAL hdrop, HGLOBAL hmap, BOOL fCopy);
static HRESULT _CopyHglobal(IStream * pstm, DWORD dwFlags, DWORD dwFileSizeHigh, DWORD dwFileSizeLow, LPVOID pvSrc, ULARGE_INTEGER *pqw);
static HRESULT CopyStream(IStream * pstm, DWORD dwFlags, DWORD dwFileSizeHigh, DWORD dwFileSizeLow, LPVOID pvSrc, ULARGE_INTEGER *pqw);
// Friend Functions
friend HRESULT CFtpDrop_Create(CFtpFolder * pff, HWND hwnd, CFtpDrop ** ppfm);
protected:
// Protected Member Variables
int m_cRef;
CFtpFolder * m_pff; // The owner
CFtpDir * m_pfd; // The FtpDir of the owner
HWND m_hwnd; // The window being drug over
DWORD m_grfks; // Last grfKeyState seen
DWORD m_grfksAvail; // Effects available
DROPEFFECT m_de; // Effect being performed
DROPEFFECT * m_pde; // Output effect
OPS m_ops; // Overwrite prompting state
int m_cobj; // Number of objects being dropped
// Private Member Functions
HRESULT SetEffect(DROPEFFECT * pde);
HRESULT _InvokePaste(LPCMINVOKECOMMANDINFO pici);
BOOL _HasData(IDataObject * pdto, FORMATETC * pformatetc) { return (S_OK == pdto->QueryGetData(pformatetc)); };
DROPEFFECT GetEffect(POINTL pt);
HRESULT CopyStorage(LPCTSTR pszFile, IStorage * pstgIn);
HRESULT CopyHdrop(IDataObject * pdto, STGMEDIUM *psm);
HRESULT CopyAsStream(LPCTSTR pszName, DWORD dwFileAttributes, DWORD dwFlags, DWORD dwFileSizeHigh, DWORD dwFileSizeLow, STREAMCOPYPROC pfn, LPVOID pv);
HRESULT CopyFCont(LPCTSTR pszName, DWORD dwFileAttributes, DWORD dwFlags, DWORD dwFileSizeHigh, DWORD dwFileSizeLow, STGMEDIUM *psm);
HRESULT CopyFGD(IDataObject * pdto, STGMEDIUM *psm, BOOL fUnicode);
HRESULT _Copy(IDataObject * pdto);
HRESULT _CopyOneHdrop(LPCTSTR pszFSSource, LPCTSTR pszFtpDest, IProgressDialog * ppd);
HRESULT _StartBackgroundInteration(void);
HRESULT _DoCountIteration(void);
HRESULT _GetFSSourcePaths(HGLOBAL hdrop, BOOL * pfAnsi);
HRESULT _GetFtpDestPaths(HGLOBAL hmap, BOOL fAnsi);
private:
// Private Member Variables
LPCTSTR m_pszzFSSource; // Paths
LPCTSTR m_pszzFtpDest; // Map
HRESULT _CalcSizeOneHdrop(LPCWSTR pszFSSource, LPCWSTR pszFtpDest, IProgressDialog * ppd);
HRESULT _GetFileDescriptor(LONG nIndex, LPFILEGROUPDESCRIPTORW pfgdW, LPFILEGROUPDESCRIPTORA pfgdA, BOOL fUnicode, LPFILEDESCRIPTOR pfd);
HRESULT _CreateFGDDirectory(LPFILEDESCRIPTOR pfd);
BOOL _IsFTPOperationAllowed(IDataObject * pdto);
CFtpDir * _GetRelativePidl(LPCWSTR pszFullPath, DWORD dwFileAttributes, DWORD dwFileSizeHigh, DWORD dwFileSizeLow, LPITEMIDLIST * ppidl);
};
#endif // _FTPDROP_H