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

📄 ftpcm.cpp

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

#include "priv.h"
#include "ftpcm.h"
#include "util.h"
#include "ftpprop.h"
#include "ftpurl.h"
#include "dialogs.h"
#include "statusbr.h"
#include "newmenu.h"
#include "view.h"
#include "resource.h"



/*****************************************************************************\
 *
 *    VERBINFO, c_rgvi
 *
 *    Information about which capabilities correspond to which verbs.
 *
 *    If the item ID is in the range 0 ... IDC_ITEM_MAX, then it is
 *    relative to the base address.
 *
\*****************************************************************************/

#pragma BEGIN_CONST_DATA

#define     CMDSTR_LOGINASA          "Login As"

// BUGBUG -- split into two arrays, cobbled together into a structure

struct VERBINFO
{
    UINT  idc;
    DWORD sfgao;
    LPCTSTR ptszCmd;
} c_rgvi[] = {
/* If you edit anything below this comment, make sure to update below */
    {    IDM_SHARED_EDIT_COPY,    SFGAO_CANCOPY,        TEXT("copy"),     },
#ifdef FEATURE_CUT_MOVE
    {    IDM_SHARED_EDIT_CUT,    SFGAO_CANMOVE,        TEXT("cut"),    },
#endif // FEATURE_CUT_MOVE
    {    IDM_SHARED_FILE_LINK,    SFGAO_CANLINK,        TEXT("link"),     },
    {    IDM_SHARED_FILE_RENAME,    SFGAO_CANRENAME,    TEXT("rename"),    },
    {    IDM_SHARED_FILE_DELETE,    SFGAO_CANDELETE,    TEXT("delete"),    },
    {    IDM_SHARED_FILE_PROP,    SFGAO_HASPROPSHEET,    TEXT("properties"), },
    {    IDM_SHARED_EDIT_PASTE,    SFGAO_DROPTARGET,    TEXT("paste"),    },
/* CVI_NONREQ is the number of items in c_rgvi up to this point */
/* The following entries must be in IDC_ITEM_* order */
    {    IDC_ITEM_OPEN,        SFGAO_FOLDER,        TEXT("open"),    },
    {    IDC_ITEM_EXPLORE,    SFGAO_FOLDER,        TEXT("explore"),},
    {    IDC_ITEM_DOWNLOAD,    SFGAO_CANCOPY,        TEXT("download"),},
    {    IDC_ITEM_BKGNDPROP,    0,                    TEXT("backgroundproperties"),},
    {    IDC_LOGIN_AS,        0,                    TEXT(CMDSTR_LOGINASA),},
    {    IDC_ITEM_NEWFOLDER,    0,                    CMDSTR_NEWFOLDER,},
/* The preceding entries must be in IDC_ITEM_* order */
/* If you edit anything above this comment, make sure to update below */
};

#ifdef FEATURE_CUT_MOVE
#define CVI_NONREQ   7        /* See remarks above */
#else // FEATURE_CUT_MOVE
#define CVI_NONREQ   6        /* See remarks above */
#endif // FEATURE_CUT_MOVE
#define IVI_REQ        CVI_NONREQ    /* First required verb */
#define IVI_MAX        ARRAYSIZE(c_rgvi)    /* One past last value index */

#pragma END_CONST_DATA



/*****************************************************************************\
    FUNCTION:   _RemoveContextMenuItems
 
    Remove context menu items based on attribute flags.
  
      If we have a drop target, ping it to see if the object on the
      clipboard is pasteable.  If not, then disable Paste.  (Shell UI
      says that you don't remove Paste, merely disable it.)
    
    Return the number of items removed.
\*****************************************************************************/
int CFtpMenu::_RemoveContextMenuItems(HMENU hmenu, UINT idCmdFirst, DWORD sfgao)
{
    int ivi;
    int nItemRemoved = 0;

    for (ivi = 0; ivi < CVI_NONREQ; ivi++)
    {
        if (!(sfgao & c_rgvi[ivi].sfgao))
        {
            EnableMenuItem(hmenu, (c_rgvi[ivi].idc + idCmdFirst), MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
            nItemRemoved++;
        }
    }

    // See if the clipboard format is supported
    if (sfgao & SFGAO_DROPTARGET)
    {
        IDataObject *pdto;
        DWORD grflEffects = 0;        // Clipboard not available

        if (EVAL(SUCCEEDED(OleGetClipboard(&pdto))))
        {
            CFtpDrop * pfdrop;
            
            if (SUCCEEDED(CFtpDrop_Create(m_pff, m_hwnd, &pfdrop)))
            {
                grflEffects = pfdrop->GetEffectsAvail(pdto);
                pfdrop->Release();
            }
            pdto->Release();
        }

        if (!(grflEffects & (DROPEFFECT_COPY | DROPEFFECT_MOVE)))
        {
            EnableMenuItem(hmenu, (IDM_SHARED_EDIT_PASTE + idCmdFirst),
                       MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
            nItemRemoved++;
        }
#ifdef _SOMEDAY_PASTESHORTCUT
        if (!(grflEffects & DROPEFFECT_LINK))
        {
            EnableMenuItem(hmenu, (IDM_SHARED_EDIT_PASTE_SHORTCUT + idCmdFirst),
                       MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
            nItemRemoved++;
        }
#endif
    }

    return nItemRemoved;
}


/*****************************************************************************\
    FUNCTION: _AddToRecentDocs

    DESCRIPTION:
        This method will add the item to the Recent Docs MRU.  The pidl parameter
    is a fully qualified pidl all the way to the root of the public shell name space
    (desktop).
\*****************************************************************************/
HRESULT CFtpMenu::_AddToRecentDocs(LPCITEMIDLIST pidl)
{
    // We may want to filter on verb.
    SHAddToRecentDocs(SHARD_PIDL, (LPCVOID) pidl);

    return S_OK;
}


typedef struct
{
    LPCWIRESTR pwSoftLink;
    LPWIRESTR pwFtpPath;
    DWORD cchSize;
} SOFTLINKDESTCBSTRUCT;

HRESULT CFtpMenu::_SoftLinkDestCB(HINTERNET hint, HINTPROCINFO * phpi, LPVOID pvsldcbs, BOOL * pfReleaseHint)
{
    HRESULT hr = S_OK;
    WIRECHAR wFrom[MAX_PATH];
    SOFTLINKDESTCBSTRUCT * psldcbs = (SOFTLINKDESTCBSTRUCT *) pvsldcbs;
    DWORD cchSize = ARRAYSIZE(wFrom);

    // Normally, I hate hard coding the buffer size, but passing structs to callbacks is such a pain
    // and this won't change.
    hr = FtpGetCurrentDirectoryWrap(hint, TRUE, wFrom, cchSize);
    if (SUCCEEDED(hr))
    {
        hr = FtpSetCurrentDirectoryWrap(hint, TRUE, psldcbs->pwSoftLink);
        if (SUCCEEDED(hr))
        {
            hr = FtpGetCurrentDirectoryWrap(hint, TRUE, psldcbs->pwFtpPath, psldcbs->cchSize);
            if (SUCCEEDED(hr))
            {
                // BUGBUG: Do we need to return?
                hr = FtpSetCurrentDirectoryWrap(hint, TRUE, wFrom);
            }
        }
    }

    return hr;
}


LPITEMIDLIST CFtpMenu::GetSoftLinkDestination(LPCITEMIDLIST pidlToSoftLink)
{
    LPITEMIDLIST pidlToDest = NULL;
    WIRECHAR wSoftLinkName[MAX_PATH];
    WIRECHAR wFtpPath[MAX_PATH];
    SOFTLINKDESTCBSTRUCT sldcbs = {wSoftLinkName, wFtpPath, ARRAYSIZE(wFtpPath)};

    StrCpyNA(wSoftLinkName, FtpPidl_GetLastItemWireName(pidlToSoftLink), ARRAYSIZE(wSoftLinkName));
    StrCpyNA(wFtpPath, FtpPidl_GetLastItemWireName(pidlToSoftLink), ARRAYSIZE(wFtpPath));

    // NULL hwnd because I don't want UI.
    if (EVAL(SUCCEEDED(m_pfd->WithHint(NULL, NULL, _SoftLinkDestCB, (LPVOID) &sldcbs, _punkSite, m_pff))))
    {
        EVAL(SUCCEEDED(CreateFtpPidlFromUrlPathAndPidl(pidlToSoftLink, m_pff->GetCWireEncoding(), wFtpPath, &pidlToDest)));
    }

    return pidlToDest;
}


// Someday maybe add: (SEE_MASK_UNICODE | SEE_MASK_FLAG_TITLE)
#define SEE_MASK_SHARED (SEE_MASK_FLAG_NO_UI | SEE_MASK_HOTKEY | SEE_MASK_NO_CONSOLE)

#define FILEATTRIB_DIRSOFTLINK (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT)

/*****************************************************************************\
    FUNCTION: _ApplyOne

    DESCRIPTION:
        This function will ShellExec() the pidl.  
        
    SECURITY ISSUES:
        We don't need to worry about the 'Open' verb on folders because that
    is always safe.  The 'Open' verb on files is safe because we later
    redirect the functionality to the original URLMON ftp support which
    goes through code download.  This displays dialogs, checks certs, and
    does all the zones checking and admin policies.
\*****************************************************************************/
HRESULT CFtpMenu::_ApplyOne(CFtpMenu * pfcm, LPCMINVOKECOMMANDINFO pici, LPCTSTR pszCmd, LPCITEMIDLIST pidl)
{
    HRESULT hr;
    SHELLEXECUTEINFO sei;
    LPITEMIDLIST pidlFullPriv = pfcm->m_pff->CreateFullPrivatePidl(pidl);

    ZeroMemory(&sei, sizeof(sei));
    sei.cbSize = sizeof(sei);

    LPITEMIDLIST pidlFullPub = NULL;

    // TODO/BUGBUG: It would be nice to see if the pidl is a SoftLink (FtpPidl_IsSoftLink)
    //     and if so, step into the directory, get the directory path and then create
    //     a pidl from that path so we end up showing the user the real destination
    //     of the softlink.
    if (FILEATTRIB_DIRSOFTLINK == (FILEATTRIB_DIRSOFTLINK & FtpPidl_GetAttributes(pidlFullPriv)))
    {
        LPITEMIDLIST pidlNew = pfcm->GetSoftLinkDestination(pidlFullPriv);

        // Switch pidls if it worked, otherwise, using the original pidl isn't that bad, so it
        // will be the fall back case if things don't work out.
        if (pidlNew)
        {
            ILFree(pidlFullPriv);
            pidlFullPriv = pidlNew;
        }

        pidlFullPub = pfcm->m_pff->CreateFullPublicPidl(pidlFullPriv);
    }
    else
    {
        // Yes, so we need to use it in the pidl we pass to ShellExecute.
        pidlFullPub = ILCombine(pfcm->m_pff->GetPublicRootPidlReference(), pidl);
    }

    // Titles are excluded because there is no lpTitle in the sei.
    // Unicode is excluded because we don't do UNICODE; in fact,
    // we filter it out up front!
    ASSERT(SEE_MASK_FLAG_NO_UI == CMIC_MASK_FLAG_NO_UI);
    ASSERT(SEE_MASK_HOTKEY == CMIC_MASK_HOTKEY);
    ASSERT(SEE_MASK_NO_CONSOLE == CMIC_MASK_NO_CONSOLE);

    sei.fMask |= SEE_MASK_IDLIST | (pici->fMask & SEE_MASK_SHARED);
    sei.hwnd = pici->hwnd;
    sei.nShow = pici->nShow;
    sei.dwHotKey = pici->dwHotKey;
    sei.hIcon = pici->hIcon;
    sei.lpIDList = (void *) pidlFullPub;

    if (EVAL(sei.lpIDList))
    {
        TCHAR szParameters[MAX_URL_STRING];
        TCHAR szDirectory[MAX_PATH];

        if (pici->lpParameters)
            SHAnsiToTChar(pici->lpParameters, szParameters, ARRAYSIZE(szParameters));

        if (pici->lpDirectory)
            SHAnsiToTChar(pici->lpDirectory, szDirectory, ARRAYSIZE(szDirectory));

        sei.lpVerb = pszCmd;
        sei.lpParameters = (pici->lpParameters ? szParameters : NULL);
        sei.lpDirectory = (pici->lpDirectory ? szDirectory : NULL);
        if (EVAL(ShellExecuteEx(&sei)))
        {
            // Yes, so we need to use it in the pidl we pass to ShellExecute.
            LPITEMIDLIST pidlFullPubTarget = ILCombine(pfcm->m_pff->GetPublicTargetPidlReference(), pidl);

            if (pidlFullPubTarget)
            {
                EVAL(SUCCEEDED(pfcm->_AddToRecentDocs(pidlFullPubTarget)));        // We don't care if AddToRecent works or not.
                ILFree(pidlFullPubTarget);
                hr = S_OK;
            }
            else
                hr = E_OUTOFMEMORY;
        }
        else
            hr = HRESULT_FROM_WIN32(GetLastError());
    }
    else
        hr = E_OUTOFMEMORY;

    if (pidlFullPub)
        ILFree(pidlFullPub);

    if (pidlFullPriv)
        ILFree(pidlFullPriv);

    return hr;
}





/*****************************************************************************\
 *
 *    _InvokeOneCB
 *
 *    Invoke the command on the single pidl.
 *
\*****************************************************************************/

int CFtpMenu::_InvokeOneCB(LPVOID pvPidl, LPVOID pv)
{
    LPCITEMIDLIST pidl = (LPCITEMIDLIST) pvPidl;
    PEII peii = (PEII) pv;

    ASSERT(peii && peii->pfcm);
    return peii->pfcm->_InvokeOne(pidl, peii);
}

int CFtpMenu::_InvokeOne(LPCITEMIDLIST pidl, PEII peii)

⌨️ 快捷键说明

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