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

📄 ftpcm.cpp

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

            // We don't support Delete or Rename from the Caption Bar
            if (_IsCallerCaptionBar(indexMenu, uFlags))
                sfgao &= ~(SFGAO_CANDELETE | SFGAO_CANRENAME); // Clear these two.

            //  Not on the "File" menu, and not from a shortcut.
            //  Add the "Delete", "Rename", etc. stuff, then go
            //  enable/disable them as needed.
            AddToPopupMenu(hmenu, IDM_ITEMCONTEXT, IDM_M_SHAREDVERBS, indexMenu, idCmdFirst, idCmdLast, MM_ADDSEPARATOR);
            _RemoveContextMenuItems(hmenu, idCmdFirst, sfgao);
        }

        // Add Download if there is anything inside.
        // The assertion makes sure that idCmdLast is set properly.
        ASSERT(IDC_ITEM_DOWNLOAD > IDC_ITEM_OPEN);
        if (!_IsCallerCaptionBar(indexMenu, uFlags))
        {
            // Don't add "Copy To Folder" in the caption bar because it doesn't work for the root of
            // an ftp server.  We aren't going to support it in subdirectories.
            AddToPopupMenu(hmenu, IDM_ITEMCONTEXT, IDM_M_VERBS, indexMenu, idCmdFirst, idCmdLast, MM_ADDSEPARATOR);
        }
        
        if (!(uFlags & CMF_NODEFAULT))
            SetMenuDefaultItem(hmenu, IDC_ITEM_DOWNLOAD + idCmdFirst, MM_ADDSEPARATOR);

        AddToPopupMenu(hmenu, IDM_ITEMCONTEXT, (fAllFolders ? IDM_M_FOLDERVERBS : IDM_M_FILEVERBS), indexMenu, idCmdFirst, 
                        idCmdLast, (_IsCallerCaptionBar(indexMenu, uFlags) ? 0 : MM_ADDSEPARATOR));
        if (fAllFolders && (SHELL_VERSION_W95NT4 == GetShellVersion()))
        {
            // On shell32 v3 (Win95 & NT4) I remove the 'Explore' verb because the shell has bugs
            // that aren't fixable are easy to fix.
            EVAL(DeleteMenu(hmenu, (IDC_ITEM_EXPLORE + idCmdFirst), MF_BYCOMMAND));
            TraceMsg(TF_FTPOPERATION, "QueryContextMenu() Removing 'Explorer' because it's shell v3");
            SetMenuDefaultItem(hmenu, idCmdFirst + IDC_ITEM_OPEN, 0);
        }
        else if (!(uFlags & CMF_NODEFAULT))
            SetMenuDefaultItem(hmenu, idCmdFirst + (((uFlags & CMF_EXPLORE) && fAllFolders)? IDC_ITEM_EXPLORE : IDC_ITEM_OPEN), 0);
    }
    else
    {                // Folder background menu
        AddToPopupMenu(hmenu, IDM_ITEMCONTEXT, IDM_M_BACKGROUNDVERBS, indexMenu, idCmdFirst, idCmdLast, MM_ADDSEPARATOR);
        // Did the menu come from the file menu?
        if (CMF_DVFILE == (CMF_DVFILE & uFlags))
        {
            // Yes, then we want to delete the "Properties" background menu item because one
            // was already merged in for the selected files.  The other Properties will
            // be there but grayed out if nothing was selected.
            EVAL(DeleteMenu(hmenu, (IDC_ITEM_BKGNDPROP + idCmdFirst), MF_BYCOMMAND));
        }

        MergeInToPopupMenu(hmenu, IDM_M_BACKGROUND_POPUPMERGE, indexMenu, idCmdFirst, idCmdLast, MM_ADDSEPARATOR);
    }

    if (EVAL(SUCCEEDED(hr)))
        hr = ResultFromShort(IDC_ITEM_MAX);

    _SHPrettyMenu(hmenu);
    return hr;
}

/*****************************************************************************\
 *
 *    IContextMenu::GetCommandString
 *
 *    Somebody wants to convert a command id into a string of some sort.
 *
\*****************************************************************************/

HRESULT CFtpMenu::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT *pwRsv, LPSTR pszName, UINT cchMax)
{
    HRESULT hr = E_FAIL;
    BOOL fUnicode = FALSE;

    if (idCmd < IDC_ITEM_MAX)
    {
        switch (uFlags)
        {
        case GCS_HELPTEXTW:
            fUnicode = TRUE;
            // Fall thru...
        case GCS_HELPTEXTA:
            GetHelpText:
            if (EVAL(cchMax))
            {
                BOOL fResult;
                pszName[0] = '\0';
                 
                if (fUnicode)
                    fResult = LoadStringW(HINST_THISDLL, IDS_ITEM_HELP((UINT)idCmd), (LPWSTR)pszName, cchMax);
                else
                    fResult = LoadStringA(HINST_THISDLL, IDS_ITEM_HELP((UINT)idCmd), pszName, cchMax);
                if (EVAL(fResult))
                    hr = S_OK;
                else
                    hr = E_INVALIDARG;
            }
            else
                hr = E_INVALIDARG;
        break;

        case GCS_VALIDATEW:
        case GCS_VALIDATEA:
            hr = S_OK;
            break;

        case GCS_VERBW:
            fUnicode = TRUE;
            // Fall thru...
        case GCS_VERBA:
        {
            int ivi;
            for (ivi = 0; ivi < IVI_MAX; ivi++)
            {
                if (c_rgvi[ivi].idc == idCmd)
                {
                    if (fUnicode)
                        SHTCharToUnicode(c_rgvi[ivi].ptszCmd, (LPWSTR)pszName, cchMax);
                    else
                        SHTCharToAnsi(c_rgvi[ivi].ptszCmd, pszName, cchMax);

                    hr = S_OK;
                    break;
                }
            }

            if (!EVAL(ivi < IVI_MAX))
                hr = E_INVALIDARG;
            break;
        }

        default:
            hr = E_NOTIMPL;
            break;
        }
    }
    else
    {
        //  _UNOBVIOUS_:  Another place where PASTE rears its ugly head.
        //  We must generate the help text for it ourselves, even though
        //  the menu item "sort of" belongs to the shell.
        if ((idCmd == SHARED_EDIT_PASTE) &&
            ((uFlags == GCS_HELPTEXTW) || (uFlags == GCS_HELPTEXTA)))
        {
            goto GetHelpText;
        }

        hr = E_INVALIDARG;
    }

    return hr;
}


HRESULT UpdateDeleteProgressStr(IProgressDialog * ppd, LPCTSTR pszFileName)
{
    HRESULT hr = E_FAIL;
    TCHAR szTemplate[MAX_PATH];

    if (EVAL(LoadString(HINST_THISDLL, IDS_DELETING, szTemplate, ARRAYSIZE(szTemplate))))
    {
        TCHAR szStatusStr[MAX_PATH];
        WCHAR wzStatusStr[MAX_PATH];

        wnsprintf(szStatusStr, ARRAYSIZE(szStatusStr), szTemplate, pszFileName);
        SHTCharToUnicode(szStatusStr, wzStatusStr, ARRAYSIZE(wzStatusStr));
        EVAL(SUCCEEDED(hr = ppd->SetLine(2, wzStatusStr, FALSE, NULL)));
    }

    return hr;
}


HRESULT FtpChangeNotifyDirPatch(HWND hwnd, LONG wEventId, CFtpFolder * pff, LPCITEMIDLIST pidlFull, LPCITEMIDLIST pidl2, BOOL fTopLevel)
{
    HRESULT hr = S_OK;
    LPITEMIDLIST pidlParent = ILClone(pidlFull);

    if (pidlParent)
    {
        ILRemoveLastID(pidlParent);
        CFtpDir * pfd = pff->GetFtpDirFromPidl(pidlParent);
    
        if (pfd)
        {
            FtpChangeNotify(hwnd, wEventId, pff, pfd, ILFindLastID(pidlFull), pidl2, fTopLevel);
            pfd->Release();
        }

        ILFree(pidlParent);
    }

    return hr;
}


// The following struct is used when recursively downloading
// files/dirs from the FTP server after a "Download" verb.
typedef struct tagDELETESTRUCT
{
    LPCITEMIDLIST           pidlRoot;          // Base URL of the Download Source
    CFtpFolder *            pff;               // Allocator to create temp pidls.
    IMalloc *               pm;                // Allocator to create temp pidls.
    LPCMINVOKECOMMANDINFO   pdoi;              // Our call.
    HWND                    hwnd;              // HWND for UI
    CStatusBar *            psb;               // Used to display info during the delete
    IProgressDialog *       ppd;               // Used to display progress during the delete.
    DWORD                   dwTotalFiles;      // How many files are there to delete total.
    DWORD                   dwDeletedFiles;    // How many files have already been deleted.
    BOOL                    fInDeletePass;     // Are we in the 'Count Files to Delete' or 'Delete Files' pass?
} DELETESTRUCT;

/*****************************************************************************\
     FUNCTION: DeleteItemCB
 
    DESCRIPTION:
        This function will download the specified item and it's contents if it
    is a directory.
\*****************************************************************************/
HRESULT _DeleteItemPrep(HINTERNET hint, LPCITEMIDLIST pidlFull, BOOL fIsTopLevel, DELETESTRUCT * pDelete)
{
    HRESULT hr = S_OK;

    if (pDelete->ppd && pDelete->ppd->HasUserCancelled())
        hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);

    if (SUCCEEDED(hr))  // May have been cancelled
    {
        DWORD dwError = 0;

        if (pDelete->fInDeletePass && pDelete->psb)
            pDelete->psb->SetStatusMessage(IDS_DELETING, FtpPidl_GetLastFileDisplayName(pidlFull));

        if (pDelete->fInDeletePass && pDelete->ppd)
            EVAL(SUCCEEDED(UpdateDeleteProgressStr(pDelete->ppd, FtpPidl_GetLastFileDisplayName(pidlFull))));

        // Is this a dir/folder that we need to recurse into? OR
        // Is this a SoftLink?
        if ((FILE_ATTRIBUTE_DIRECTORY & FtpPidl_GetAttributes(pidlFull)) ||
            (0 == FtpPidl_GetAttributes(pidlFull)))
        {
            // This is the head of the recursion.  We will do nothing now and we will
            // wait to delete the dir in the recursion tail because we need to wait
            // until all the files are gone.

            // Don't delete softlinks because of the recursion problem.
        }
        else
        {
            if (pDelete->fInDeletePass)
            {
                if (pDelete->ppd)
                    EVAL(SUCCEEDED(pDelete->ppd->SetProgress(pDelete->dwDeletedFiles, pDelete->dwTotalFiles)));

                // Contemplate adding a callback function in order to feed the status bar.
                hr = FtpDeleteFileWrap(hint, TRUE, FtpPidl_GetLastItemWireName(pidlFull));
                if (FAILED(hr))
                {
                    // We need to display the error now while the extended error info is still valid.
                    // This is because as we walk out of the resursive call, we will be calling
                    // FtpSetCurrentDirectory() which will wipe clean the extended error msg.
                    if (FAILED(hr) && (HRESULT_FROM_WIN32(ERROR_CANCELLED) != hr))
                    {
                        DisplayWininetError(pDelete->hwnd, TRUE, HRESULT_CODE(hr), IDS_FTPERR_TITLE_ERROR, IDS_FTPERR_DELETE, IDS_FTPERR_WININET, MB_OK, pDelete->ppd);
                        hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);  // Wrong permissions
                    }
                }
                else
                    FtpChangeNotifyDirPatch(pDelete->hwnd, SHCNE_DELETE, pDelete->pff, pidlFull, NULL, fIsTopLevel);

                pDelete->dwDeletedFiles++;
                TraceMsg(TF_FTPOPERATION, "DeleteItemCB() FtpDeleteFileA() returned dwError=%#08lx.  File=%s", dwError, FtpPidl_GetLastFileDisplayName(pidlFull));
            }
            else
                pDelete->dwTotalFiles++;
        }
    }

    return hr;
}

HRESULT _DeleteItemCleanUp(HRESULT hr, DELETESTRUCT * pDelete)
{
    if (pDelete->ppd && pDelete->ppd->HasUserCancelled())
        hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);

    if (pDelete->fInDeletePass) // Only display errors and fire ChangeNotify if in Delete pass.
    {
        if ((FAILED(hr)) && (HRESULT_FROM_WIN32(ERROR_CANCELLED) != hr))
        {
            int nResult = DisplayWininetError(pDelete->hwnd, TRUE, HRESULT_CODE(hr), IDS_FTPERR_TITLE_ERROR, IDS_FTPERR_DELETE, IDS_FTPERR_WININET, MB_OK, pDelete->ppd);
            hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);   // Don't display any more error dialogs.
        }
    }

    return hr;
}


HRESULT FtpRemoveDirectoryWithCN(HWND hwnd, HINTERNET hint, CFtpFolder * pff, LPCITEMIDLIST pidlFull, BOOL fIsTopLevel)
{
    HRESULT hr = S_OK;

    hr = FtpRemoveDirectoryWrap(hint, TRUE, FtpPidl_GetLastItemWireName(pidlFull));
    if (SUCCEEDED(hr))
    {
        hr = FtpChangeNotifyDirPatch(hwnd, SHCNE_RMDIR, pff, pidlFull, NULL, fIsTopLevel);
        TraceMsg(TF_WININET_DEBUG, "FtpRemoveDirectoryWithCN() FtpRemoveDirectory(%hs) returned %#08lx", FtpPidl_GetLastItemWireName(pidlFull), hr);
    }

    return hr;
}


INT ILCountItemIDs(LPCITEMIDLIST pidl)
{
    INT nCount = 0;

    if (pidl)
    {
        while (!ILIsEmpty(pidl))
        {
            pidl = _ILNext(pidl);
            nCount++;
        }
    }

    return nCount;
}


/*****************************************************************************\
     FUNCTION: _IsTopLevel
 
    DESCRIPTION:
\*****************************************************************************/
BOOL _IsTopLevel(LPCITEMIDLIST pidlRoot, LPCITEMIDLIST pidlCurrent)
{
    INT nRoot = ILCountItemIDs(pidlRoot);
    INT nCurrent = ILCountItemIDs(pidlCurrent);

    // It is the root if nCurrent has no more than 1 more than nRoot

⌨️ 快捷键说明

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