📄 ftpapi.cpp
字号:
/*****************************************************************************\
FILE: ftpapi.cpp
DESCRIPTION:
This file contains functions to perform the following 2 things:
1. WININET WRAPPERS: Wininet APIs have either wierd bugs or bugs that come thru the APIs
from the server. It's also important to keep track of the perf impact
of each call. These wrappers solve these problems.
2. FTP STRs to PIDLs: These wrappers will take ftp filenames and file paths
that come in from the server and turn them into pidls. These pidls contain
both a unicode display string and the filename/path in wire bytes for future
server requests.
\*****************************************************************************/
#include "priv.h"
#include "util.h"
#include "encoding.h"
#include "ftpapi.h"
///////////////////////////////////////////////////////////////////////////////////////////
// 1. WININET WRAPPERS: Wininet APIs have either wierd bugs or bugs that come thru the APIs
// from the server. It's also important to keep track of the perf impact
// of each call. These wrappers solve these problems.
///////////////////////////////////////////////////////////////////////////////////////////
/*****************************************************************************\
FUNCTION: FtpSetCurrentDirectoryWrap
DESCRIPTION:
PERF Notes:
[Direct Net Connection]
To: shapitst <Down the Hall>: 1ms
To: rigel.cyberpass.net <San Diego, CA>: 140ms - 200ms
To: ftp.rz.uni-frankfurt.de <Germany>: 570ms - 2496ms
\*****************************************************************************/
HRESULT FtpSetCurrentDirectoryWrap(HINTERNET hConnect, BOOL fAssertOnFailure, LPCWIRESTR pwFtpPath)
{
HRESULT hr = S_OK;
DWORD dwError = 0;
// WARNING: FtpSetCurrentDirectory() may fail if it's not really a directory.
// PERF: Status FtpGetCurrentDirectory/FtpSetCurrentDirectory() takes
// 180-280ms on ftp.microsoft.com on average.
// 500-2000ms on ftp://ftp.tu-clausthal.de/ on average
// 0-10ms on ftp://shapitst/ on average
DEBUG_CODE(DebugStartWatch());
if (!FtpSetCurrentDirectoryA(hConnect, pwFtpPath))
{
dwError = GetLastError();
hr = HRESULT_FROM_WIN32(dwError);
}
DEBUG_CODE(TraceMsg(TF_WININET_DEBUG, "FtpSetCurrentDirectory(%#08lx, \"%hs\") returned %u. Time=%lums", hConnect, pwFtpPath, dwError, DebugStopWatch()));
if (fAssertOnFailure)
{
WININET_ASSERT(SUCCEEDED(hr));
}
return hr;
}
/*****************************************************************************\
FUNCTION: FtpGetCurrentDirectoryWrap
DESCRIPTION:
PERF Notes:
These are for short directory listings. Long listings can take 3-10x.
[Direct Net Connection]
To: shapitst <Down the Hall>: 1ms - 4ms
To: rigel.cyberpass.net <San Diego, CA>: 132ms - 213ms
To: ftp.rz.uni-frankfurt.de <Germany>: 507ms - 2012ms
\*****************************************************************************/
HRESULT FtpGetCurrentDirectoryWrap(HINTERNET hConnect, BOOL fAssertOnFailure, LPWIRESTR pwFtpPath, DWORD cchCurrentDirectory)
{
HRESULT hr = S_OK;
DWORD dwError = 0;
// PERF: Status FtpGetCurrentDirectory/FtpSetCurrentDirectory() takes
// 180-280ms on ftp.microsoft.com on average.
// 500-2000ms on ftp://ftp.tu-clausthal.de/ on average
// 0-10ms on ftp://shapitst/ on average
DEBUG_CODE(DebugStartWatch());
if (!FtpGetCurrentDirectoryA(hConnect, pwFtpPath, &cchCurrentDirectory))
{
dwError = GetLastError();
hr = HRESULT_FROM_WIN32(dwError);
}
DEBUG_CODE(TraceMsg(TF_WININET_DEBUG, "FtpGetCurrentDirectoryA(%#08lx, \"%hs\") returned %u. Time=%lums", hConnect, pwFtpPath, dwError, DebugStopWatch()));
if (fAssertOnFailure)
{
WININET_ASSERT(SUCCEEDED(hr));
}
return hr;
}
/*****************************************************************************\
FUNCTION: FtpGetFileExWrap
DESCRIPTION:
PERF Notes: (*** Depends on file size ***)
[Direct Net Connection]
To: shapitst <Down the Hall>: 100ms - 1,000ms+
To: rigel.cyberpass.net <San Diego, CA>: 1210ms - 1610ms
To: ftp.rz.uni-frankfurt.de <Germany>: ???????
\*****************************************************************************/
HRESULT FtpGetFileExWrap(HINTERNET hConnect, BOOL fAssertOnFailure, LPCWIRESTR pwFtpPath/*Src*/, LPCWSTR pwzFilePath/*Dest*/, BOOL fFailIfExists,
DWORD dwFlagsAndAttributes, DWORD dwFlags, DWORD_PTR dwContext)
{
HRESULT hr = S_OK;
DWORD dwError = 0;
DEBUG_CODE(DebugStartWatch());
if (!FtpGetFileEx(hConnect, pwFtpPath, pwzFilePath, fFailIfExists, dwFlagsAndAttributes, dwFlags, dwContext))
{
dwError = GetLastError();
hr = HRESULT_FROM_WIN32(dwError);
if (HRESULT_FROM_WIN32(ERROR_INTERNET_OPERATION_CANCELLED) == hr)
hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
}
DEBUG_CODE(TraceMsg(TF_WININET_DEBUG, "FtpGetFileEx(%#08lx, \"%hs\", \"%ls\") returned %u. Time=%lums", hConnect, pwFtpPath, pwzFilePath, dwError, DebugStopWatch()));
if (fAssertOnFailure)
{
WININET_ASSERT(SUCCEEDED(hr));
}
return hr;
}
/*****************************************************************************\
FUNCTION: FtpPutFileExWrap
DESCRIPTION:
PERF Notes: (*** Depends on file size ***)
[Direct Net Connection]
To: shapitst <Down the Hall>: 194ms - 400ms+
To: rigel.cyberpass.net <San Diego, CA>: 1662ms - 8454ms
To: ftp.rz.uni-frankfurt.de <Germany>: ???????
\*****************************************************************************/
HRESULT FtpPutFileExWrap(HINTERNET hConnect, BOOL fAssertOnFailure, LPCWSTR pwzFilePath/*Src*/, LPCWIRESTR pwFtpPath/*Dest*/, DWORD dwFlags, DWORD_PTR dwContext)
{
HRESULT hr = S_OK;
DWORD dwError = 0;
DEBUG_CODE(DebugStartWatch());
if (!FtpPutFileEx(hConnect, pwzFilePath, pwFtpPath, dwFlags, dwContext))
{
dwError = GetLastError();
hr = HRESULT_FROM_WIN32(dwError);
}
DEBUG_CODE(TraceMsg(TF_WININET_DEBUG, "FtpPutFileEx(%#08lx, \"%ls\", \"%hs\") returned %u. Time=%lums", hConnect, pwzFilePath, pwFtpPath, dwError, DebugStopWatch()));
if (fAssertOnFailure)
{
WININET_ASSERT(SUCCEEDED(hr));
}
return hr;
}
/*****************************************************************************\
FUNCTION: FtpDeleteFileWrap
DESCRIPTION:
PERF Notes:
[Direct Net Connection]
To: shapitst <Down the Hall>: 4ms (22ms once in a while)
To: rigel.cyberpass.net <San Diego, CA>: 175ms - 291ms
To: ftp.rz.uni-frankfurt.de <Germany>: ???????
\*****************************************************************************/
HRESULT FtpDeleteFileWrap(HINTERNET hConnect, BOOL fAssertOnFailure, LPCWIRESTR pwFtpFileName)
{
HRESULT hr = S_OK;
DWORD dwError = 0;
DEBUG_CODE(DebugStartWatch());
if (!FtpDeleteFileA(hConnect, pwFtpFileName))
{
dwError = GetLastError();
hr = HRESULT_FROM_WIN32(dwError);
}
DEBUG_CODE(TraceMsg(TF_WININET_DEBUG, "FtpDeleteFile(%#08lx, \"%hs\") returned %u. Time=%lums", hConnect, pwFtpFileName, dwError, DebugStopWatch()));
if (fAssertOnFailure)
{
WININET_ASSERT(SUCCEEDED(hr));
}
return hr;
}
/*****************************************************************************\
FUNCTION: FtpRenameFileWrap
DESCRIPTION:
PERF Notes:
[Direct Net Connection]
To: shapitst <Down the Hall>: 4ms
To: rigel.cyberpass.net <San Diego, CA>: 329ms - 446ms
To: ftp.rz.uni-frankfurt.de <Germany>: ???????
\*****************************************************************************/
HRESULT FtpRenameFileWrap(HINTERNET hConnect, BOOL fAssertOnFailure, LPCWIRESTR pwFtpFileNameExisting, LPCWIRESTR pwFtpFileNameNew)
{
HRESULT hr = S_OK;
DWORD dwError = 0;
DEBUG_CODE(DebugStartWatch());
if (!FtpRenameFileA(hConnect, pwFtpFileNameExisting, pwFtpFileNameNew))
{
dwError = GetLastError();
hr = HRESULT_FROM_WIN32(dwError);
}
DEBUG_CODE(TraceMsg(TF_WININET_DEBUG, "FtpRenameFile(%#08lx, \"%hs\", \"%hs\") returned %u. Time=%lums", hConnect, pwFtpFileNameExisting, pwFtpFileNameNew, dwError, DebugStopWatch()));
if (fAssertOnFailure)
{
WININET_ASSERT(SUCCEEDED(hr));
}
return hr;
}
/*****************************************************************************\
FUNCTION: FtpOpenFileWrap
DESCRIPTION:
PERF Notes:
[Direct Net Connection]
To: shapitst <Down the Hall>: 2ms
To: rigel.cyberpass.net <San Diego, CA>: 757ms - 817ms
To: ftp.rz.uni-frankfurt.de <Germany>: 2112ms - 10026ms
\*****************************************************************************/
HRESULT FtpOpenFileWrap(HINTERNET hConnect, BOOL fAssertOnFailure, LPCWIRESTR pwFtpFileName, DWORD dwAccess, DWORD dwFlags, DWORD_PTR dwContext, HINTERNET * phFileHandle)
{
HRESULT hr = S_OK;
DWORD dwError = 0;
DEBUG_CODE(DebugStartWatch());
*phFileHandle = FtpOpenFileA(hConnect, pwFtpFileName, dwAccess, dwFlags, dwContext);
if (!*phFileHandle)
{
dwError = GetLastError();
hr = HRESULT_FROM_WIN32(dwError);
}
DEBUG_CODE(TraceMsg(TF_WININET_DEBUG, "FtpOpenFile(%#08lx, \"%hs\") returned %u. Time=%lums", hConnect, pwFtpFileName, dwError, DebugStopWatch()));
if (fAssertOnFailure)
{
WININET_ASSERT(SUCCEEDED(hr));
}
return hr;
}
/*****************************************************************************\
FUNCTION: FtpCreateDirectoryWrap
DESCRIPTION:
PERF Notes:
[Direct Net Connection]
To: shapitst <Down the Hall>: 3ms
To: rigel.cyberpass.net <San Diego, CA>: 210ms - 350ms
To: ftp.rz.uni-frankfurt.de <Germany>: ???????
\*****************************************************************************/
HRESULT FtpCreateDirectoryWrap(HINTERNET hConnect, BOOL fAssertOnFailure, LPCWIRESTR pwFtpPath)
{
HRESULT hr = S_OK;
DWORD dwError = 0;
DEBUG_CODE(DebugStartWatch());
if (!FtpCreateDirectoryA(hConnect, pwFtpPath))
{
dwError = GetLastError();
hr = HRESULT_FROM_WIN32(dwError);
}
DEBUG_CODE(TraceMsg(TF_WININET_DEBUG, "FtpCreateDirectoryA(%#08lx, \"%hs\") returned %u. Time=%lums", hConnect, pwFtpPath, dwError, DebugStopWatch()));
if (fAssertOnFailure)
{
WININET_ASSERT(SUCCEEDED(hr));
}
return hr;
}
/*****************************************************************************\
FUNCTION: FtpRemoveDirectoryWrap
DESCRIPTION:
PERF Notes:
[Direct Net Connection]
To: shapitst <Down the Hall>: 2ms
To: rigel.cyberpass.net <San Diego, CA>: 157ms - 227ms
To: ftp.rz.uni-frankfurt.de <Germany>: ???????
\*****************************************************************************/
HRESULT FtpRemoveDirectoryWrap(HINTERNET hConnect, BOOL fAssertOnFailure, LPCWIRESTR pwFtpPath)
{
HRESULT hr = S_OK;
DWORD dwError = 0;
DEBUG_CODE(DebugStartWatch());
if (!FtpRemoveDirectoryA(hConnect, pwFtpPath))
{
dwError = GetLastError();
hr = HRESULT_FROM_WIN32(dwError);
}
DEBUG_CODE(TraceMsg(TF_WININET_DEBUG, "FtpRemoveDirectory(%#08lx, \"%hs\") returned %u. Time=%lums", hConnect, pwFtpPath, dwError, DebugStopWatch()));
if (fAssertOnFailure)
{
WININET_ASSERT(SUCCEEDED(hr));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -