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

📄 ftppidl.cpp

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

    *ppidl = (LPITEMIDLIST) pbMemory;
    hr = pbMemory ? S_OK : E_OUTOFMEMORY;

    ASSERT(IsValidPIDL(*ppidl));
    ASSERT_POINTER_MATCHES_HRESULT(*ppidl, hr);

    return hr;
}


/*****************************************************************************\
    FUNCTION: FtpItemID_CreateReal

    DESCRIPTION:
        Cook up a pidl based on a WIN32_FIND_DATA.

    The cFileName field is itself MAX_PATH characters long,
    so its length cannot possibly exceed MAX_PATH...
\*****************************************************************************/
HRESULT FtpItemID_CreateReal(const LPFTP_FIND_DATA pwfd, LPCWSTR pwzDisplayName, LPITEMIDLIST * ppidl)
{
    HRESULT hr;
    FTPIDLIST fi = {0};

    // Fill in fi.
    fi.dwIDType = (IDTYPE_ISVALID | IDVALID_FILESIZE | IDVALID_MOD_DATE);
    fi.uliFileSize.LowPart = pwfd->nFileSizeLow;
    fi.uliFileSize.HighPart = pwfd->nFileSizeHigh;
    fi.ftModified = pwfd->ftLastWriteTime;
    fi.dwAttributes = pwfd->dwFileAttributes;
    fi.dwUNIXPermission = pwfd->dwReserved0;    // Set by WININET
    StrCpyNA(fi.szWireName, pwfd->cFileName, ARRAYSIZE(fi.szWireName));
    StrCpyN(fi.wzDisplayName, pwzDisplayName, ARRAYSIZE(fi.wzDisplayName));

    if (pwfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        fi.dwIDType |= IDTYPE_DIR;
    else
        fi.dwIDType |= IDTYPE_FILE;

    hr = FtpItemID_Alloc(&fi, ppidl);
    ASSERT(IsValidPIDL(*ppidl));

    return hr;
}


/****************************************************\
    FUNCTION: FtpItemID_CreateFake

    DESCRIPTION:
        Create a ItemID but we are only setting the
    name.  We don't know the true file attributes,
    file size, or modification date yet because
    we haven't touched the server yet.  If we did,
    we would use the returned WIN32_FIND_DATA struct
    to create the ItemID by using FtpItemID_CreateReal().
\****************************************************/
HRESULT FtpItemID_CreateFake(LPCWSTR pwzDisplayName, LPCWIRESTR pwWireName, BOOL fTypeKnown, BOOL fIsFile, BOOL fIsFragment, LPITEMIDLIST * ppidl)
{
    HRESULT hr;
    DWORD dwType = IDTYPE_ISVALID;
    FTPIDLIST fi = {0};

    // Is it unknown?
    if (!fTypeKnown)
    {
        // HACK: We will assume everything w/o a file extension is a Dir
        //    and everything w/an extension is a file.
        fTypeKnown = TRUE;
        fIsFile = (0 != *PathFindExtension(pwzDisplayName)) ? TRUE : FALSE;
    }
    if (fTypeKnown)
    {
        if (fIsFile)
            dwType |= IDTYPE_FILE;
        else if (fIsFragment)
            dwType |= IDTYPE_FRAGMENT;
        else
            dwType |= IDTYPE_DIR;
    }
    else
    {
        // You need to know if it's a fragment because there is no
        // heuristic to find out.
        ASSERT(!fIsFragment);

        dwType |= IDTYPE_FILEORDIR;
    }

    fi.dwIDType = dwType;
    fi.dwAttributes = (fIsFile ? FILE_ATTRIBUTE_NORMAL : FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_DIRECTORY);
    fi.uliFileSize.QuadPart = 0;
    StrCpyNW(fi.wzDisplayName, pwzDisplayName, ARRAYSIZE(fi.wzDisplayName));
    StrCpyNA(fi.szWireName, pwWireName, ARRAYSIZE(fi.szWireName));

    hr = FtpItemID_Alloc(&fi, ppidl);
    ASSERT(IsValidPIDL(*ppidl));
    ASSERT_POINTER_MATCHES_HRESULT(*ppidl, hr);

    return hr;
}


/*****************************************************************************\
    FUNCTION: FtpItemID_SetName

    DESCRIPTION:
        The user chose a new name for the ftp file or dir (in unicode).  We
    now need to create the name in wire bytes and we will use the original
    wire byte name to decide how to do that (from pidl).
\*****************************************************************************/
HRESULT FtpItemID_CreateWithNewName(LPCITEMIDLIST pidl, LPCWSTR pwzDisplayName, LPCWIRESTR pwWireName, LPITEMIDLIST * ppidlOut)
{
    HRESULT hr;
    FTPIDLIST fi;
    const FTPIDLIST * pfi = FtpItemID_GetData(pidl);
    CWireEncoding cWireEncoding;

    CopyMemory(&fi, pfi, sizeof(FTPIDLIST) - sizeof(fi.szWireName) - sizeof(fi.wzDisplayName));
    StrCpyNW(fi.wzDisplayName, pwzDisplayName, ARRAYSIZE(fi.wzDisplayName));
    StrCpyNA(fi.szWireName, pwWireName, ARRAYSIZE(fi.szWireName));

    hr = FtpItemID_Alloc(&fi, ppidlOut);
    ASSERT(IsValidPIDL(*ppidlOut));

    return hr;
}


HRESULT Private_GetFileInfo(SHFILEINFO *psfi, DWORD rgf, LPCTSTR pszName, DWORD dwFileAttributes)
{
    HRESULT hr = E_FAIL;

    if (SHGetFileInfo(pszName, dwFileAttributes, psfi, sizeof(*psfi), rgf | SHGFI_USEFILEATTRIBUTES))
        hr = S_OK;

    return hr;
}


/*****************************************************************************\
    FUNCTION: FtpPidl_GetFileInfo

    DESCRIPTION:
        _UNDOCUMENTED_:  We strip the Hidden and System bits so
    that SHGetFileInfo won't think that we're passing something
    that might be a junction.

    We also force the SHGFI_USEFILEATTRIBUTES bit to remind the shell
    that this isn't a file.
\*****************************************************************************/
HRESULT FtpPidl_GetFileInfo(LPCITEMIDLIST pidl, SHFILEINFO *psfi, DWORD rgf)
{
    HRESULT hr;
    TCHAR szDisplayName[MAX_PATH];

    psfi->iIcon = 0;
    psfi->hIcon = NULL;
    psfi->dwAttributes = 0;
    psfi->szDisplayName[0] = 0;
    psfi->szTypeName[0] = 0;

    ASSERT(IsValidPIDL(pidl));
    if (FtpID_IsServerItemID(pidl))
    {
        FtpServerID_GetServer(pidl, szDisplayName, ARRAYSIZE(szDisplayName));
        hr = Private_GetFileInfo(psfi, rgf, szDisplayName, FILE_ATTRIBUTE_DIRECTORY);
        if (psfi->hIcon)
            DestroyIcon(psfi->hIcon);

        psfi->hIcon = LoadIcon(HINST_THISDLL, MAKEINTRESOURCE(IDI_FTPFOLDER));
        ASSERT(psfi->hIcon);

        // Now replace the type (szTypeName) with "FTP Server" because
        // it could go in the Properties dialog
        EVAL(LoadString(HINST_THISDLL, IDS_ITEMTYPE_SERVER, psfi->szTypeName, ARRAYSIZE(psfi->szTypeName)));
    }
    else
    {
        LPFTPIDLIST pfi = FtpItemID_GetData(pidl);
        FtpItemID_GetDisplayName(pidl, szDisplayName, ARRAYSIZE(szDisplayName));
        hr = Private_GetFileInfo(psfi, rgf, szDisplayName, (pfi->dwAttributes & ~(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)));
    }

    return hr;
}

HRESULT FtpPidl_GetFileType(LPCITEMIDLIST pidl, LPTSTR pszType, DWORD cchSize)
{
    SHFILEINFO sfi;
    HRESULT hr;

    ASSERT(IsValidPIDL(pidl));
    hr = FtpPidl_GetFileInfo(pidl, &sfi, SHGFI_TYPENAME);
    if (EVAL(SUCCEEDED(hr)))
    {
        StrCpyN(pszType, sfi.szTypeName, cchSize);
        if (sfi.hIcon)
            DestroyIcon(sfi.hIcon);
    }

    return hr;
}


HRESULT FtpPidl_GetFileTypeStrRet(LPCITEMIDLIST pidl, LPSTRRET pstr)
{
    WCHAR szType[MAX_URL_STRING];
    HRESULT hr;

    ASSERT(IsValidPIDL(pidl));
    hr = FtpPidl_GetFileType(pidl, szType, ARRAYSIZE(szType));
    if (EVAL(SUCCEEDED(hr)))
        StringToStrRetW(szType, pstr);

    return hr;
}


/*****************************************************************************\
    FUNCTION: _FtpItemID_CompareOneID

    DESCRIPTION:
        ici - attribute (column) to compare

    Note! that UNIX filenames are case-*sensitive*.

    We make two passes on the name.  If the names are different in other
    than case, we return the result of that comparison.  Otherwise,
    we return the result of a case-sensitive comparison.

    This algorithm ensures that the items sort themselves in a
    case-insensitive way, with ties broken by a case-sensitive
    comparison.  This makes ftp folders act "mostly" like normal
    folders.

    _UNDOCUMENTED_: The documentation says that the ici parameter
    is undefined and must be zero.  In reality, it is the column
    number (defined by IShellView) for which the comparison is to
    be made.
\*****************************************************************************/
HRESULT _FtpItemID_CompareOneID(LPARAM ici, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2, DWORD dwCompFlags)
{
    int iRc = 0;    // 0 means we don't know.
    HRESULT hr = S_OK;

    ASSERT(IsValidPIDL(pidl1));
    ASSERT(IsValidPIDL(pidl2));

    // Are they both the same type? (Both Dirs or both files?)
    if (!(dwCompFlags & FCMP_GROUPDIRS) || (!FtpPidl_IsDirectory(pidl1, FALSE) == !FtpPidl_IsDirectory(pidl2, FALSE)))
    {
        switch (ici & SHCIDS_COLUMNMASK)
        {
        case COL_NAME:
        {
            // Yes they are the same, so we will key off the name...
            WIRECHAR szName1[MAX_PATH];
            WIRECHAR szName2[MAX_PATH];

            szName1[0] = TEXT('\0');
            szName2[0] = TEXT('\0');

            FtpPidl_GetWireName(pidl1, szName1, ARRAYSIZE(szName1));
            FtpPidl_GetWireName(pidl2, szName2, ARRAYSIZE(szName2));

            iRc = StrCmpIA(szName1, szName2);
            if (0 == iRc)
            {
                if (!(dwCompFlags & FCMP_CASEINSENSE))
                    iRc = StrCmpA(szName1, szName2);

/*
                // They are the same name, so now lets check on the username
                // if they are Server IDs.
                if ((0 == iRc) && (FtpID_IsServerItemID(pidl1)))
                {
                    FtpPidl_GetUserName(pidl1, szName1, ARRAYSIZE(szName1));
                    FtpPidl_GetUserName(pidl2, szName2, ARRAYSIZE(szName2));
                    iRc = StrCmp(szName1, szName2);
                }
*/
            }
        }
        break;

        case COL_SIZE:
            if (FtpPidl_GetFileSize(pidl1) < FtpPidl_GetFileSize(pidl2))
                iRc = -1;
            else if (FtpPidl_GetFileSize(pidl1) > FtpPidl_GetFileSize(pidl2))
                iRc = +1;
            else
                iRc = 0;        // I don't know
            break;

        case COL_TYPE:
            if (!FtpID_IsServerItemID(pidl1) && !FtpID_IsServerItemID(pidl2))
            {
                TCHAR szType1[MAX_PATH];

                hr = FtpPidl_GetFileType(pidl1, szType1, ARRAYSIZE(szType1));
                if (EVAL(SUCCEEDED(hr)))
                {
                    TCHAR szType2[MAX_PATH];
                    hr = FtpPidl_GetFileType(pidl2, szType2, ARRAYSIZE(szType2));
                    if (EVAL(SUCCEEDED(hr)))
                        iRc = StrCmpI(szType1, szType2);
                }
            }
            break;

        case COL_MODIFIED:
        {
            FILETIME ft1 = FtpPidl_GetFileTime(pidl1);
            FILETIME ft2 = FtpPidl_GetFileTime(pidl2);
            iRc = CompareFileTime(&ft1, &ft2);
        }
            break;

        default:
            hr = E_NOTIMPL;
            break;
        }
    }
    else
    {
        // No they are different.  We want the Folder to always come first.
        // This doesn't seam right, but it forces folders to bubble to the top
        // in the most frequent case and it matches DefView's Behavior.
        if (FtpPidl_IsDirectory(pidl1, FALSE))
            iRc = -1;
        else
            iRc = 1;
    }

    if (EVAL(S_OK == hr))
        hr = HRESULT_FROM_SUCCESS_VALUE(iRc);   // encode the sort value in the return code.

    return hr;
}


/*****************************************************************************\
    FUNCTION: FtpItemID_CompareIDs
    
    DESCRIPTION:
        ici - attribute (column) to compare

    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 

⌨️ 快捷键说明

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