📄 ceinet.cpp
字号:
#include "stdafx.h"
#include <wininet.h>
#include <afxtempl.h>
#include <afxmt.h>
#pragma warning(disable: 4706)
#pragma warning(disable: 4074)
#include "ceinet.h"
typedef struct CEtagServiceTable {
DWORD dwService;
LPCTSTR pstrIdentifier;
} CESvcTable;
AFX_STATIC_DATA const TCHAR _CEURLftp[] = _T("ftp://");
class CSessionMapPtrToPtr : public CMapPtrToPtr
{
private:
CCriticalSection m_sect;
public:
CSessionMapPtrToPtr() { }
~CSessionMapPtrToPtr() { }
void SetAt(HINTERNET hInternet, CCEInternetSession* pSess)
{
m_sect.Lock();
CMapPtrToPtr::SetAt(hInternet, pSess);
m_sect.Unlock();
}
void RemoveKey(HINTERNET hInternet)
{
m_sect.Lock();
CMapPtrToPtr::RemoveKey(hInternet);
m_sect.Unlock();
}
BOOL Lookup(HINTERNET hInternet, CCEInternetSession*& refpSession)
{
BOOL bRet;
m_sect.Lock();
bRet = CMapPtrToPtr::Lookup(hInternet, (void*&) refpSession);
m_sect.Unlock();
return bRet;
}
};
CSessionMapPtrToPtr _CESessionMap;
/////////////////////////////////////////////////////////////////////////////
// Global Functions
bool __stdcall _CEParseURLWorker(LPCTSTR pstrURL,
LPURL_COMPONENTS lpComponents, DWORD& dwServiceType,
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(AfxIsValidAddress(lpComponents, sizeof(URL_COMPONENTS), TRUE));
LPTSTR pstrCanonicalizedURL;
TCHAR 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 = InternetCanonicalizeUrl(pstrURL, szCanonicalizedURL,
&dwNeededLength, dwCanonicalizeFlags);
if (!bRetVal)
{
if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
return FALSE;
pstrCanonicalizedURL = new TCHAR[dwNeededLength];
bMustFree = TRUE;
bRetVal = InternetCanonicalizeUrl(pstrURL, pstrCanonicalizedURL,
&dwNeededLength, dwCanonicalizeFlags);
if (!bRetVal)
{
delete [] pstrCanonicalizedURL;
return FALSE;
}
}
else
pstrCanonicalizedURL = szCanonicalizedURL;
// now that it's safely canonicalized, crack it
bRetVal = InternetCrackUrl(pstrCanonicalizedURL, 0,
dwCrackFlags, lpComponents);
if (bMustFree)
delete [] pstrCanonicalizedURL;
// convert to MFC-style service ID
if (!bRetVal)
dwServiceType = AFX_INET_SERVICE_UNK;
else
{
nPort = lpComponents->nPort;
switch (lpComponents->nScheme)
{
case INTERNET_SCHEME_FTP:
dwServiceType = AFX_INET_SERVICE_FTP;
break;
case INTERNET_SCHEME_GOPHER:
dwServiceType = AFX_INET_SERVICE_GOPHER;
break;
case INTERNET_SCHEME_HTTP:
dwServiceType = AFX_INET_SERVICE_HTTP;
break;
case INTERNET_SCHEME_HTTPS:
dwServiceType = AFX_INET_SERVICE_HTTPS;
break;
case INTERNET_SCHEME_FILE:
dwServiceType = AFX_INET_SERVICE_FILE;
break;
case INTERNET_SCHEME_NEWS:
dwServiceType = AFX_INET_SERVICE_NNTP;
break;
case INTERNET_SCHEME_MAILTO:
dwServiceType = AFX_INET_SERVICE_MAILTO;
break;
default:
dwServiceType = AFX_INET_SERVICE_UNK;
}
}
return bRetVal;
}
BOOL __stdcall CEParseURLEx(LPCTSTR pstrURL, DWORD& dwServiceType,
CString& strServer, CString& strObject, INTERNET_PORT& nPort,
CString& strUsername, CString& strPassword, DWORD dwFlags/* = 0*/)
{
dwServiceType = AFX_INET_SERVICE_UNK;
ASSERT(pstrURL != NULL);
if (pstrURL == NULL)
return FALSE;
URL_COMPONENTS urlComponents;
memset(&urlComponents, 0, sizeof(URL_COMPONENTS));
urlComponents.dwStructSize = sizeof(URL_COMPONENTS);
urlComponents.dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH;
urlComponents.lpszHostName = strServer.GetBuffer(INTERNET_MAX_HOST_NAME_LENGTH+1);
urlComponents.dwUrlPathLength = INTERNET_MAX_PATH_LENGTH;
urlComponents.lpszUrlPath = strObject.GetBuffer(INTERNET_MAX_PATH_LENGTH+1);
urlComponents.dwUserNameLength = INTERNET_MAX_USER_NAME_LENGTH;
urlComponents.lpszUserName = strUsername.GetBuffer(INTERNET_MAX_USER_NAME_LENGTH+1);
urlComponents.dwPasswordLength = INTERNET_MAX_PASSWORD_LENGTH;
urlComponents.lpszPassword = strPassword.GetBuffer(INTERNET_MAX_PASSWORD_LENGTH+1);
BOOL bRetVal = _CEParseURLWorker(pstrURL, &urlComponents,
dwServiceType, nPort, dwFlags);
strServer.ReleaseBuffer();
strObject.ReleaseBuffer();
strUsername.ReleaseBuffer();
strPassword.ReleaseBuffer();
return bRetVal;
}
BOOL __stdcall CEParseURL(LPCTSTR pstrURL, DWORD& dwServiceType,
CString& strServer, CString& strObject, INTERNET_PORT& nPort)
{
dwServiceType = AFX_INET_SERVICE_UNK;
ASSERT(pstrURL != NULL);
if (pstrURL == NULL)
return FALSE;
URL_COMPONENTS urlComponents;
memset(&urlComponents, 0, sizeof(URL_COMPONENTS));
urlComponents.dwStructSize = sizeof(URL_COMPONENTS);
urlComponents.dwHostNameLength = INTERNET_MAX_URL_LENGTH;
urlComponents.lpszHostName = strServer.GetBuffer(INTERNET_MAX_URL_LENGTH+1);
urlComponents.dwUrlPathLength = INTERNET_MAX_URL_LENGTH;
urlComponents.lpszUrlPath = strObject.GetBuffer(INTERNET_MAX_URL_LENGTH+1);
BOOL bRetVal = _CEParseURLWorker(pstrURL, &urlComponents,
dwServiceType, nPort, ICU_BROWSER_MODE);
strServer.ReleaseBuffer();
strObject.ReleaseBuffer();
return bRetVal;
}
DWORD __stdcall CEGetInternetHandleType(HINTERNET hQuery)
{
DWORD dwServiceType;
DWORD dwTypeLen = sizeof(dwServiceType);
if (hQuery == NULL ||
!InternetQueryOption(hQuery, INTERNET_OPTION_HANDLE_TYPE,
&dwServiceType, &dwTypeLen))
return AFX_INET_SERVICE_UNK;
else
return dwServiceType;
}
BOOL __stdcall
_CEQueryCStringInternetOption(HINTERNET hHandle, DWORD dwOption, CString& refString)
{
DWORD dwLength = 0;
LPTSTR pstrBuffer;
if (hHandle == NULL)
return FALSE;
if (!InternetQueryOption(hHandle, dwOption, NULL, &dwLength) &&
GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
refString.Empty();
return FALSE;
}
pstrBuffer = refString.GetBuffer(dwLength);
BOOL bRet = InternetQueryOption(hHandle, dwOption, pstrBuffer, &dwLength);
refString.ReleaseBuffer();
return bRet;
}
#ifdef _DEBUG
void __stdcall CEInternetStatusCallbackDebug(HINTERNET hInternet,
DWORD dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength)
{
UNUSED_ALWAYS(hInternet);
TRACE1("Internet ctxt=%d: ", dwContext);
switch (dwInternetStatus)
{
case INTERNET_STATUS_RESOLVING_NAME:
TRACE1("resolving name for %s\n", lpvStatusInformation);
break;
case INTERNET_STATUS_NAME_RESOLVED:
TRACE1("resolved name for %s!\n", lpvStatusInformation);
break;
case INTERNET_STATUS_HANDLE_CREATED:
TRACE1("handle %8.8X created\n", hInternet);
break;
case INTERNET_STATUS_CONNECTING_TO_SERVER:
{
sockaddr* pSockAddr = (sockaddr*) lpvStatusInformation;
TRACE1("connecting to socket address \"%s\"\n", pSockAddr->sa_data);
}
break;
case INTERNET_STATUS_REQUEST_SENT:
TRACE0("request sent!\n");
break;
case INTERNET_STATUS_SENDING_REQUEST:
TRACE0("sending request...\n");
break;
case INTERNET_STATUS_CONNECTED_TO_SERVER:
TRACE0("connected to socket address!\n");
break;
case INTERNET_STATUS_RECEIVING_RESPONSE:
TRACE0("receiving response...\n");
break;
case INTERNET_STATUS_RESPONSE_RECEIVED:
TRACE0("response received!\n");
break;
case INTERNET_STATUS_CLOSING_CONNECTION:
TRACE1("closing connection %8.8X\n", hInternet);
break;
case INTERNET_STATUS_CONNECTION_CLOSED:
TRACE1("connection %8.8X closed!\n", hInternet);
break;
case INTERNET_STATUS_HANDLE_CLOSING:
TRACE1("handle %8.8X closed!\n", hInternet);
break;
case INTERNET_STATUS_REQUEST_COMPLETE:
if (dwStatusInformationLength == sizeof(INTERNET_ASYNC_RESULT))
{
INTERNET_ASYNC_RESULT* pResult = (INTERNET_ASYNC_RESULT*) lpvStatusInformation;
TRACE2("request complete, dwResult = %8.8X, dwError = %8.8X\n",
pResult->dwResult, pResult->dwError);
}
else
TRACE0("request complete.\n");
break;
case INTERNET_STATUS_CTL_RESPONSE_RECEIVED:
case INTERNET_STATUS_REDIRECT:
default:
TRACE1("Unknown status: %d\n", dwInternetStatus);
break;
}
return;
}
#endif // _DEBUG
void __stdcall CEInternetStatusCallback(HINTERNET hInternet, DWORD dwContext,
DWORD dwInternetStatus, LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength)
{
CCEInternetSession* pSession;
if (_CESessionMap.Lookup(hInternet, pSession))
{
pSession->OnStatusCallback(dwContext, dwInternetStatus,
lpvStatusInformation, dwStatusInformationLength);
}
// note that an entry we can't match is simply ignored as
// WININET can send notifications for handles that we can't
// see -- such as when using InternetOpenURL()
}
/////////////////////////////////////////////////////////////////////////////
/////CCEInternetSession
//
IMPLEMENT_DYNAMIC(CCEInternetSession, CObject)
CCEInternetSession::~CCEInternetSession()
{
Close();
}
CCEInternetSession::CCEInternetSession(LPCTSTR pstrAgent /* = NULL */,
DWORD dwContext /* = 1 */,
DWORD dwAccessType /* = PRE_CONFIG_INTERNET_ACCESS */,
LPCTSTR pstrProxyName /* = NULL */,
LPCTSTR pstrProxyBypass /* = NULL */,
DWORD dwFlags /* = 0 */)
{
#if defined(_WIN32_WCE)
ASSERT(dwFlags == 0);
#else // _WIN32_WCE
ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
#endif // _WIN32_WCE
m_bCallbackEnabled = FALSE;
m_pOldCallback = NULL;
m_dwContext = dwContext;
if (pstrAgent == NULL)
pstrAgent = AfxGetAppName();
m_hSession = InternetOpen(pstrAgent, dwAccessType,
pstrProxyName, pstrProxyBypass, dwFlags);
if (m_hSession == NULL)
CEThrowInternetException(m_dwContext);
else
_CESessionMap.SetAt(m_hSession, this);
#if defined(_WIN32_WCE)
if((dwContext != 0) && (m_hSession != NULL))
EnableStatusCallback(TRUE);
#endif // _WIN32_WCE
}
CCEInternetSession::operator HINTERNET() const
{
return this->m_hSession;
}
void CCEInternetSession::Close()
{
if (m_bCallbackEnabled)
EnableStatusCallback(FALSE);
if (m_hSession != NULL)
{
InternetCloseHandle(m_hSession);
_CESessionMap.RemoveKey(m_hSession);
m_hSession = NULL;
}
}
DWORD CCEInternetSession::GetContext() const
{
return m_dwContext;
}
CCEFtpConnection* CCEInternetSession::GetFtpConnection(LPCTSTR pstrServer,
LPCTSTR pstrUserName /* = NULL */, LPCTSTR pstrPassword /* = NULL */,
INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
BOOL bPassive /* = FALSE */)
{
ASSERT(AfxIsValidString(pstrServer));
CCEFtpConnection* pReturn = new CCEFtpConnection(this,
pstrServer, pstrUserName, pstrPassword, m_dwContext,
nPort, bPassive);
return pReturn;
}
CStdioFile* CCEInternetSession::OpenURL(LPCTSTR pstrURL,
DWORD dwContext /* = 0 */, DWORD dwFlags /* = INTERNET_FLAG_TRANSFER_BINARY */,
LPCTSTR pstrHeaders /* = NULL */, DWORD dwHeadersLength /* = 0 */)
{
ASSERT(AfxIsValidString(pstrURL));
ASSERT(dwHeadersLength == 0 || pstrHeaders != NULL);
ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
// must have TRANSFER_BINARY or TRANSFER_ASCII but not both
#define _AFX_TRANSFER_MASK (INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_TRANSFER_ASCII)
ASSERT((dwFlags & _AFX_TRANSFER_MASK) != 0);
ASSERT((dwFlags & _AFX_TRANSFER_MASK) != _AFX_TRANSFER_MASK);
#if defined(_WIN32_WCE)
ASSERT( (dwFlags & ~(_AFX_TRANSFER_MASK | INTERNET_FLAG_SECURE | INTERNET_FLAG_NO_AUTO_REDIRECT)) == 0 );
#endif
if (dwContext == 1)
dwContext = m_dwContext;
DWORD dwServiceType;
CString strServer;
CString strObject;
INTERNET_PORT nPort;
CStdioFile* pReturn;
BOOL bParsed = CEParseURL(pstrURL, dwServiceType, strServer, strObject, nPort);
// if it turns out to be a file...
if (bParsed && dwServiceType == AFX_INET_SERVICE_FILE)
{
int nMode = CFile::modeRead | CFile::shareCompat;
if (dwFlags & INTERNET_FLAG_TRANSFER_BINARY)
nMode |= CFile::typeBinary;
else
nMode |= CFile::typeText;
pReturn = new CStdioFile(strObject, nMode);
}
else
{
HINTERNET hOpener;
dwFlags &= ~(INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_TRANSFER_ASCII);
hOpener = InternetOpenUrl(m_hSession, pstrURL, pstrHeaders,
dwHeadersLength, dwFlags, dwContext);
if (hOpener == NULL)
CEThrowInternetException(m_dwContext);
if (!bParsed)
dwServiceType = CEGetInternetHandleType(hOpener);
switch (dwServiceType)
{
/*
#if !defined(_WIN32_WCE_NO_FTP)
case INTERNET_HANDLE_TYPE_FTP_FILE:
case AFX_INET_SERVICE_FTP:
pReturn = new CCEInternetFile(hOpener, m_hSession, strObject,
strServer, dwContext, TRUE);
_CESessionMap.SetAt(hOpener, this);
break;
#endif // _WIN32_WCE_NO_FTP
*/
case INTERNET_HANDLE_TYPE_HTTP_REQUEST:
case AFX_INET_SERVICE_HTTP:
case AFX_INET_SERVICE_HTTPS:
pReturn = NULL;
break;
default:
TRACE1("Error: Unidentified service type: %8.8X\n", dwServiceType);
pReturn = NULL;
}
}
return pReturn;
}
BOOL CCEInternetSession::SetOption(DWORD dwOption, LPVOID lpBuffer,
DWORD dwBufferLength, DWORD dwFlags /* = 0 */)
{
ASSERT(AfxIsValidAddress(lpBuffer, dwBufferLength, FALSE));
ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
dwOption <= INTERNET_LAST_OPTION);
ASSERT(dwBufferLength != 0);
ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
// bogus flag?
ASSERT(dwFlags == 0 || WCE_IF(FALSE, ((dwFlags & ISO_VALID_FLAGS) == dwFlags)));
return WCE_FCTN(InternetSetOptionEx)(m_hSession, dwOption,
lpBuffer, dwBufferLength, dwFlags);
}
BOOL CCEInternetSession::QueryOption(DWORD dwOption, LPVOID lpBuffer,
LPDWORD lpdwBufferLength) const
{
ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
dwOption <= INTERNET_LAST_OPTION);
ASSERT_POINTER(lpdwBufferLength, DWORD);
ASSERT(AfxIsValidAddress(lpBuffer, *lpdwBufferLength));
ASSERT(*lpdwBufferLength != 0);
return InternetQueryOption(m_hSession, dwOption,
lpBuffer, lpdwBufferLength);
}
BOOL CCEInternetSession::QueryOption(DWORD dwOption, DWORD& dwValue) const
{
DWORD dwLen = sizeof(DWORD);
return InternetQueryOption(m_hSession, dwOption,
&dwValue, &dwLen);
}
BOOL CCEInternetSession::QueryOption(DWORD dwOption, CString& refString) const
{
ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
dwOption <= INTERNET_LAST_OPTION);
return _CEQueryCStringInternetOption(m_hSession, dwOption, refString);
}
void CCEInternetSession::OnStatusCallback(DWORD dwContext,
DWORD dwInternetStatus, LPVOID lpvStatusInformation,
DWORD dwStatusInformationLength)
{
ASSERT(m_bCallbackEnabled != NULL);
if (m_pOldCallback != NULL)
{
(*m_pOldCallback)(m_hSession, dwContext, dwInternetStatus,
lpvStatusInformation, dwStatusInformationLength);
}
}
BOOL CCEInternetSession::EnableStatusCallback(BOOL bEnable /* = TRUE */)
{
ASSERT(!bEnable || m_hSession != NULL);
if (m_hSession == NULL)
return FALSE;
BOOL bResult = TRUE;
if (bEnable)
{
#if !defined(_WIN32_WCE)
ASSERT(!m_bCallbackEnabled);
#endif // _WIN32_WCE
if (!m_bCallbackEnabled)
{
INTERNET_STATUS_CALLBACK pRet =
InternetSetStatusCallback(m_hSession, CEInternetStatusCallback);
if (pRet != INTERNET_INVALID_STATUS_CALLBACK)
{
m_pOldCallback = pRet;
m_bCallbackEnabled = TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -