initial commit
This commit is contained in:
@@ -0,0 +1,650 @@
|
||||
#include "sgu_stdafx.h"
|
||||
#include "sgu_download_ant.h"
|
||||
#include "sgu_utils.h"
|
||||
|
||||
#include "libEncrypt_MD5.h"
|
||||
|
||||
#define debugLog(...) __noop
|
||||
|
||||
bool parseURL(const wchar_t* pstrURL, INTERNET_SCHEME& schemeType, wchar_t* strServer, wchar_t* strObject, INTERNET_PORT& nPort);
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
CDownloadAnt::CDownloadAnt()
|
||||
{
|
||||
m_hThread = 0;
|
||||
|
||||
m_theStateCategory = IDLE;
|
||||
m_theState = IDLE_NOTINIT;
|
||||
|
||||
m_wszURLToDownload[0] = 0;
|
||||
m_wszFileToDownloadInto[0] = 0;
|
||||
|
||||
m_pOwner = NULL;
|
||||
|
||||
m_schemeType = INTERNET_SCHEME_UNKNOWN;
|
||||
m_wszServer[0] = 0;
|
||||
m_wszObject[0] = 0;
|
||||
m_nPort = 80;
|
||||
|
||||
m_hInternetSession = NULL;
|
||||
m_hHttpConnection = NULL;
|
||||
m_hHttpFile = NULL;
|
||||
|
||||
m_dwUserCmd = MANAGER_CMD_CONTINUE;
|
||||
m_nOverTime = INFINITE;
|
||||
|
||||
m_bGotFileSize = FALSE;
|
||||
m_dwFileSizeTotal = 0;
|
||||
m_dwFileSizeRead = 0;
|
||||
m_fpFileToWrite = NULL;
|
||||
|
||||
UserCallBack = NULL;
|
||||
|
||||
m_wszStatusInfor[0] = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
CDownloadAnt::~CDownloadAnt()
|
||||
{
|
||||
//关闭
|
||||
UserCallBack = NULL;
|
||||
if (m_hHttpFile)
|
||||
{
|
||||
::InternetCloseHandle(m_hHttpFile);
|
||||
m_hHttpFile = NULL;
|
||||
}
|
||||
if (m_hHttpConnection)
|
||||
{
|
||||
::InternetCloseHandle(m_hHttpConnection);
|
||||
m_hHttpConnection = NULL;
|
||||
}
|
||||
if (m_hInternetSession)
|
||||
{
|
||||
::InternetCloseHandle(m_hInternetSession);
|
||||
m_hInternetSession = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
bool CDownloadAnt::init(const wchar_t* wszURLToDownload, const wchar_t* wszFileToDownloadInto,
|
||||
DOWNANT_STATUS_CALLBACK funcUserCallBack, void* pOwner, unsigned int nOverTime)
|
||||
{
|
||||
assert(m_theStateCategory != BUSY);
|
||||
assert(wszURLToDownload && wszFileToDownloadInto);
|
||||
|
||||
StringCchCopyW(m_wszURLToDownload, INTERNET_MAX_URL_LENGTH, wszURLToDownload);
|
||||
StringCchCopyW(m_wszFileToDownloadInto, MAX_PATH, wszFileToDownloadInto);
|
||||
|
||||
debugLog(L"build ant download \"%s\" to \"%s\"", m_wszURLToDownload, m_wszFileToDownloadInto);
|
||||
|
||||
m_pOwner = pOwner;
|
||||
UserCallBack = funcUserCallBack;
|
||||
|
||||
if (wcslen(m_wszURLToDownload) > 0 && wcslen(m_wszFileToDownloadInto) > 0)
|
||||
{
|
||||
if (!parseURL(m_wszURLToDownload, m_schemeType, m_wszServer, m_wszObject, m_nPort) ||
|
||||
m_schemeType == INTERNET_SCHEME_UNKNOWN)
|
||||
{
|
||||
const wchar_t* wsz = L"Parser URL Error: %s";
|
||||
StringCchPrintfW(m_wszStatusInfor, MAX_PATH, L"Parser URL Error: %s", m_wszURLToDownload);
|
||||
setStatus(IDLE_INIT_FAILED);
|
||||
return FALSE;
|
||||
}
|
||||
setStatus(IDLE_INIT_SUCCESS);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
StringCchPrintfW(m_wszStatusInfor, MAX_PATH, L"url and local file address can't be empty!");
|
||||
setStatus(IDLE_INIT_FAILED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
m_nOverTime = nOverTime;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
void CDownloadAnt::begin(bool bBlock)
|
||||
{
|
||||
assert(m_theState == IDLE_INIT_SUCCESS);
|
||||
|
||||
UINT nThreadID;
|
||||
m_hThread = (HANDLE)::_beginthreadex(NULL, 0, _downloadThread, this, CREATE_SUSPENDED, &nThreadID);
|
||||
|
||||
if (m_hThread == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus(BUSY_BEGIN_THREAD);
|
||||
m_beginTime = ::GetTickCount64();
|
||||
ResumeThread(m_hThread);
|
||||
|
||||
if (bBlock)
|
||||
{
|
||||
::WaitForSingleObject(m_hThread, INFINITE);
|
||||
//关闭句柄
|
||||
CloseHandle(m_hThread); m_hThread = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
UINT CDownloadAnt::_downloadThread(void* pParam)
|
||||
{
|
||||
CDownloadAnt* pAnt = (CDownloadAnt*)pParam;
|
||||
assert(pAnt);
|
||||
|
||||
try
|
||||
{
|
||||
pAnt->downloadThread();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
void CDownloadAnt::downloadThread(void)
|
||||
{
|
||||
assert(m_theState == BUSY_BEGIN_THREAD);
|
||||
assert(m_hInternetSession == NULL);
|
||||
assert(m_fpFileToWrite == NULL);
|
||||
assert(m_hHttpConnection == NULL);
|
||||
assert(m_hHttpFile == NULL);
|
||||
|
||||
_wfopen_s(&m_fpFileToWrite, m_wszFileToDownloadInto, L"wb");
|
||||
if (m_fpFileToWrite == NULL)
|
||||
{
|
||||
StringCchPrintfW(m_wszStatusInfor, MAX_PATH, L"Create local file error: %s, Error:%d", m_wszFileToDownloadInto, ::GetLastError());
|
||||
setStatus(FINISH_ERROR_TRY_OPEN_LOCALFILE);
|
||||
return;
|
||||
}
|
||||
|
||||
//打开Internet句柄
|
||||
m_hInternetSession = InternetOpenW(NULL, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
|
||||
if (m_hInternetSession == NULL)
|
||||
{
|
||||
StringCchPrintfW(m_wszStatusInfor, MAX_PATH, L"(::InternetOpen) Error:%d\n", ::GetLastError());
|
||||
setStatus(FINISH_ERROR_INTERNET_OPEN);
|
||||
return;
|
||||
}
|
||||
if (_checkAbort()) return;
|
||||
|
||||
DWORD dwTemp = 0, dwSize = sizeof(DWORD);
|
||||
BOOL bRet = InternetQueryOptionW(m_hInternetSession, INTERNET_OPTION_MAX_CONNS_PER_SERVER, &dwTemp, &dwSize);
|
||||
DWORD dwErr = GetLastError();
|
||||
|
||||
//设置状态回调函数
|
||||
if (::InternetSetStatusCallbackW(m_hInternetSession, _onWininetStatusCallBack) == INTERNET_INVALID_STATUS_CALLBACK)
|
||||
{
|
||||
StringCchPrintfW(m_wszStatusInfor, MAX_PATH, L"(::InternetSetStatusCallback), Error:%d\n", ::GetLastError());
|
||||
setStatus(FINISH_ERROR_SETSTATUSCALLBACK);
|
||||
return;
|
||||
}
|
||||
if (_checkAbort()) return;
|
||||
|
||||
DWORD serviceType = 0;
|
||||
if(m_schemeType == INTERNET_SCHEME_HTTP||m_schemeType== INTERNET_SCHEME_HTTPS)
|
||||
{
|
||||
serviceType = INTERNET_SERVICE_HTTP;
|
||||
}
|
||||
else if (m_schemeType == INTERNET_SCHEME_FTP)
|
||||
{
|
||||
serviceType = INTERNET_SERVICE_FTP;
|
||||
}
|
||||
else
|
||||
{
|
||||
StringCchPrintfW(m_wszStatusInfor, MAX_PATH, L"Unsupported scheme type: %d", m_schemeType);
|
||||
setStatus(FINISH_ERROR_UNSUPPORTED_SCHEME);
|
||||
return;
|
||||
}
|
||||
|
||||
//打开Internet连接
|
||||
m_hHttpConnection = InternetConnectW(m_hInternetSession, m_wszServer, m_nPort, NULL,
|
||||
NULL, serviceType, 0, (DWORD_PTR)this);
|
||||
|
||||
if (m_hHttpConnection == NULL)
|
||||
{
|
||||
StringCchPrintfW(m_wszStatusInfor, MAX_PATH, L"(::InternetConnect), Error:%d\n", ::GetLastError());
|
||||
setStatus(FINISH_ERROR_INTERNETCONNECT);
|
||||
return;
|
||||
}
|
||||
if (_checkAbort()) return;
|
||||
|
||||
//生成Request
|
||||
const wchar_t* ppszAcceptTypes[2];
|
||||
ppszAcceptTypes[0] = L"*/*";
|
||||
ppszAcceptTypes[1] = NULL;
|
||||
|
||||
DWORD dwFlags = INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_COOKIES;
|
||||
if(serviceType==INTERNET_SERVICE_HTTP && m_schemeType == INTERNET_SCHEME_HTTPS)
|
||||
{
|
||||
dwFlags |= INTERNET_FLAG_SECURE;
|
||||
}
|
||||
|
||||
m_hHttpFile = HttpOpenRequestW(m_hHttpConnection,
|
||||
L"GET", m_wszObject, NULL, NULL, ppszAcceptTypes,
|
||||
dwFlags,
|
||||
(DWORD_PTR)this);
|
||||
if (m_hHttpFile == NULL)
|
||||
{
|
||||
StringCchPrintfW(m_wszStatusInfor, MAX_PATH, L"(::HttpOpenRequest), Error:%d\n", ::GetLastError());
|
||||
setStatus(FINISH_ERROR_OPENREQUEST);
|
||||
return;
|
||||
}
|
||||
if (_checkAbort()) return;
|
||||
setStatus(BUSY_OPEN_REQUEST);
|
||||
|
||||
//发送Request
|
||||
BOOL bSend = HttpSendRequestW(m_hHttpFile, NULL, 0, NULL, 0);
|
||||
if (!bSend)
|
||||
{
|
||||
StringCchPrintfW(m_wszStatusInfor, MAX_PATH, L"(::HttpSendRequest), Error:%d\n", ::GetLastError());
|
||||
setStatus(FINISH_ERROR_SENDREQUEST);
|
||||
return;
|
||||
}
|
||||
if (_checkAbort()) return;
|
||||
|
||||
//查询状态
|
||||
DWORD dwInfoSize = 64;
|
||||
CHAR szStatusCode[64] = { 0 };
|
||||
if (!::HttpQueryInfoW(m_hHttpFile, HTTP_QUERY_STATUS_CODE, szStatusCode, &dwInfoSize, NULL))
|
||||
{
|
||||
StringCchPrintfW(m_wszStatusInfor, MAX_PATH, L"Failed in call to HttpQueryInfo for HTTP query status code, Error:%d\n", ::GetLastError());
|
||||
setStatus(FINISH_ERROR_QUERYINFO);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
long nStatusCode = atoi(szStatusCode);
|
||||
|
||||
if (nStatusCode != HTTP_STATUS_OK)
|
||||
{
|
||||
m_theState = FINISH_ERROR_INVALID_HTTP_RESPONSE;
|
||||
|
||||
if (nStatusCode == HTTP_STATUS_PROXY_AUTH_REQ)
|
||||
{
|
||||
StringCchPrintfW(m_wszStatusInfor, MAX_PATH, L"Authentication errors, Status Code:%d\n", nStatusCode);
|
||||
setStatus(FINISH_ERROR_NEED_PROXY_AUTH_REQ);
|
||||
return;
|
||||
}
|
||||
else if (nStatusCode == HTTP_STATUS_DENIED)
|
||||
{
|
||||
StringCchPrintfW(m_wszStatusInfor, MAX_PATH, L"Authentication errors, Status Code:%d\n", nStatusCode);
|
||||
setStatus(FINISH_ERROR_DENIED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_checkAbort()) return;
|
||||
|
||||
// 取得文件大小
|
||||
dwInfoSize = 64;
|
||||
wchar_t wszContentLength[64] = { 0 };
|
||||
if (HttpQueryInfoW(m_hHttpFile, HTTP_QUERY_CONTENT_LENGTH, wszContentLength, &dwInfoSize, NULL))
|
||||
{
|
||||
m_bGotFileSize = TRUE;
|
||||
m_dwFileSizeTotal = _wtoi64(wszContentLength);
|
||||
StringCchPrintfW(m_wszStatusInfor, MAX_PATH, L"FileSize: %I64d", m_dwFileSizeTotal);
|
||||
}
|
||||
|
||||
debugLog(L"Get file size %I64d, begin download...", m_dwFileSizeTotal);
|
||||
//得到文件大小,让Manager处理位置
|
||||
setStatus(BUSY_GET_FILE_INFORMATION);
|
||||
if (_checkAbort()) return;
|
||||
|
||||
//开始下载
|
||||
ULONGLONG startTicks = ::GetTickCount64();
|
||||
DWORD dwBytesRead = 0;
|
||||
char szReadBuf[DOWNANT_MINSIZE] = { 0 };
|
||||
DWORD dwBytesToRead = DOWNANT_MINSIZE;
|
||||
m_dwFileSizeRead = 0;
|
||||
|
||||
MD5Context md5Ctx;
|
||||
md5Init(&md5Ctx);
|
||||
|
||||
setStatus(BUSY_BEGIN_DOWNFILE);
|
||||
do
|
||||
{
|
||||
if (!InternetReadFile(m_hHttpFile, szReadBuf, dwBytesToRead, &dwBytesRead))
|
||||
{
|
||||
StringCchPrintfW(m_wszStatusInfor, MAX_PATH, L"(::InternetReadFile), Error:%d\n", ::GetLastError());
|
||||
setStatus(FINISH_ERROR_READFILE);
|
||||
return;
|
||||
}
|
||||
else if (dwBytesRead && m_dwUserCmd == MANAGER_CMD_CONTINUE)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (dwBytesRead != ::fwrite(szReadBuf, 1, dwBytesRead, m_fpFileToWrite))
|
||||
{
|
||||
throw FINISH_ERROR_EXCEPTION;
|
||||
}
|
||||
|
||||
md5Update(&md5Ctx, (unsigned char*)szReadBuf, dwBytesRead);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
StringCchPrintfW(m_wszStatusInfor, MAX_PATH, L"write local file error!, Error:%d", ::GetLastError());
|
||||
setStatus(FINISH_ERROR_EXCEPTION);
|
||||
return;
|
||||
}
|
||||
|
||||
m_dwFileSizeRead += dwBytesRead;
|
||||
onStatusCallback();
|
||||
}
|
||||
|
||||
if (_checkAbort())
|
||||
{
|
||||
if (m_fpFileToWrite)::fclose(m_fpFileToWrite);
|
||||
m_fpFileToWrite = NULL;
|
||||
return;
|
||||
}
|
||||
} while (dwBytesRead && m_dwUserCmd == MANAGER_CMD_CONTINUE);
|
||||
|
||||
//生成MD5
|
||||
m_fileMD5 = md5Finalize(&md5Ctx);
|
||||
|
||||
if (m_fpFileToWrite)::fclose(m_fpFileToWrite);
|
||||
m_fpFileToWrite = NULL;
|
||||
|
||||
debugLog(L"Download success over!");
|
||||
|
||||
setStatus(FINISH_SUCCESS_OVER);
|
||||
return;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
bool CDownloadAnt::checkMD5(const char* md5_string) const
|
||||
{
|
||||
MD5Digest md5;
|
||||
if (!string2MD5(md5_string, md5)) return false;
|
||||
|
||||
return (0 == memcmp(&md5, &m_fileMD5, md5.size()));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
void CALLBACK CDownloadAnt::_onWininetStatusCallBack(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus,
|
||||
LPVOID lpvStatusInformation, DWORD dwStatusInformationLength)
|
||||
{
|
||||
CDownloadAnt* pDownMan = (CDownloadAnt*)dwContext;
|
||||
assert(pDownMan);
|
||||
|
||||
pDownMan->onWininetStatusCallBack(hInternet, dwInternetStatus, lpvStatusInformation, dwStatusInformationLength);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
void CDownloadAnt::onWininetStatusCallBack(HINTERNET /*hInternet*/, DWORD dwInternetStatus,
|
||||
LPVOID lpvStatusInformation, DWORD /*dwStatusInformationLength*/)
|
||||
{
|
||||
switch (dwInternetStatus)
|
||||
{
|
||||
case INTERNET_STATUS_RESOLVING_NAME:
|
||||
{
|
||||
StringCchCopyW(m_wszStatusInfor, MAX_PATH, (LPCWSTR)lpvStatusInformation);
|
||||
setStatus(BUSY_RESOLVING_NAME);
|
||||
break;
|
||||
}
|
||||
case INTERNET_STATUS_NAME_RESOLVED:
|
||||
{
|
||||
StringCchCopyW(m_wszStatusInfor, MAX_PATH, (LPCWSTR)lpvStatusInformation);
|
||||
setStatus(BUSY_RESOLVED_NAME);
|
||||
break;
|
||||
}
|
||||
case INTERNET_STATUS_CONNECTING_TO_SERVER:
|
||||
{
|
||||
StringCchCopyW(m_wszStatusInfor, MAX_PATH, (LPCWSTR)lpvStatusInformation);
|
||||
setStatus(BUSY_CONNECTING);
|
||||
break;
|
||||
}
|
||||
case INTERNET_STATUS_CONNECTED_TO_SERVER:
|
||||
{
|
||||
StringCchCopyW(m_wszStatusInfor, MAX_PATH, (LPCWSTR)lpvStatusInformation);
|
||||
setStatus(BUSY_CONNECTED);
|
||||
break;
|
||||
}
|
||||
case INTERNET_STATUS_REDIRECT:
|
||||
{
|
||||
StringCchCopyW(m_wszStatusInfor, MAX_PATH, (LPCWSTR)lpvStatusInformation);
|
||||
setStatus(BUSY_REDIRECTING);
|
||||
break;
|
||||
}
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
void CDownloadAnt::setStatus(CDownloadAnt::DOWN_STATE newState)
|
||||
{
|
||||
m_theState = newState;
|
||||
onStatusCallback();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
void CDownloadAnt::onStatusCallback(void)
|
||||
{
|
||||
switch (m_theState)
|
||||
{
|
||||
case IDLE_NOTINIT:
|
||||
case IDLE_INIT_SUCCESS:
|
||||
case IDLE_INIT_FAILED:
|
||||
{
|
||||
m_theStateCategory = IDLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case BUSY_BEGIN_THREAD:
|
||||
case BUSY_OPEN_REQUEST:
|
||||
case BUSY_RESOLVING_NAME:
|
||||
case BUSY_RESOLVED_NAME:
|
||||
case BUSY_CONNECTING:
|
||||
case BUSY_CONNECTED:
|
||||
case BUSY_REDIRECTING:
|
||||
case BUSY_GET_FILE_INFORMATION:
|
||||
case BUSY_BEGIN_DOWNFILE:
|
||||
{
|
||||
m_theStateCategory = BUSY;
|
||||
}
|
||||
break;
|
||||
|
||||
case FINISH_SUCCESS_OVER:
|
||||
case FINISH_SUCCESS_STOPHERE:
|
||||
{
|
||||
m_theStateCategory = FINISH_SUCCESS;
|
||||
}
|
||||
break;
|
||||
|
||||
case FINISH_FORCEABORT:
|
||||
case FINISH_ERROR_TIMEOUT:
|
||||
case FINISH_ERROR_TRY_OPEN_LOCALFILE:
|
||||
case FINISH_ERROR_INTERNET_OPEN:
|
||||
case FINISH_ERROR_SETSTATUSCALLBACK:
|
||||
case FINISH_ERROR_INTERNETCONNECT:
|
||||
case FINISH_ERROR_OPENREQUEST:
|
||||
case FINISH_ERROR_SENDREQUEST:
|
||||
case FINISH_ERROR_QUERYINFO:
|
||||
case FINISH_ERROR_NEED_PROXY_AUTH_REQ:
|
||||
case FINISH_ERROR_DENIED:
|
||||
case FINISH_ERROR_INVALID_HTTP_RESPONSE:
|
||||
case FINISH_ERROR_READFILE:
|
||||
case FINISH_ERROR_EXCEPTION:
|
||||
{
|
||||
m_theStateCategory = FINISH_NOT_SUCCESS;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_theStateCategory == FINISH_SUCCESS || m_theStateCategory == FINISH_NOT_SUCCESS)
|
||||
{
|
||||
if (m_fpFileToWrite)
|
||||
{
|
||||
::fclose(m_fpFileToWrite);
|
||||
m_fpFileToWrite = NULL;
|
||||
}
|
||||
|
||||
if (m_hHttpFile)
|
||||
{
|
||||
::InternetCloseHandle(m_hHttpFile);
|
||||
m_hHttpFile = NULL;
|
||||
}
|
||||
if (m_hHttpConnection)
|
||||
{
|
||||
::InternetCloseHandle(m_hHttpConnection);
|
||||
m_hHttpConnection = NULL;
|
||||
}
|
||||
if (m_hInternetSession)
|
||||
{
|
||||
::InternetCloseHandle(m_hInternetSession);
|
||||
m_hInternetSession = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (UserCallBack)
|
||||
{
|
||||
m_dwUserCmd = UserCallBack(m_pOwner, this);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------
|
||||
BOOL CDownloadAnt::_checkAbort(void)
|
||||
{
|
||||
HANDLE hCloseMutex = OpenMutexW(SYNCHRONIZE, FALSE, L"Global\\8e931dcb-868e-4ba6-aff4-d1a22bc9d476");
|
||||
if (hCloseMutex != 0)
|
||||
{
|
||||
CloseHandle(hCloseMutex);
|
||||
debugLog(L"[ANT]Receive autoclose signal, quit!");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (MANAGER_CMD_FORCEABORT == m_dwUserCmd)
|
||||
{
|
||||
setStatus(FINISH_FORCEABORT);
|
||||
return TRUE;
|
||||
}
|
||||
if (MANAGER_CMD_STOPHERE == m_dwUserCmd)
|
||||
{
|
||||
setStatus(FINISH_SUCCESS_STOPHERE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (m_nOverTime != INFINITE && m_theStateCategory == BUSY)
|
||||
{
|
||||
ULONGLONG timeNow = ::GetTickCount64();
|
||||
ULONGLONG timeRun;
|
||||
if (timeNow >= m_beginTime) timeRun = timeNow - m_beginTime;
|
||||
else timeRun = timeNow + (0XFFFFFFFFFFFFFFFFULL - m_beginTime);
|
||||
|
||||
if (timeRun > m_nOverTime * 1000ULL)
|
||||
{
|
||||
setStatus(FINISH_ERROR_TIMEOUT);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
BOOL MyAfxIsValidAddress(const void* lp, UINT nBytes, BOOL bReadWrite /* = TRUE */)
|
||||
{
|
||||
// simple version using Win-32 APIs for pointer validation.
|
||||
return (lp != NULL && !IsBadReadPtr(lp, nBytes) &&
|
||||
(!bReadWrite || !IsBadWritePtr((LPVOID)lp, nBytes)));
|
||||
}
|
||||
|
||||
bool _AfxParseURLWorker(const wchar_t* pstrURL, LPURL_COMPONENTSW lpComponents,
|
||||
INTERNET_SCHEME& schemeType, INTERNET_PORT& nPort, DWORD dwFlags)
|
||||
{
|
||||
// this function will return bogus stuff if lpComponents
|
||||
// isn't set up to copy the components
|
||||
|
||||
assert(lpComponents != NULL && pstrURL != NULL);
|
||||
if (lpComponents == NULL || pstrURL == NULL)
|
||||
return FALSE;
|
||||
assert(lpComponents->dwHostNameLength == 0 ||
|
||||
lpComponents->lpszHostName != NULL);
|
||||
assert(lpComponents->dwUrlPathLength == 0 ||
|
||||
lpComponents->lpszUrlPath != NULL);
|
||||
assert(lpComponents->dwUserNameLength == 0 ||
|
||||
lpComponents->lpszUserName != NULL);
|
||||
assert(lpComponents->dwPasswordLength == 0 ||
|
||||
lpComponents->lpszPassword != NULL);
|
||||
|
||||
assert(MyAfxIsValidAddress(lpComponents, sizeof(URL_COMPONENTS), TRUE));
|
||||
|
||||
wchar_t* pstrCanonicalizedURL;
|
||||
wchar_t szCanonicalizedURL[INTERNET_MAX_URL_LENGTH];
|
||||
DWORD dwNeededLength = INTERNET_MAX_URL_LENGTH;
|
||||
BOOL bRetVal;
|
||||
BOOL bMustFree = FALSE;
|
||||
DWORD dwCanonicalizeFlags = dwFlags &
|
||||
(ICU_NO_ENCODE | ICU_DECODE | ICU_NO_META |
|
||||
ICU_ENCODE_SPACES_ONLY | ICU_BROWSER_MODE);
|
||||
DWORD dwCrackFlags = dwFlags & (ICU_ESCAPE | ICU_USERNAME);
|
||||
|
||||
bRetVal = InternetCanonicalizeUrlW(pstrURL, szCanonicalizedURL,
|
||||
&dwNeededLength, dwCanonicalizeFlags);
|
||||
|
||||
if (!bRetVal)
|
||||
{
|
||||
if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||
return FALSE;
|
||||
|
||||
pstrCanonicalizedURL = new wchar_t[dwNeededLength];
|
||||
bMustFree = TRUE;
|
||||
bRetVal = InternetCanonicalizeUrlW(pstrURL, pstrCanonicalizedURL,
|
||||
&dwNeededLength, dwCanonicalizeFlags);
|
||||
if (!bRetVal)
|
||||
{
|
||||
delete[] pstrCanonicalizedURL;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
pstrCanonicalizedURL = szCanonicalizedURL;
|
||||
|
||||
// now that it's safely canonicalized, crack it
|
||||
bRetVal = InternetCrackUrlW(pstrCanonicalizedURL, 0, dwCrackFlags, lpComponents);
|
||||
if (bMustFree)
|
||||
delete[] pstrCanonicalizedURL;
|
||||
|
||||
if (bRetVal)
|
||||
{
|
||||
nPort = lpComponents->nPort;
|
||||
schemeType = lpComponents->nScheme;
|
||||
}
|
||||
else
|
||||
{
|
||||
schemeType = INTERNET_SCHEME_UNKNOWN;
|
||||
}
|
||||
|
||||
return bRetVal == TRUE;
|
||||
}
|
||||
|
||||
bool parseURL(const wchar_t* pstrURL, INTERNET_SCHEME& schemeType, wchar_t* strServer, wchar_t* strObject, INTERNET_PORT& nPort)
|
||||
{
|
||||
schemeType = INTERNET_SCHEME_UNKNOWN;
|
||||
|
||||
assert(pstrURL != NULL);
|
||||
if (pstrURL == NULL)
|
||||
return FALSE;
|
||||
|
||||
URL_COMPONENTSW urlComponents;
|
||||
memset(&urlComponents, 0, sizeof(URL_COMPONENTS));
|
||||
urlComponents.dwStructSize = sizeof(URL_COMPONENTS);
|
||||
|
||||
urlComponents.dwHostNameLength = MAX_PATH;
|
||||
urlComponents.lpszHostName = strServer;
|
||||
urlComponents.dwUrlPathLength = INTERNET_MAX_URL_LENGTH;
|
||||
urlComponents.lpszUrlPath = strObject;
|
||||
|
||||
return _AfxParseURLWorker(pstrURL, &urlComponents, schemeType, nPort, ICU_BROWSER_MODE);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user