⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftpdrop.cpp

📁 很好用的ftp源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:

    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 CDropOperation          : public IUnknown
{
public:
    //////////////////////////////////////////////////////
    // Public Interfaces
    //////////////////////////////////////////////////////
    
    // *** IUnknown ***
    virtual STDMETHODIMP_(ULONG) AddRef(void);
    virtual STDMETHODIMP_(ULONG) Release(void);
    virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);

public:
    CDropOperation();
    ~CDropOperation(void);

    // Public Member Functions
    HRESULT DoOperation(BOOL fAsync);

    static HRESULT CopyCB(HINTERNET hint, HINTPROCINFO * phpi, LPVOID pv, BOOL * pfReleaseHint);

    // Friend Functions
    friend HRESULT CDropOperation_Create(CFtpFolder * pff, HWND hwnd, LPCTSTR pszzFSSource, LPCTSTR pszzFtpDest, CDropOperation ** ppfdt, DROPEFFECT de, OPS ops, int cobj);

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

    DROPEFFECT              m_de;           // Effect being performed
    OPS                     m_ops;          // Overwrite prompting state
    int                     m_cobj;         // Number of objects being dropped
    ULARGE_INTEGER          m_uliBytesCompleted;
    ULARGE_INTEGER          m_uliBytesTotal;


    // Private Member Functions
    HRESULT _ConfirmCopy(LPCWSTR pszLocal, LPCWSTR psz, BOOL * pfFireChangeNotify);
    HRESULT _CalcSizeOneHdrop(LPCWSTR pszFSSource, LPCWSTR pszFtpDest, IProgressDialog * ppd);
    HRESULT _ThreadProcCB(void);
    HRESULT _CopyOneHdrop(LPCWSTR pszFSSource, LPCWSTR pszFtpDest);

    HRESULT _StartBackgroundInteration(void);
    HRESULT _DoCopyIteration(void);
    HRESULT _CalcUploadProgress(void);

private:
    // Private Member Variables
    IProgressDialog *       m_ppd;
    LPCWSTR                 m_pszzFSSource;            // Paths
    LPCWSTR                 m_pszzFtpDest;              // Map
    CMultiLanguageCache     m_mlc;          // Cache for fast str thunking.

    static DWORD CALLBACK _ThreadProc(LPVOID pThis) {return ((CDropOperation *)pThis)->_ThreadProcCB();};
};


HRESULT CDropOperation_Create(CFtpFolder * pff, HWND hwnd, LPCTSTR pszzFSSource, LPCTSTR pszzFtpDest, CDropOperation ** ppfdt, 
                              DROPEFFECT de, OPS ops, int cobj)
{
    HRESULT hr = E_OUTOFMEMORY;
    CDropOperation * pfdt = new CDropOperation();
    *ppfdt = pfdt;

    if (pfdt)
    {
        pfdt->m_hwnd = hwnd;

        // Copy the CFtpFolder * value
        pfdt->m_pff = pff;
        if (pff)
            pff->AddRef();

        // Copy the CFtpDir * value
        ASSERT(!pfdt->m_pfd);
        pfdt->m_pfd = pff->GetFtpDir();
        ASSERT(pfdt->m_pfd);

        ASSERT(!pfdt->m_pszzFSSource);
        pfdt->m_pszzFSSource = pszzFSSource;

        ASSERT(!pfdt->m_pszzFtpDest);
        pfdt->m_pszzFtpDest = pszzFtpDest;

        pfdt->m_de = de;           // Effect being performed
        pfdt->m_ops = ops;          // Overwrite prompting state
        pfdt->m_cobj = cobj;         // Number of objects being dropped

        hr = S_OK;
    }

    ASSERT_POINTER_MATCHES_HRESULT(*ppfdt, hr);
    return hr;
}


/****************************************************\
    Constructor
\****************************************************/
CDropOperation::CDropOperation() : m_cRef(1)
{
    DllAddRef();

    // This needs to be allocated in Zero Inited Memory.
    // Assert that all Member Variables are inited to Zero.
    ASSERT(!m_pff);
    ASSERT(!m_pfd);
    ASSERT(!m_hwnd);
    ASSERT(!m_cobj);

    LEAK_ADDREF(LEAK_CDropOperation);
}


/****************************************************\
    Destructor
\****************************************************/
CDropOperation::~CDropOperation()
{
    // use ATOMICRELEASE
    IUnknown_Set(&m_pff, NULL);
    IUnknown_Set(&m_pfd, NULL);
    IUnknown_Set((IUnknown **)&m_ppd, NULL);
    Str_SetPtr((LPTSTR *) &m_pszzFSSource, NULL);
    Str_SetPtr((LPTSTR *) &m_pszzFtpDest, NULL);

    DllRelease();
    LEAK_DELREF(LEAK_CDropOperation);
}


//===========================
// *** IUnknown Interface ***
//===========================

ULONG CDropOperation::AddRef()
{
    m_cRef++;
    return m_cRef;
}

ULONG CDropOperation::Release()
{
    ASSERT(m_cRef > 0);
    m_cRef--;

    if (m_cRef > 0)
        return m_cRef;

    delete this;
    return 0;
}

HRESULT CDropOperation::QueryInterface(REFIID riid, void **ppvObj)
{
    if (IsEqualIID(riid, IID_IUnknown))
    {
        *ppvObj = SAFECAST(this, IUnknown*);
    }
    else
    {
        TraceMsg(TF_FTPQI, "CDropOperation::QueryInterface() failed.");
        *ppvObj = NULL;
        return E_NOINTERFACE;
    }

    AddRef();
    return S_OK;
}




/****************************************************\
    FUNCTION: _ThreadProcCB

    DESCRIPTION:
\****************************************************/
HRESULT CDropOperation::_ThreadProcCB(void)
{
    HRESULT hr;
    HRESULT hrOleInit = SHCoInitialize();
    
    // WARNING: Init OLE if you plan to do COM.
    m_ppd = CProgressDialog_CreateInstance(IDS_COPY_TITLE, IDA_FTPUPLOAD);
    if (EVAL(m_ppd))
    {
        ASSERT(m_hwnd);
        // We give a NULL punkEnableModless because we don't want to go modal.
        EVAL(SUCCEEDED(m_ppd->StartProgressDialog(m_hwnd, NULL, PROGDLG_AUTOTIME, NULL)));
    }

    hr = _CalcUploadProgress();
    // Did we succeed creating the directories and counting the
    // size we need to copy?
    if (SUCCEEDED(hr))
    {
        if (m_ppd)
        {
            EVAL(SUCCEEDED(m_ppd->SetProgress64(m_uliBytesCompleted.QuadPart, m_uliBytesTotal.QuadPart)));

            // Reset because _CalcUploadProgress() 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)));
        }

        hr = _DoCopyIteration();
    }

    if (m_ppd)
    {
        EVAL(SUCCEEDED(m_ppd->StopProgressDialog()));
        ATOMICRELEASE(m_ppd);
    }

    SHCoUninitialize(hrOleInit);
    Release();
    return hr;
}


HRESULT CDropOperation::DoOperation(BOOL fAsync)
{
    HRESULT hr = S_OK;

    AddRef();
    if (fAsync)
    {
        HANDLE hThread;
        DWORD dwThreadId;

        hThread = CreateThread(NULL, 0, CDropOperation::_ThreadProc, this, 0, &dwThreadId);
        if (hThread)
            CloseHandle(hThread);
        else
        {
            TraceMsg(TF_ERROR, "CDropOperation::DoOperation() CreateThread() failed and GetLastError()=%lu.", GetLastError());
            Release();
        }
    }
    else
        hr = _ThreadProcCB();

    return hr;
}



/****************************************************\
    FUNCTION: _CalcUploadProgress

    DESCRIPTION:
\****************************************************/
HRESULT CDropOperation::_CalcUploadProgress(void)
{
    HRESULT hr = S_OK;
    LPCWSTR pszzFSSource = m_pszzFSSource;
    LPCWSTR pszzFtpDest = m_pszzFtpDest;
    WCHAR wzProgressDialogStr[MAX_PATH];

    m_uliBytesCompleted.QuadPart = 0;
    m_uliBytesTotal.QuadPart = 0;
    
    // Tell the user we are calculating how long it will take.
    if (EVAL(LoadStringW(HINST_THISDLL, IDS_PROGRESS_UPLOADTIMECALC, wzProgressDialogStr, ARRAYSIZE(wzProgressDialogStr))))
        EVAL(SUCCEEDED(m_ppd->SetLine(2, wzProgressDialogStr, FALSE, NULL)));

    while (S_OK == hr)
    {
        WCHAR szFSSource[MAX_PATH];
        WCHAR szFtpDest[MAX_PATH];

        hr = _EnumOneHdrop(&pszzFSSource, &pszzFtpDest, szFSSource, ARRAYSIZE(szFSSource), szFtpDest, ARRAYSIZE(szFtpDest));
        if (S_OK == hr)
            hr = _CalcSizeOneHdrop(szFSSource, szFtpDest, m_ppd);
    }

    if (FAILED(hr))
        TraceMsg(TF_ALWAYS, "CDropOperation::_CalcUploadProgress() Calculating the upload time failed, but oh well.");

    return hr;
}


HRESULT CDropOperation::_CalcSizeOneHdrop(LPCWSTR pszFSSource, LPCWSTR pszFtpDest, IProgressDialog * ppd)
{
    HRESULT hr;
    WCHAR wzTo[MAX_PATH];

    EVAL(SUCCEEDED(m_pfd->GetDisplayPath(wzTo, ARRAYSIZE(wzTo))));
    pszFtpDest = PathFindFileName(pszFtpDest);

    COPYONEHDROPINFO cohi = {0};

    cohi.pff = m_pff;
    cohi.pszFSSource = pszFSSource;
    cohi.pszFtpDest = pszFtpDest;
    cohi.pszDir = wzTo;
    cohi.dwOperation = COHDI_FILESIZE_COUNT;
    cohi.ops = opsPrompt;
    cohi.fIsRoot = TRUE;
    cohi.pmlc = &m_mlc;
    cohi.pidlServer = FtpCloneServerID(m_pff->GetPrivatePidlReference());
    cohi.progInfo.ppd = ppd;
    cohi.fFireChangeNotify = TRUE;

    cohi.progInfo.uliBytesCompleted.QuadPart = m_uliBytesCompleted.QuadPart;
    cohi.progInfo.uliBytesTotal.QuadPart = m_uliBytesTotal.QuadPart;

    hr = m_pfd->WithHint(NULL, m_hwnd, CopyCB, &cohi, NULL, m_pff);
    if (SUCCEEDED(hr))
    {
        m_uliBytesCompleted = cohi.progInfo.uliBytesCompleted;
        m_uliBytesTotal = cohi.progInfo.uliBytesTotal;
    }

    ILFree(cohi.pidlServer);
    return hr;
}


/****************************************************\
    FUNCTION: CDropOperation

    DESCRIPTION:
\****************************************************/
HRESULT CDropOperation::_DoCopyIteration()
{
    HRESULT hr = S_OK;
    LPCTSTR pszzFSSource = m_pszzFSSource;
    LPCTSTR pszzFtpDest = m_pszzFtpDest;

    m_ops = opsPrompt;
    while (S_OK == hr)
    {
        WCHAR szFSSource[MAX_PATH];
        WCHAR szFtpDest[MAX_PATH];

        hr = _EnumOneHdrop(&pszzFSSource, &pszzFtpDest, szFSSource, ARRAYSIZE(szFSSource), szFtpDest, ARRAYSIZE(szFtpDest));
        if (S_OK == hr)
        {
            szFSSource[lstrlenW(szFSSource)+1] = 0;   // Double terminate for SHFileOperation(Delete) in move case

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -