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

📄 ftpobj.cpp

📁 很好用的ftp源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/*****************************************************************************
 *
 *    ftpobj.cpp - IDataObject interface
 *
 *****************************************************************************/

#include "priv.h"
#include "ftpobj.h"
#include "ftpurl.h"
#include <shlwapi.h>


// CLSIDs
// {299D0193-6DAA-11d2-B679-006097DF5BD4}
const GUID CLSID_FtpDataObject = { 0x299d0193, 0x6daa, 0x11d2, 0xb6, 0x79, 0x0, 0x60, 0x97, 0xdf, 0x5b, 0xd4 };

/*****************************************************************************
 *
 *    g_dropTypes conveniently mirrors our FORMATETCs.
 *
 *    Hardly coincidence, of course.  Enum_Fe did the real work.
 *
 *****************************************************************************/

/*****************************************************************************
 *
 *    Preinitialized global data.
 *
 *****************************************************************************/
FORMATETC g_formatEtcOffsets;
FORMATETC g_formatPasteSucceeded;
CLIPFORMAT g_cfTargetCLSID;

FORMATETC g_dropTypes[] =
{
    { 0, 0, DVASPECT_CONTENT, -1, TYMED_ISTREAM },  // DROP_FCont
    { 0, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },  // DROP_FGDW
    { 0, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },  // DROP_FGDA
    { 0, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },  // DROP_IDList
    { 0, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },  // DROP_URL
//    { 0, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },  // DROP_Offsets
    { 0, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },  // DROP_PrefDe
    { 0, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },  // DROP_PerfDe
    { 0, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },  // DROP_FTP_PRIVATE
    { 0, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },  // DROP_OLEPERSIST - see _RenderOlePersist() for desc.
    { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL },  // DROP_Hdrop
    { 0, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }, // DROP_FNMA
    { 0, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }  // DROP_FNMW
};



/*****************************************************************************\
    GLOBAL: c_stgInit

    DESCRIPTION:
        Mostly straightforward.  The only major weirdness is that cfURL
    is delay-rendered iff the m_pflHfpl contains only one object.  Otherwise,
    cfURL is not supported.  (URLs can refer to only one object at a time.)
\*****************************************************************************/
STGMEDIUM c_stgInit[] =
{
    { 0, 0, 0 },  // DROP_FCont
    { TYMED_HGLOBAL, 0, 0 },    // DROP_FGDW - delay-rendered
    { TYMED_HGLOBAL, 0, 0 },    // DROP_FGDA - delay-rendered
    { TYMED_HGLOBAL, 0, 0 },    // DROP_IDList - delay-rendered
    { 0, 0, 0 },                // DROP_URL - opt delay-rendered
//    { 0, 0, 0 },                // DROP_Offsets
    { TYMED_HGLOBAL, 0, 0 },    // DROP_PrefDe - delay-rendered
    { 0, 0, 0 },                // DROP_PerfDe
    { TYMED_HGLOBAL, 0, 0 },    // DROP_FTP_PRIVATE
    { TYMED_HGLOBAL, 0, 0 },    // DROP_OLEPERSIST - see _RenderOlePersist() for desc.
    { 0, 0, 0 },                // DROP_Hdrop
    { 0, 0, 0 },                // DROP_FNMA
    { 0, 0, 0 }                 // DROP_FNMW
};



/*****************************************************************************\
    FUNCTION: TraceMsgWithFormatEtc

    DESCRIPTION:
\*****************************************************************************/
void TraceMsgWithFormat(DWORD dwFlags, LPCSTR pszBefore, LPFORMATETC pFormatEtc, LPCSTR pszAfter, HRESULT hr)
{
#ifdef DEBUG
    TCHAR szFormatName[MAX_PATH];
    TCHAR szMedium[MAX_PATH];

    szFormatName[0] = 0;
    szMedium[0] = 0;
    if (pFormatEtc)
    {
        // This may fail if it's a basic format.
        if (!GetClipboardFormatName(pFormatEtc->cfFormat, szFormatName, ARRAYSIZE(szFormatName)))
            wnsprintf(szFormatName, ARRAYSIZE(szFormatName), TEXT("Pre-defined=%d"), pFormatEtc->cfFormat);

        switch (pFormatEtc->tymed)
        {
        case TYMED_HGLOBAL: StrCpyN(szMedium, TEXT("HGLOBAL"), ARRAYSIZE(szMedium)); break;
        case TYMED_FILE: StrCpyN(szMedium, TEXT("File"), ARRAYSIZE(szMedium)); break;
        case TYMED_GDI: StrCpyN(szMedium, TEXT("GDI"), ARRAYSIZE(szMedium)); break;
        case TYMED_MFPICT: StrCpyN(szMedium, TEXT("MFPICT"), ARRAYSIZE(szMedium)); break;
        case TYMED_ENHMF: StrCpyN(szMedium, TEXT("ENHMF"), ARRAYSIZE(szMedium)); break;
        case TYMED_ISTORAGE: StrCpyN(szMedium, TEXT("ISTORAGE"), ARRAYSIZE(szMedium)); break;
        case TYMED_ISTREAM: StrCpyN(szMedium, TEXT("ISTREAM"), ARRAYSIZE(szMedium)); break;
        }
    }
    else
    {
        szMedium[0] = 0;
    }

    TraceMsg(dwFlags, "%hs [FRMTETC: %ls, lndx: %d, %ls] hr=%#08lx, %hs", pszBefore, szFormatName, pFormatEtc->lindex, szMedium, hr, pszAfter);
#endif // DEBUG
}


/*****************************************************************************\
    FUNCTION: _IsLindexOkay
 
   DESCRIPTION:
    If ife != DROP_FCont, then pfeWant->lindex must be -1.
 
    If ife == DROP_FCont, then pfeWant->lindex must be in the range
    0 ... m_pflHfpl->GetCount() - 1
\*****************************************************************************/
BOOL CFtpObj::_IsLindexOkay(int ife, FORMATETC *pfeWant)
{
    BOOL fResult;

    if (ife != DROP_FCont)
        fResult = pfeWant->lindex == -1;
    else
        fResult = (LONG)pfeWant->lindex < m_pflHfpl->GetCount();

    return fResult;
}


/*****************************************************************************\
    FUNCTION: _FindData

    DESCRIPTION:
        Locate our FORMATETC/STGMEDIUM given a FORMATETC from somebody else.
    On success, stores the index found into *piOut.
 
    We do not allow clients to change the TYMED of a FORMATETC, so
    in fact checking the TYMED is what we want, even on a SetData.
\*****************************************************************************/
HRESULT CFtpObj::_FindData(FORMATETC *pfe, PINT piOut)
{
    int nIndex;
    HRESULT hres = DV_E_FORMATETC;

    *piOut = 0;
    for (nIndex = DROP_FCont; nIndex < DROP_OFFERMAX; nIndex++)
    {
        ASSERT(0 == (g_dropTypes[nIndex]).ptd);
        ASSERT(g_dropTypes[nIndex].dwAspect == DVASPECT_CONTENT);

        if ((pfe->cfFormat == g_dropTypes[nIndex].cfFormat) && !ShouldSkipDropFormat(nIndex))
        {
            if (EVAL(g_dropTypes[nIndex].ptd == NULL))
            {
                if (EVAL(pfe->dwAspect == DVASPECT_CONTENT))
                {
                    if (EVAL(g_dropTypes[nIndex].tymed & pfe->tymed))
                    {
                        if (EVAL(_IsLindexOkay(nIndex, pfe)))
                        {
                            *piOut = nIndex;
                            hres = S_OK;
                        }
                        else
                            hres = DV_E_LINDEX;
                    }
                    else
                        hres = DV_E_TYMED;
                }
                else
                    hres = DV_E_DVASPECT;
            }
            else
                hres = DV_E_DVTARGETDEVICE;
            break;
        }
    }

    return hres;
}


/*****************************************************************************\
    FUNCTION: _FindDataForGet
 
    DESCRIPTION:
        Locate our FORMATETC/STGMEDIUM given a FORMATETC from somebody else.
    On success, stores the index found into *piOut.  Unlike _FindData, we will
    fail the call if the data object doesn't currently have the clipboard format.
    (Delayed render counts as "currently having it".  What we are filtering out
    are formats for which GetData will necessarily fail.)
\*****************************************************************************/
HRESULT CFtpObj::_FindDataForGet(FORMATETC *pfe, PINT piOut)
{
    HRESULT hr = _FindData(pfe, piOut);

    // TODO: g_cfHIDA should return an array of pidls for each folder.
    //       If we do this, the caller will support creating Shortcuts
    //       (LNK files) that point to these pidls.  We may want to do 
    //       that later.

    if (SUCCEEDED(hr))
    {
        if (*piOut != DROP_FCont)
        {
            if (m_stgCache[*piOut].tymed)
            {
                // Do we have data at all?
                // (possibly delay-rendered)
            }
            else
                hr = DV_E_FORMATETC;        // I guess not
        }
        else
        {
            // File contents always okay
        }
    }

#ifdef DEBUG
    if (FAILED(hr))
    {
        //TraceMsg(TF_FTPDRAGDROP, "CFtpObj::_FindDataForGet(FORMATETC.cfFormat=%d) Failed.", pfe->cfFormat);
        *piOut = 0xBAADF00D;
    }
#endif

    return hr;
}


// The following are used to enumerate sub directories when creating a list of pidls for
// a directory download (Ftp->FileSys).
typedef struct tagGENPIDLLIST
{
    CFtpPidlList *      ppidlList;
    IMalloc *           pm;
    IProgressDialog *   ppd;
    CWireEncoding *     pwe;
} GENPIDLLIST;


/*****************************************************************************\
     FUNCTION: ProcessItemCB
 
    DESCRIPTION:
        This function will add the specified pidl to the list.  It will then
    detect if it's a folder and if so, will call EnumFolder() to recursively
    enum it's contents and call ProcessItemCB() for each one.
 
    PARAMETERS:
\*****************************************************************************/
HRESULT ProcessItemCB(LPVOID pvFuncCB, HINTERNET hint, LPCITEMIDLIST pidlFull, BOOL * pfValidhinst, LPVOID pvData)
{
    GENPIDLLIST * pGenPidlList = (GENPIDLLIST *) pvData;
    HRESULT hr = S_OK;

    // Does the user want to cancel?
    if (pGenPidlList->ppd && pGenPidlList->ppd->HasUserCancelled())
    {
        EVAL(SUCCEEDED(pGenPidlList->ppd->StopProgressDialog()));
        hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
    }

    if (SUCCEEDED(hr))
    {
        // No, don't cancel so continue...

        // Add everything except SoftLinks.
        // This is because dir SoftLinks may cause infinite recurion.
        // Someday, we may want to upload a shortcut but
        // that's too much work for now.
        if (0 != FtpPidl_GetAttributes(pidlFull))
        {
            // We exist to do this:
            pGenPidlList->ppidlList->InsertSorted(pidlFull);
        }

        // Is this a dir/folder that we need to recurse into?
        if (SUCCEEDED(hr) && (FILE_ATTRIBUTE_DIRECTORY & FtpPidl_GetAttributes(pidlFull)))
        {
            hr = EnumFolder((LPFNPROCESSITEMCB) pvFuncCB, hint, pidlFull, pGenPidlList->pwe, pfValidhinst, pvData);
        }
    }

    return hr;
}


/*****************************************************************************\
     FUNCTION: _ExpandPidlListRecursively
 
    DESCRIPTION:
        This function will take the pidl list (ppidlListSrc) and call into it
    to enumerate.  It will provide ProcessItemCB as the callback function.
    This function will help it create a new CFtpPidlList which will not only
    contain the pidls in a base folder, but also all the pidls in any subfolders
    that are in the original list.

    Delay-render a file group descriptor.
\*****************************************************************************/
CFtpPidlList * CFtpObj::_ExpandPidlListRecursively(CFtpPidlList * ppidlListSrc)
{
    GENPIDLLIST pep = {0};

    pep.ppidlList = NULL;
    pep.ppd = m_ppd;
    pep.pwe = m_pff->GetCWireEncoding();
    if (SUCCEEDED(CFtpPidlList_Create(0, NULL, &pep.ppidlList)))
    {
        m_pff->GetItemAllocator(&pep.pm);

        if (EVAL(m_pfd) && EVAL(pep.pm))
        {
            HINTERNET hint;

            if (SUCCEEDED(m_pfd->GetHint(NULL, NULL, &hint, NULL, m_pff)))
            {
                LPITEMIDLIST pidlRoot = ILClone(m_pfd->GetPidlReference());

                if (EVAL(pidlRoot))
                {
                    HRESULT hr = ppidlListSrc->RecursiveEnum(pidlRoot, ProcessItemCB, hint, (LPVOID) &pep);
                   
                    if (m_ppd)
                        EVAL(SUCCEEDED(m_ppd->StopProgressDialog()));

                    if (FAILED(hr) && (HRESULT_FROM_WIN32(ERROR_CANCELLED) != hr) && !m_fErrAlreadyDisplayed)
                    {
                        pep.ppidlList->Release();
                        pep.ppidlList = NULL;

                        // Oh, I want a real hwnd, but where or where can I get one?
                        DisplayWininetErrorEx(NULL, TRUE, HRESULT_CODE(hr), IDS_FTPERR_TITLE_ERROR, IDS_FTPERR_DROPFAIL, IDS_FTPERR_WININET, MB_OK, NULL, NULL);
                        hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);  // Wrong permissions

                        // We need to suppress subsequent error dlgs from this location
                        // because callers like to ask for FILEGROUPDESCRIPTORA and
                        // if that fails, ask for FILEGROUPDESCRIPTORW and we don't
                        // want an error dialog for each.
                        m_fErrAlreadyDisplayed = TRUE;
                    }

                    ILFree(pidlRoot);
                }

                m_pfd->ReleaseHint(hint);
                pep.pm->Release();
            }
        }
    }

    return pep.ppidlList;
}


/*****************************************************************************\
    FUNCTION: _DelayRender_FGD

    DESCRIPTION:
        Delay-render a file group descriptor
\*****************************************************************************/
HGLOBAL CFtpObj::_DelayRender_FGD(BOOL fUnicode)
{
    HGLOBAL hGlobal = NULL;
    
    if (m_fCheckSecurity &&
        ZoneCheckPidlAction(SAFECAST(this, IInternetSecurityMgrSite *), URLACTION_SHELL_FILE_DOWNLOAD, m_pff->GetPrivatePidlReference(), (PUAF_DEFAULT | PUAF_WARN_IF_DENIED)))
    {
        m_pflHfpl->TraceDump(m_pff->GetPrivatePidlReference(), TEXT("_DelayRender_FGD() TraceDump before"));
        CFtpPidlList * pPidlList;
    
        if (!m_fFGDRendered)
        {
            pPidlList = _ExpandPidlListRecursively(m_pflHfpl);
            if (pPidlList)
            {
                // We succeeded so now it's expanded.
                m_fFGDRendered = TRUE;
            }
        }
        else

⌨️ 快捷键说明

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