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

📄 ftpdrop.cpp

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


/*****************************************************************************\
    FUNCTION: _FireChangeNotify

    DESCRIPTION:
        asd
\*****************************************************************************/
HRESULT _FireChangeNotify(HINTPROCINFO * phpi, LPCOPYONEHDROPINFO pcohi)
{
    HRESULT hr = S_OK;
    WIN32_FIND_DATA wfd;
    HANDLE handle = FindFirstFile(pcohi->pszFSSource, &wfd);

    TraceMsg(TF_WININET_DEBUG, "_FireChangeNotify() FtpPutFileEx(%s -> %s) succeeded", pcohi->pszFSSource, pcohi->pszFtpDest);
    if (handle != INVALID_HANDLE_VALUE)
    {
        ULARGE_INTEGER uliFileSize;
        FTP_FIND_DATA ffd;
        CWireEncoding * pwe = pcohi->pff->GetCWireEncoding();

        uliFileSize.LowPart = wfd.nFileSizeLow;
        uliFileSize.HighPart = wfd.nFileSizeHigh;
        pcohi->progInfo.uliBytesCompleted.QuadPart += uliFileSize.QuadPart;

        hr = pwe->UnicodeToWireBytes(pcohi->pmlc, wfd.cFileName, (phpi->pfd->IsUTF8Supported() ? WIREENC_USE_UTF8 : WIREENC_NONE), ffd.cFileName, ARRAYSIZE(ffd.cFileName));
        if (EVAL(SUCCEEDED(hr)))
        {
            LPITEMIDLIST pidlFtpFile;
            SYSTEMTIME st;
            FILETIME ftUTC;

            ffd.dwFileAttributes = wfd.dwFileAttributes;
            ffd.dwReserved0 = wfd.dwReserved0;
            ffd.dwReserved1 = wfd.dwReserved1;
            ffd.nFileSizeHigh = wfd.nFileSizeHigh;
            ffd.nFileSizeLow = wfd.nFileSizeLow;

            // wfd.ft*Time is in UTF and FtpItemID_CreateReal wants
            // it in LocalTime, so we need to convert here.
            GetSystemTime(&st);
            SystemTimeToFileTime(&st, &ftUTC);
            FileTimeToLocalFileTime(&ftUTC, &ffd.ftLastWriteTime);   // UTC->LocalTime
            ffd.ftCreationTime = ffd.ftLastWriteTime;
            ffd.ftLastAccessTime = ffd.ftLastWriteTime;

            hr = FtpItemID_CreateReal(&ffd, pcohi->pszFtpDest, &pidlFtpFile);
            if (SUCCEEDED(hr))
            {
                // Note that we created the mapped name
                // PERF: Note that we give the time/date stamp to SHChangeNotify that comes from the source
                //       file, not from the FTP server, so it may be inforrect.  However, it's perf prohibitive
                //       to do the right thing.
                FtpChangeNotify(phpi->hwnd, SHCNE_CREATE, pcohi->pff, phpi->pfd, pidlFtpFile, NULL, pcohi->fIsRoot);
                ILFree(pidlFtpFile);
            }
        }

        FindClose(handle);
    }

    return hr;
}


#define CCH_SIZE_ERROR_MESSAGE  6*1024

/*****************************************************************************\
    FtpCopyFile

    Callback procedure that copies a single hdrop / map.
    Should I try to make the name unique in case of collision?
    Naah, just prompt, but! no way to tell if destination is case-sensitive...
\*****************************************************************************/
HRESULT FtpCopyFile(HINTERNET hint, HINTPROCINFO * phpi, LPCOPYONEHDROPINFO pcohi)
{
    HRESULT hr = S_OK;

    if (pcohi->dwOperation != COHDI_FILESIZE_COUNT)
    {
        WIRECHAR wWireName[MAX_PATH];

        EVAL(SUCCEEDED(pcohi->pff->GetCWireEncoding()->UnicodeToWireBytes(pcohi->pmlc, pcohi->pszFtpDest, (pcohi->pff->IsUTF8Supported() ? WIREENC_USE_UTF8 : WIREENC_NONE), wWireName, ARRAYSIZE(wWireName))));

        if (phpi->psb)
            phpi->psb->SetStatusMessage(IDS_COPYING, pcohi->pszFSSource);

        if (pcohi->progInfo.ppd)
        {
            EVAL(SUCCEEDED(UpdateCopyProgressInfo(pcohi->progInfo.ppd, pcohi->pszFtpDest)));
            EVAL(SUCCEEDED(pcohi->progInfo.ppd->SetProgress64(pcohi->progInfo.uliBytesCompleted.QuadPart, pcohi->progInfo.uliBytesTotal.QuadPart)));
        }

        pcohi->progInfo.dwCompletedInCurFile = 0;
        pcohi->progInfo.dwLastDisplayed = 0;

        // BUGBUG: We need to pass the FTP_TRANSFER_TYPE (_ASCII vs. _BINARY)
        hr = FtpPutFileExWrap(hint, TRUE, pcohi->pszFSSource, wWireName, FTP_TRANSFER_TYPE_UNKNOWN, (DWORD_PTR)&(pcohi->progInfo));
        if (SUCCEEDED(hr))
        {
            // We don't fire change notify on browser only if we
            // are replacing a file because ChangeNotify really
            // just hacks ListView and doen't know how to handle
            // duplicates (file replace).
            if (pcohi->fFireChangeNotify)
                hr = _FireChangeNotify(phpi, pcohi);
        }
        else
        {
            if (HRESULT_FROM_WIN32(ERROR_INTERNET_OPERATION_CANCELLED) == hr)
            {
                // Clean up the file.
                EVAL(SUCCEEDED(phpi->pfd->WithHint(NULL, phpi->hwnd, DeleteOneFileCB, pcohi, NULL, pcohi->pff)));
                hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
            }
            else
            {
                // We still want to delete the file, but we need to save the error message
                // so the dialog is correct.
                CHAR szErrorMsg[CCH_SIZE_ERROR_MESSAGE];
                WCHAR wzErrorMsg[CCH_SIZE_ERROR_MESSAGE];
                DWORD cchSize = ARRAYSIZE(szErrorMsg);
                InternetGetLastResponseInfoWrap(TRUE, NULL, szErrorMsg, &cchSize);
                HRESULT hrOrig = hr;
                CWireEncoding * pwe = phpi->pfd->GetFtpSite()->GetCWireEncoding();

                pwe->WireBytesToUnicode(NULL, szErrorMsg, WIREENC_NONE, wzErrorMsg, ARRAYSIZE(wzErrorMsg));
                // Does it already exist?  This may fail.
                SUCCEEDED(phpi->pfd->WithHint(NULL, phpi->hwnd, DeleteOneFileCB, pcohi, NULL, pcohi->pff));

                // No, so it was a real error, now display the error message with the original
                // server response.
                DisplayWininetErrorEx(phpi->hwnd, TRUE, HRESULT_CODE(hrOrig), IDS_FTPERR_TITLE_ERROR, IDS_FTPERR_FILECOPY, IDS_FTPERR_WININET, MB_OK, pcohi->progInfo.ppd, wzErrorMsg);
                hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
            }
        }
    }
    else
    {
        // Just get the file size.   
        WIN32_FIND_DATA wfd;
        HANDLE handle = FindFirstFile(pcohi->pszFSSource, &wfd);

        if (handle && (handle != INVALID_HANDLE_VALUE))
        {
            ULARGE_INTEGER uliFileSize;
            uliFileSize.LowPart = wfd.nFileSizeLow;
            uliFileSize.HighPart = wfd.nFileSizeHigh;
            pcohi->progInfo.uliBytesTotal.QuadPart += uliFileSize.QuadPart;
            FindClose(handle);
        }
    }

    //TraceMsg(TF_FTPOPERATION, "FtpPutFileA(From=%ls, To=%s) hr=%#08lX", pcohi->pszFSSource, pcohi->pszFtpDest, hr);
    return hr;
}


/*****************************************************************************\
    _EnumOneHdropW

    Handle one hdrop and corresponding filemap.

    This is annoying because we need to convert from UNICODE to ANSI.
\*****************************************************************************/
#define OleStrToStrA(a, b) OleStrToStrN(a, ARRAYSIZE(a), b, -1)

HRESULT _EnumOneHdropW(LPCWSTR * ppwzzFSSources, LPCWSTR * ppwzzFtpDest, LPTSTR pszFSSourceOut, DWORD cchFSSourceOut, LPTSTR pszFtpDestOut, DWORD cchFtpDestOut)
{
    HRESULT hres;
    int cwch;

    if (*ppwzzFSSources && (*ppwzzFSSources)[0])
    {
        cwch = SHUnicodeToTChar(*ppwzzFSSources, pszFSSourceOut, cchFSSourceOut);
        if (EVAL(cwch))
        {
            *ppwzzFSSources += cwch;
            if (EVAL((*ppwzzFtpDest)[0]))
            {
                cwch = SHUnicodeToTChar(*ppwzzFtpDest, pszFtpDestOut, cchFtpDestOut);
                if (EVAL(cwch))
                {
                    *ppwzzFtpDest += cwch;
                    hres = S_OK;    // Both strings converted okay
                }
                else
                    hres = E_UNEXPECTED; // File name too long
            }
            else
                hres = E_UNEXPECTED;    // Premature EOF in map
        }
        else
            hres = E_UNEXPECTED;    // File name too long
    }
    else
        hres = S_FALSE;            // End of buffer

    return hres;
}


/*****************************************************************************\
    _EnumOneHdropA

    Handle one hdrop and corresponding filemap.
\*****************************************************************************/
HRESULT _EnumOneHdropA(LPCSTR * ppszzFSSource, LPCSTR * ppszzFtpDest, LPTSTR pszFSSourceOut, DWORD cchFSSourceOut, LPTSTR pszFtpDestOut, DWORD cchFtpDestOut)
{
    HRESULT hres;

    if ((*ppszzFSSource)[0])
    {
        SHAnsiToTChar(*ppszzFSSource, pszFSSourceOut, cchFSSourceOut);
        *ppszzFSSource += lstrlenA(*ppszzFSSource) + 1;
        if (EVAL((*ppszzFtpDest)[0]))
        {
            SHAnsiToTChar(*ppszzFtpDest, pszFtpDestOut, cchFtpDestOut);
            *ppszzFtpDest += lstrlenA(*ppszzFtpDest) + 1;
            hres = S_OK;        // No problemo
        }
        else
            hres = E_UNEXPECTED;    // Premature EOF in map
    }
    else
        hres = S_FALSE;            // No more files

    return hres;
}


/*****************************************************************************\
    ConfirmCopy

    Callback procedure that checks if this file really ought to be
    copied.

    Returns S_OK if the file should be copied.
    Returns S_FALSE if the file should not be copied.

    - If the user cancelled, then say S_FALSE from now on.
    - If the user said Yes to All, then say S_OK.
    - If there is no conflict, then say S_OK.
    - If the user said No to All, then say S_FALSE.
    - Else, ask the user what to do.

    Note that the order of the tests above means that if you say
    "Yes to All", then we don't waste our time doing overwrite checks.

    _GROSS_:  NOTE! that we don't try to uniquify the name, because
    WinINet doesn't support the STOU (store unique) command, and
    there is no way to know what filenames are valid on the server.
\*****************************************************************************/
HRESULT ConfirmCopy(LPCWSTR pszLocal, LPCWSTR pszFtpName, OPS * pOps, HWND hwnd, CFtpFolder * pff, CFtpDir * pfd, DROPEFFECT * pde, int nObjs, BOOL * pfFireChangeNotify)
{
    HRESULT hr = S_OK;

    *pfFireChangeNotify = TRUE;
    if (*pOps == opsCancel)
        hr = S_FALSE;
    else 
    {
        HANDLE hfind;
        WIN32_FIND_DATA wfdSrc;
        hfind = FindFirstFile(pszLocal, &wfdSrc);
        if (hfind != INVALID_HANDLE_VALUE)
        {
            FindClose(hfind);

            // Is it a file?  We don't care about confirming the replacement
            // of directories.
            if (!(FILE_ATTRIBUTE_DIRECTORY & wfdSrc.dwFileAttributes))
            {
                FTP_FIND_DATA wfd;
                hr = pfd->GetFindDataForDisplayPath(hwnd, pszFtpName, &wfd, pff);
                if (*pOps == opsYesToAll)
                {
                    // If the file exists (S_OK) and it's browser only, 
                    // then don't fire the change notify.
                    if ((S_OK == hr) && (SHELL_VERSION_NT5 != GetShellVersion()))
                        *pfFireChangeNotify = FALSE;

                    hr = S_OK;
                }
                else
                {
                    switch (hr)
                    {
                    case S_OK:            // File exists; worry
                        if (*pOps == opsNoToAll)
                            hr = S_FALSE;
                        else
                        {
                            FILETIME ftUTC = wfdSrc.ftLastWriteTime;
    
                            FileTimeToLocalFileTime(&ftUTC, &wfdSrc.ftLastWriteTime);   // UTC->LocalTime
                            // BUGBUG/TODO: Do we need to set modal?
                            switch (FtpConfirmReplaceDialog(hwnd, &wfdSrc, &wfd, nObjs, pff))
                            {
                            case IDC_REPLACE_YESTOALL:
                                *pOps = opsYesToAll;
                                // FALLTHROUGH

                            case IDC_REPLACE_YES:
                                // pre-NT5 doesn't work 
                                if (SHELL_VERSION_NT5 != GetShellVersion())
                                    *pfFireChangeNotify = FALSE;

                                hr = S_OK;
                                break;

                            case IDC_REPLACE_NOTOALL:
                                *pOps = opsNoToAll;
                                // FALLTHROUGH

                            case IDC_REPLACE_NO:
                                hr = S_FALSE;
                                break;

                            default:
                                ASSERT(0);        // Huh?
                                // FALLTHROUGH

                            case IDC_REPLACE_CANCEL:
                                if (pde)
                                    *pde = 0;

                                *pOps = opsCancel;
                                hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
                                break;
                            }
                        }
                        break;

                    case S_FALSE:
                    default:
                        // Assume the file doesn't exist; no problemo
                        hr = S_OK;
                        break;
                    }
                }
            }
        }
        else
        {                   // File doesn't exist
            hr = S_OK;    // The open will raise the error
        }

    }

    //TraceMsg(TF_FTPDRAGDROP, "ConfirmCopy(%s) -> %08x", pszFtpName, hr);
    return hr;
}




/*****************************************************************************\
    CLASS: CDropOperation

⌨️ 快捷键说明

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