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

📄 ftpfoldr.cpp

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

IMalloc * CFtpFolder::GetIMalloc(void)
{
    IMalloc * pm = NULL;

    IUnknown_Set(&pm, m_pm);
    ASSERT(pm);
    return pm;
}


/*****************************************************************************\
    FUNCTION: IShellFolder::EnumObjects

    DESCRIPTION:
        Design subtlety: If we couldn't create an enumeration on the server,
    succeed, but return an enumerator that shows no objects.

    This is necessary so that our IShellView callback can put
    up error UI.  If we failed the create, the shell would
    destroy the view without giving us a chance to say what's
    up.

    It's also important for write-only directories like /incoming,
    so that the user can drag files into the directory without
    necessarily being able to drag files out.
\*****************************************************************************/
HRESULT CFtpFolder::EnumObjects(HWND hwndOwner, DWORD grfFlags, IEnumIDList ** ppenumIDList)
{
    HRESULT hres = E_FAIL;
    CFtpDir * pfd = GetFtpDir();

    // This will happen if some TARD tries to just CoCreateInstance our
    // Name Space extension and see what contents we have.  TweakUI
    // is an example of one such abuser.  Since we can only populate
    // our contents after we navigate to a FTP server, we are empty.
    *ppenumIDList = NULL;
    if (pfd)
    {
        //    Create a new enumeration object for the caller.
        ASSERT(m_pm);
        hres = CFtpEidl_Create(pfd, this, hwndOwner, grfFlags, ppenumIDList);
        TraceMsg(TF_FTPISF, "CFtpFolder::EnumObjects() CFtpEidl_Create() returned hres=%#08lx", hres);

        if (!EVAL(SUCCEEDED(hres)))
        {
            ASSERT(*ppenumIDList);            // We failed, so free what we have.
        }

        pfd->Release();
    }

    ASSERT_POINTER_MATCHES_HRESULT(*ppenumIDList, hres);
    return hres;
}


BOOL CFtpFolder::_NeedToFallBackRelative(LPCITEMIDLIST pidl, BOOL * pfDisplayProxyFallBackDlg)
{
    LPITEMIDLIST pidlFull = CreateFullPrivatePidl(pidl);
    BOOL fFallBack = FALSE;

    if (pidlFull)
    {
        fFallBack = _NeedToFallBack(pidl, pfDisplayProxyFallBackDlg);
        ILFree(pidlFull);
    }

    return fFallBack;
}



/*****************************************************************************\
    FUNCTION: _NeedToFallBack

    DESCRIPTION:
        We need to fall back to the old URLMON support in these cases:
    #1 It's a file, we let the old code use URLMON to do the download.
    #2 The app (WebOC host) has bugs that cause us to fail.
    #3 The user turned off the New FTP UI. (For whatever reason)
    #4 The proxy is a web proxy and allows URLMON but not WININET access,
       so fall back to the old support.
    #5 WININET doesn't support VMS servers, so we need to fall back in that case.

    NOTE: The order is important because we always need to calc
          fIsProxyBlockingFTP so we only display the fallback dlg
          in the correct case.
\*****************************************************************************/
BOOL CFtpFolder::_NeedToFallBack(LPCITEMIDLIST pidlFull, BOOL * pfDisplayProxyFallBackDlg)
{
    BOOL fNeedToFallBack = TRUE;

    *pfDisplayProxyFallBackDlg = FALSE;

    // TweakUI sends us an Empty pidls so don't fault. NT #396234.
    if (pidlFull && !ILIsEmpty(pidlFull))
    {
        BOOL fIsDirectory;

        if (IsFtpPidlQuestionable(pidlFull))
            _FixQuestionablePidl(pidlFull);

        fIsDirectory = (!FtpPidl_HasPath(pidlFull) || FtpPidl_IsDirectory(pidlFull, FALSE));
        if (fIsDirectory)       // #1
        {
            if (IsAppFTPCompatible())   // #2
            {
                if (!SHRegGetBoolUSValue(SZ_REGKEY_FTPFOLDER, SZ_REGKEY_USE_OLD_UI, FALSE, FALSE)) // #3
                {
                    // The binding code passes us a bind context and that would be a good
                    // key to determine if were are about to navigate to the site.  The
                    // problem is that we can't skip the proxy checking because we will
                    // fail later.
                    //
                    // #224285 is an example where navigating from ftp://ftp.microsoft.com/ to
                    // "www.microsoft.com" will cause CShellUrl to call :: BindToObject and then
                    // our IEnumIDList::Next() which will give an error message.
                    //
                    // Are we unable to get access to the server because there is
                    // a CERN type proxy blocking us?
                    // PERF: Only check for the proxy if we have a bind context because
                    //       the only place we are called from to navigate is
                    //       CDocObjectFolder:: BindToObject() and we are guaranteed that they
                    //       pass it to us.
                    if (!_IsProxyBlockingSite(pidlFull))   // #4
                    {
                        // Is this a VMS Server? If yes, fallback
                        // to URLMON support because wininet doesn't work with this kind of server.
                        if (!_IsServerVMS(pidlFull))
                        {
                            // Only continue if the user didn't turn the new UI Off.
                            fNeedToFallBack = FALSE;
                        }
                    }
                    else
                        *pfDisplayProxyFallBackDlg = TRUE;
                }
            }
        }
    }

    return fNeedToFallBack;
}


/*****************************************************************************\
    FUNCTION: IShellFolder:: BindToObject

    DESCRIPTION:
        First thing we need to do, is see if we want to over ride the default
    IE FTP support.  If we do, we call otherwise, we just fallback to the old
    support.  We want the new UI if: a) it's a directory, b) the web proxy doesn't
    block us, and c) the user didn't turn us off.

    PERF/TODO:
        OrderItem_GetSystemImageListIndexFromCache (\shell\lib\dpastuff.cpp)
    uses riid=IShellFolder when trying to find out the icon.  We don't want
    to hit the net in that case, so force them to pass a pbc to indicate skipping
    the net in that case.
\*****************************************************************************/
HRESULT CFtpFolder::BindToObject(LPCITEMIDLIST pidl, IBindCtx * pbc, REFIID riid, LPVOID * ppvObj)
{
    HRESULT hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);   // Indicate we want the old functionality to kick in.

    if (ppvObj)
        *ppvObj = NULL;

    if (!pidl || ILIsEmpty(pidl) || !_IsValidPidlParameter(pidl))
    {
        // Caller, are you smoking crack?  What's the idea of passing
        // an empty pidl. (Comdlg32 is known to do this)
        hr = E_INVALIDARG;
    }
    else
    {
        BOOL fDisplayProxyFallBackDlg = FALSE;
        LPITEMIDLIST pidlFull = CreateFullPrivatePidl(pidl);

        // We need to handle it.
        hr = _BindToObject(pidl, pidlFull, pbc, riid, ppvObj);

        // Maybe we still need to handle it if 
        ASSERT(HRESULT_FROM_WIN32(ERROR_CANCELLED) != hr);
        ILFree(pidlFull);
    }

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


/*****************************************************************************\
     FUNCTION: IShellFolder::BindToStorage
 
    DESCRIPTION:
         We need to implement this so the user can Open and Save files in
    the standard Open Dialog and Save Dialog.
\*****************************************************************************/
HRESULT CFtpFolder::BindToStorage(LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, LPVOID * ppvObj)
{
    HRESULT hr = E_INVALIDARG;

    if (!EVAL(_IsValidPidlParameter(pidl)))
        return E_INVALIDARG;

    *ppvObj = 0;
    if (EVAL(pidl))
    {
        IMoniker * pmk;

        hr = _PidlToMoniker(pidl, &pmk);
        if (SUCCEEDED(hr))
        {
            hr =  pmk->BindToStorage(pbc, NULL, riid, ppvObj);
            pmk->Release();
        }
    }

    ASSERT_POINTER_MATCHES_HRESULT(*ppvObj, hr);
    TraceMsg(TF_FTPISF, "CFtpFolder::BindToStorage() hr=%#08lx", hr);
    return hr;
}


/*****************************************************************************\
    FUNCTION: IShellFolder::CompareIDs

    DESCRIPTION:
        ici - column on which to sort.  Note! that we rely on the fact that
    IShellFolders are uniform; we do not need to bind to the shell folder in
    order to compare its sub-itemids.

    _UNDOCUMENTED_: The documentation does not say whether or not
    complex pidls can be received.  In fact, they can.
\*****************************************************************************/
HRESULT CFtpFolder::CompareIDs(LPARAM ici, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
{
    ASSERT(IsValidPIDL(pidl1));
    ASSERT(IsValidPIDL(pidl2));

    return FtpItemID_CompareIDs(ici, pidl1, pidl2, FCMP_GROUPDIRS);
}


HRESULT CFtpFolder::_CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID * ppvObj)
{
    HRESULT hr = E_FAIL;
    CFtpDir * pfd = GetFtpDir();

    *ppvObj = NULL;            // Explorer relies on this
    //TraceMsg(TF_FTPISF, "CFtpObj::CreateViewObject() ");
    if (pfd)
    {
        if (IsEqualIID(riid, IID_IDropTarget))
        {
            //  Don't create a drop target for the root FTP folder.
            if (IsRoot())
                hr = E_NOINTERFACE;
            else
            {
                CFtpDrop * pfm;
                hr = CFtpDrop_Create(this, hwndOwner, &pfm);
                if (EVAL(SUCCEEDED(hr)))
                {
                    hr = pfm->QueryInterface(riid, ppvObj);
                    pfm->Release();
                }
            }
        }
        else
            hr = E_NOINTERFACE;

        // TODO: IID_IShellDetails
        pfd->Release();
    }
    else
        hr = E_FAIL;            // Can't do that yet - Never _Initialize'd

    ASSERT_POINTER_MATCHES_HRESULT(*ppvObj, hr);
    if (FAILED(hr))
        hr = CBaseFolder::CreateViewObject(hwndOwner, riid, ppvObj);

    return hr;
}


IShellFolder * CFtpFolder::_GetLegacyShellFolder(void)
{
    IShellFolder * psfLegacy = NULL;

    // I assert that this succeeds because I need to make
    // sure every install case has this CLSID publicly available.
    if (EVAL(SUCCEEDED(CoCreateInstance(CLSID_CDocObjectFolder, NULL, CLSCTX_INPROC_SERVER, IID_IShellFolder, (void **)&psfLegacy))))
    {
        LPITEMIDLIST pidl = GetPrivatePidlClone();

        if (pidl && !ILIsEmpty(pidl))
        {
            LPITEMIDLIST pidlLast = (LPITEMIDLIST) ILGetLastID(pidl);
            LPITEMIDLIST pidlLegacy;

            if (!FtpID_IsServerItemID(pidlLast))
            {
                // NT #291513: We want to force the last item to always be marked as a file
                //          because then it will not have the trailing '/' in the URL when we
                //          pass it to URLMON.  This way, we leave wether it's a file or dir
                //          ambigious for URLMON to figure out.  This is because we can't
                //          disambiguate because the proxy blocks us but URLMON handles it
                //          correctly.
                FtpPidl_SetFileItemType(pidlLast, FALSE);
                FtpPidl_SetAttributes(pidl, FILE_ATTRIBUTE_NORMAL);
            }

            if (SUCCEEDED(_GetLegacyPidl(pidl, &pidlLegacy)))
            {
                if (FAILED(_InitLegacyShellFolder(psfLegacy, pidlLegacy)))
                    ATOMICRELEASE(psfLegacy);

                ILFree(pidlLegacy);
            }
            
            ILFree(pidl);
        }
    }

    return psfLegacy;
}


/*****************************************************************************\
    FUNCTION: IShellFolder:: CreateViewObject

    DESCRIPTION:
    _UNDOCUMENTED_: This entire method is not documented.

    _UNDOCUMENTED_: It is not documented that you need to
    provide an IDropTarget object if you want the view to
    act as a drop target.

    IDropTarget produces a droptarget for the folder itself.

    _UNDOCUMENTED_: The IShellView interface is not documented.

    IShellView produces a shell view for the folder itself.

    _UNOBVIOUS_:  Not obvious that this is how the shell gets
    a context menu for the folder itself.  (You might think it
    comes from GetUIObjectOf...)

    IContextMenu produces a context menu for the folder itself.
    This is important for supporting things like New and Paste.

    IShellDetails (undocumented) is the direct interface to
    GetDetailsOf and ColumnClick, which is now obsolete, replaced
    by the DVM_GETDETAILSOF and DVM_COLUMNCLICK notifications.

    _UNDOCUMENTED_: SHCreateShellFolderViewEx is not documented.

    Yes, it's annoy

⌨️ 快捷键说明

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