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

📄 ftpdir.cpp

📁 很好用的ftp源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
            pidlToFind = m_pflHfpl->FindPidl(pidlTemp, TRUE);
        ILFree(pidlTemp);
    }

    return pidlToFind;
}


LPCITEMIDLIST CFtpDir::GetPidlFromDisplayName(LPCWSTR pwzDisplayName)
{
    WIRECHAR wWireName[MAX_PATH];
    CWireEncoding * pwe = GetFtpSite()->GetCWireEncoding();

    EVAL(SUCCEEDED(pwe->UnicodeToWireBytes(NULL, pwzDisplayName, (IsUTF8Supported() ? WIREENC_USE_UTF8 : WIREENC_NONE), wWireName, ARRAYSIZE(wWireName))));
    return GetPidlFromWireName(wWireName);
}


/*****************************************************************************\
    FUNCTION: IsRoot

    DESCRIPTION:
        Returns FALSE if we are at the "FTP Folder" root level, not
    inside an actual FTP site.y
\*****************************************************************************/
BOOL CFtpDir::IsRoot(void)
{
    return ILIsEmpty(m_pidl);
}


typedef struct tagGETFINDDATAINFO
{
    LPCWIRESTR pwWireName;
    LPFTP_FIND_DATA pwfd;
} GETFINDDATAINFO, * LPGETFINDDATAINFO;

HRESULT CFtpDir::_GetFindData(HINTERNET hint, HINTPROCINFO * phpi, LPVOID pv, BOOL * pfReleaseHint)
{
    LPGETFINDDATAINFO pgfdi = (LPGETFINDDATAINFO) pv;
    HRESULT hr = S_FALSE;

    // Remember, FTP filenames are always in the ANSI character set
    // PERF: Status
    hr = FtpDoesFileExist(hint, TRUE, pgfdi->pwWireName, pgfdi->pwfd, INTERNET_NO_CALLBACK);
    if (SUCCEEDED(hr))
    {
        if (!StrCmpIA(pgfdi->pwfd->cFileName, pgfdi->pwWireName))
            hr = S_OK;        // The are equal.
        else if (!StrCmpA(pgfdi->pwfd->cFileName, SZ_DOTA))
        {
            //    Coincidence of coincidences:  If we found a ".",
            //  then the wfd already contains the description of
            //  the directory!  In other words, the wfd contains
            //  the correct information after all, save for the name.
            //  Aren't we lucky.
            //
            //  And if it isn't dot, then it's some directory with
            //  unknown attributes (so we'll use whatever's lying around).
            //  Just make sure it's a directory.
            pgfdi->pwfd->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
            StrCpyNA(pgfdi->pwfd->cFileName, pgfdi->pwWireName, ARRAYSIZE(pgfdi->pwfd->cFileName));
            hr = S_OK;
        }
    }
    else
    {
#ifndef DEBUG
        // Don't display an error msg because some callers will call when they
        // know the file may not exist.  This is the case for ConfirmCopy().
        hr = S_FALSE;
#endif // DEBUG
    }

    return hr;
}


/*****************************************************************************\
    FUNCTION: GetFindData

    DESCRIPTION:
        Get the WIN32_FIND_DATA for a file, given by name.

    This is done as part of drag/drop to allow for an overwrite prompt.

    BUGBUG -- This is all a gross hack because the STAT command
    isn't supported by WinINet (as FtpGetFileAttributes).

    Not that it'd help, because ftp.microsoft.com is OUT OF SPEC
    with regard to the STAT command.  (The first line of the output
    isn't terminated correctly, causing the client to hang.)

    Furthermore, UNIX ftp servers implement STAT incorrectly, too,
    rendering STAT no more useful than LIST.

    HACKHACK -- There is a bug in WinINet where doing a FindFirst
    on a name which happens to be a directory returns the contents
    of the directory instead of the attributes of the directory itself.
    (This is actually a failing of most FTP implementation, because
    they just use /bin/ls for directory listings.)

    So we compare the name that comes back against the name we ask
    for.  If they are different, then it's a folder.  We'll compare
    in a case-insensitive manner because we don't know whether the
    server is case-sensitive or not.

    Note that we can get faked out if a directory contains a file
    which has the same name as the directory.  There is nothing we
    can do about that.  Fortunately, UNIX servers always return "."
    as the first file in a subdirectory, so 99% of the time, we'll
    do the right thing.
\*****************************************************************************/
HRESULT CFtpDir::GetFindData(HWND hwnd, LPCWIRESTR pwWireName, LPFTP_FIND_DATA pwfd, CFtpFolder * pff)
{
    GETFINDDATAINFO gfdi = {pwWireName, pwfd};
    HRESULT hr = WithHint(NULL, hwnd, _GetFindData, &gfdi, NULL, pff);

    return hr;
}


/*****************************************************************************\
    FUNCTION: GetFindDataForDisplayPath

    DESCRIPTION:
\*****************************************************************************/
HRESULT CFtpDir::GetFindDataForDisplayPath(HWND hwnd, LPCWSTR pwzDisplayPath, LPFTP_FIND_DATA pwfd, CFtpFolder * pff)
{
    CWireEncoding * pwe = GetFtpSite()->GetCWireEncoding();
    WIRECHAR wWirePath[MAX_PATH];

    EVAL(SUCCEEDED(pwe->UnicodeToWireBytes(NULL, pwzDisplayPath, (IsUTF8Supported() ? WIREENC_USE_UTF8 : WIREENC_NONE), wWirePath, ARRAYSIZE(wWirePath))));
    return GetFindData(hwnd, wWirePath, pwfd, pff);
}


/*****************************************************************************\
    FUNCTION: GetNameOf

    DESCRIPTION:
        Common worker that handles SHGDN_FORPARSING style GetDisplayNameOf's.

    Note! that since we do not support junctions (duh), we can
    safely walk down the pidl generating goop as we go, secure
    in the knowledge that we are in charge of every subpidl.

    _CHARSET_:  Since FTP filenames are always in the ANSI character
    set, by RFC 1738, we can return ANSI display names without loss
    of fidelity.  In a general folder implementation, we should be
    using cStr to return display names, so that the UNICODE
    version of the shell extension can handle UNICODE names.
\*****************************************************************************/
HRESULT CFtpDir::GetNameOf(LPCITEMIDLIST pidl, DWORD shgno, LPSTRRET pstr)
{
    LPITEMIDLIST pidlFull = ILCombine(m_pidl, pidl);
    HRESULT hr = E_FAIL;

    if (pidlFull)
    {
        hr = StrRetFromFtpPidl(pstr, shgno, pidlFull);
        ILFree(pidlFull);
    }

    return hr;
}

/*****************************************************************************\
      FUNCTION: ChangeFolderName

      DESCRIPTION:
        A rename happened on this folder so update the szDir and m_pidl

      PARAMETERS:
        pidlFtpPath
\*****************************************************************************/
HRESULT CFtpDir::ChangeFolderName(LPCITEMIDLIST pidlFtpPath)
{
    HRESULT hr = E_FAIL;
    LPITEMIDLIST pidlNewFtpPath = NULL;

    EVAL(SUCCEEDED(m_pfs->FlushSubDirs(m_pidlFtpDir)));
    hr = FtpPidl_ReplacePath(m_pidl, pidlFtpPath, &pidlNewFtpPath);
    _SetFtpDir(m_pfs, this, pidlFtpPath);
    if (EVAL(SUCCEEDED(hr)))
    {
        Pidl_Set(&m_pidl, pidlNewFtpPath);
        ILFree(pidlNewFtpPath);
    }

    return hr;
}


/*****************************************************************************\
      FUNCTION: _CompareDirs

      DESCRIPTION:
        Check if the indicated pfd is already rooted at the indicated pidl.
\*****************************************************************************/
int CALLBACK _CompareDirs(LPVOID pvPidl, LPVOID pvFtpDir, LPARAM lParam)
{
    LPCITEMIDLIST pidl = (LPCITEMIDLIST) pvPidl;
    CFtpDir * pfd = (CFtpDir *) pvFtpDir;

    return FtpItemID_CompareIDsInt(COL_NAME, pfd->m_pidl, pidl, FCMP_NORMAL);
}


HRESULT CFtpDir::_SetFtpDir(CFtpSite * pfs, CFtpDir * pfd, LPCITEMIDLIST pidl)
{
    if (FtpID_IsServerItemID(pidl))
        pidl = _ILNext(pidl);

    // We don't want pfd->m_pidlFtpDir to include the virtual root.
    if (pfd->GetFtpSite()->HasVirtualRoot())
    {
        LPITEMIDLIST pidlIterate = (LPITEMIDLIST) pidl;
        LPITEMIDLIST pidlVRootIterate = (LPITEMIDLIST) pfd->GetFtpSite()->GetVirtualRootReference();

        ASSERT(!FtpID_IsServerItemID(pidl) && !FtpID_IsServerItemID(pidlVRootIterate));
        // Let's see if pidl starts off with 
        while (!ILIsEmpty(pidlVRootIterate) && !ILIsEmpty(pidlIterate) && 
                FtpItemID_IsEqual(pidlVRootIterate, pidlIterate))
        {
            pidlVRootIterate = _ILNext(pidlVRootIterate);
            pidlIterate = _ILNext(pidlIterate);
        }

        if (ILIsEmpty(pidlVRootIterate))
            pidl = (LPCITEMIDLIST)pidlIterate;

    }

    Pidl_Set(&pfd->m_pidlFtpDir, pidl);
    return S_OK;
}


/*****************************************************************************\
      FUNCTION: CFtpDir_Create

      DESCRIPTION:
        Create a brand new FtpDir structure.
\*****************************************************************************/
HRESULT CFtpDir_Create(CFtpSite * pfs, LPCITEMIDLIST pidl, CFtpDir ** ppfd)
{
    CFtpDir * pfd = new CFtpDir();
    HRESULT hr = E_OUTOFMEMORY;

    ASSERT(pfs);
    if (EVAL(pfd))
    {
        // WARNING: No ref held because it's a back pointer.
        //          This requires that the parent (CFtpSite) always
        //          out live this object.
        pfd->m_pfs = pfs;

        Pidl_Set(&pfd->m_pidl, pidl);
        if (EVAL(pfd->m_pidl))
            hr = pfd->_SetFtpDir(pfs, pfd, pidl);
        else
            IUnknown_Set(&pfd, NULL);
    }

    *ppfd = pfd;
    ASSERT(*ppfd ? SUCCEEDED(hr) : FAILED(hr));

    return hr;
}


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

    // This needs to be allocated in Zero Inited Memory.
    // Assert that all Member Variables are inited to Zero.
    ASSERT(!m_pfs);
    ASSERT(!m_pflHfpl);
    ASSERT(!m_pfgMotd);
    ASSERT(!m_pidl);

    LEAK_ADDREF(LEAK_CFtpDir);
}


/****************************************************\
    Destructor
\****************************************************/
CFtpDir::~CFtpDir()
{
    // WARNING: m_pfs is a back pointer that doesn't have a ref.
    // m_pfs)

    IUnknown_Set(&m_pflHfpl, NULL);
    IUnknown_Set(&m_pfgMotd, NULL);
    
    if (m_pidl)         // Win95's Shell32.dll crashes with ILFree(NULL)
        ILFree(m_pidl);

    DllRelease();
    LEAK_DELREF(LEAK_CFtpDir);
}


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

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

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

    if (m_cRef > 0)
        return m_cRef;

    delete this;
    return 0;
}

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

    AddRef();
    return S_OK;
}

⌨️ 快捷键说明

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