[prev in list] [next in list] [prev in thread] [next in thread]
List: helix-filesystem-cvs
Subject: [Filesystem-cvs] filesystem/httpshim/platform/win WinHttpDriver.cpp, NONE,
From: qluo () helixcommunity ! org
Date: 2013-04-03 2:23:49
[Download RAW message or body]
Update of /cvsroot/filesystem/filesystem/httpshim/platform/win
In directory cvs01.internal.helixcommunity.org:/tmp/cvs-serv13857/platform/win
Added Files:
WinHttpDriver.cpp WinHttpDriver.h WinHttpRequest.cpp
WinHttpRequest.h WinHttpResponse.cpp WinHttpResponse.h
WinInetUtility.cpp WinInetUtility.h
Log Message:
check-in initial implementation on behalf of Jason Liao and Richard Zhao
--- NEW FILE: WinInetUtility.cpp ---
#include "WinInetUtility.h"
#include <assert.h>
#pragma comment (lib, "wininet.lib")
HINTERNET CWinInetUtility::OpenInternet( LPCTSTR szUserAgent,
DWORD dwAccessType /*= INTERNET_OPEN_TYPE_PRECONFIG*/,
LPCTSTR szProxyName /*= NULL*/,
LPCTSTR szProxyBypass /*= NULL*/)
{
HINTERNET hInternet = InternetOpen(szUserAgent, dwAccessType, szProxyName, \
szProxyBypass, INTERNET_FLAG_ASYNC); assert(hInternet != NULL && hInternet != \
INVALID_HANDLE_VALUE); return hInternet;
}
DWORD CWinInetUtility::GetLastErrorCode()
{
return GetLastError();
}
void CWinInetUtility::CloseInternet(HINTERNET& hInternet)
{
_CloseInternetHandler(hInternet);
}
HINTERNET CWinInetUtility::OpenConnection( HINTERNET hInternet,
LPCTSTR szServerAddr,
DWORD_PTR dwContext,
INTERNET_PORT nPort /*= INTERNET_DEFAULT_HTTP_PORT*/,
LPCTSTR szUsrName /*= NULL*/,
LPCTSTR szUsrPwd /*= NULL*/)
{
assert(hInternet != NULL && hInternet != INVALID_HANDLE_VALUE);
assert(szServerAddr && *szServerAddr);
HINTERNET hConnection = InternetConnect(hInternet, szServerAddr, nPort, \
szUsrName, szUsrPwd, INTERNET_SERVICE_HTTP, 0, dwContext); assert(hConnection != \
NULL && hConnection != INVALID_HANDLE_VALUE); return hConnection;
}
HINTERNET CWinInetUtility::OpenURL( HINTERNET hInternet, LPCTSTR szURL, DWORD_PTR \
dwContext, DWORD dwFlags ) {
HINTERNET hHttpFile = InternetOpenUrl(hInternet, szURL, NULL, 0, dwFlags, \
dwContext); return hHttpFile;
}
void CWinInetUtility::CloseConnection(HINTERNET& hConnection)
{
_CloseInternetHandler(hConnection);
}
void CWinInetUtility::_CloseInternetHandler( HINTERNET& hHandler )
{
if(hHandler != NULL && hHandler != INVALID_HANDLE_VALUE)
{
::InternetCloseHandle(hHandler);
}
hHandler = NULL;
}
HINTERNET CWinInetUtility::OpenRequest( HINTERNET hConnection,
LPCTSTR szMethod,
LPCTSTR szObjectName,
DWORD_PTR dwContext,
DWORD dwFlags /*= INTERNET_FLAG_HYPERLINK | INTERNET_FLAG_KEEP_CONNECTION | \
INTERNET_FLAG_NO_UI | INTERNET_FLAG_RESYNCHRONIZE | INTERNET_FLAG_NO_CACHE_WRITE | \
INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD*/, LPCTSTR szReferer /*= \
NULL*/) {
static LPCTSTR szAcceptedType[] = {_T("*/*"), NULL};
HINTERNET hRequest = HttpOpenRequest(hConnection, szMethod, szObjectName, NULL, \
szReferer, szAcceptedType, dwFlags, dwContext); return hRequest;
}
void CWinInetUtility::CloseRequest( HINTERNET& hRequest )
{
_CloseInternetHandler(hRequest);
}
BOOL CWinInetUtility::AddHeader( HINTERNET hRequest, LPCTSTR szName, LPCTSTR szValue \
) {
CString strHeader = szName;
strHeader += _T(": ");
strHeader += szValue;
strHeader += _T("\r\n");
return HttpAddRequestHeaders(hRequest, strHeader, strHeader.GetLength(), \
HTTP_ADDREQ_FLAG_ADD); }
BOOL CWinInetUtility::EndRequest(HINTERNET hRequest)
{
return HttpEndRequest(hRequest, NULL, 0, 0);
}
BOOL CWinInetUtility::SendRequest( HINTERNET hRequest, LPVOID pPostedBuffer /*= \
NULL*/, DWORD dwBufferSize /*= 0*/ ) {
return HttpSendRequest(hRequest, NULL, 0, pPostedBuffer, dwBufferSize);
}
BOOL CWinInetUtility::SendRequestEx( HINTERNET hRequest, DWORD dwPostedSize, \
DWORD_PTR dwContext /*= NULL*/ ) {
INTERNET_BUFFERS bufferIn;
ZeroMemory(&bufferIn, sizeof(bufferIn));
bufferIn.dwStructSize = sizeof( INTERNET_BUFFERS );
bufferIn.dwBufferTotal = dwPostedSize;
return HttpSendRequestEx(hRequest, &bufferIn, NULL, 0, dwContext);
}
BOOL CWinInetUtility::WriteFile( HINTERNET hRequest, LPVOID pBuffer, DWORD \
dwBufferSize ) {
BOOL bRet = FALSE;
DWORD dwTotalWritten = 0;
DWORD dwWritten = 0;
while ( dwTotalWritten < dwBufferSize )
{
if (!(bRet = InternetWriteFile(hRequest, (BYTE *)pBuffer + dwTotalWritten, \
dwBufferSize - dwTotalWritten, &dwWritten))) break;
dwTotalWritten += dwWritten;
}
return bRet;
}
BOOL CWinInetUtility::GetStatusText( HINTERNET hRequest, CString& strStatusText )
{
BOOL bRet = TRUE;
DWORD dwBufSize = 0 ;
LPVOID pBuffer = NULL;
// Get required buffer size
if (!QueryInfo(hRequest, HTTP_QUERY_STATUS_TEXT, pBuffer, dwBufSize, NULL))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
bRet = FALSE;
}
}
if(bRet)
{
assert(dwBufSize > 0);
pBuffer = (LPVOID)malloc(dwBufSize + sizeof(TCHAR));
ZeroMemory(pBuffer, dwBufSize + sizeof(TCHAR));
// Get the status text
bRet = QueryInfo(hRequest, HTTP_QUERY_STATUS_TEXT, pBuffer, dwBufSize, NULL);
strStatusText = (TCHAR *)pBuffer;
free(pBuffer);
}
return bRet;
}
BOOL CWinInetUtility::GetHeader( HINTERNET hRequest, CString& strHeader, LPCTSTR \
szName, DWORD* pdwIndex /*= NULL*/ ) {
BOOL bRet = TRUE;
DWORD dwOriginalIndex = 0;
if(pdwIndex)
{
dwOriginalIndex = *pdwIndex;
}
DWORD dwBufSize = (_tcslen(szName) + 1) * sizeof(TCHAR);
LPVOID pBuffer = (LPVOID)malloc(dwBufSize);
ZeroMemory(pBuffer, dwBufSize);
memcpy(pBuffer, szName, _tcslen(szName) * sizeof(TCHAR));
if(!(bRet = QueryInfo(hRequest, HTTP_QUERY_CUSTOM, pBuffer, dwBufSize, \
pdwIndex))) {
if(GetLastError () == ERROR_INSUFFICIENT_BUFFER)
{
free(pBuffer);
pBuffer = (LPVOID)malloc(dwBufSize + sizeof(TCHAR));
ZeroMemory(pBuffer, dwBufSize + sizeof(TCHAR));
memcpy(pBuffer, szName, _tcslen(szName) * sizeof(TCHAR));
if(pdwIndex)
{
*pdwIndex = dwOriginalIndex;
}
bRet = QueryInfo(hRequest, HTTP_QUERY_CUSTOM, pBuffer, dwBufSize, \
pdwIndex); }
}
if(bRet)
{
strHeader = (TCHAR *)pBuffer;
}
free(pBuffer);
return bRet;
}
BOOL CWinInetUtility::SetInternetOption( HINTERNET hInternet, DWORD dwOption, LPVOID \
lpBuffer, DWORD dwBufferLength ) {
return InternetSetOption(hInternet, dwOption, lpBuffer, dwBufferLength);
}
BOOL CWinInetUtility::ReadFile( HINTERNET hRequest, LPVOID pBuffer, DWORD \
dwBytesToRead, LPDWORD pdwBytesRead) {
return InternetReadFile(hRequest, pBuffer, dwBytesToRead, pdwBytesRead);
}
BOOL CWinInetUtility::ReadFileEx( HINTERNET hRequest, LPVOID pBuffer, DWORD \
dwBytesToRead, LPDWORD pdwRead, DWORD_PTR dwContext /*= NULL*/ ) {
INTERNET_BUFFERS ib;
ZeroMemory(&ib, sizeof(ib));
ib.lpvBuffer = pBuffer;
ib.dwStructSize = sizeof(INTERNET_BUFFERS);
ib.dwBufferLength = dwBytesToRead;
BOOL bRet = InternetReadFileEx(hRequest, &ib, IRF_ASYNC, dwContext);
if(pdwRead)
{
*pdwRead = ib.dwBufferLength;
}
return bRet;
}
BOOL CWinInetUtility::GetContentLength( HINTERNET hRequest, DWORD& dwContentLength )
{
DWORD dwBufferSize = sizeof(DWORD);
return QueryInfo(hRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, \
(LPVOID)(&dwContentLength), dwBufferSize, NULL); }
void CWinInetUtility::SetStatusCallback( HINTERNET hInternet, \
INTERNET_STATUS_CALLBACK lpCallback /*= NULL*/) {
InternetSetStatusCallback(hInternet, lpCallback);
}
BOOL CWinInetUtility::GetStatus( HINTERNET hRequest, DWORD& dwStatus )
{
DWORD dwBufferSize = sizeof(DWORD);
return QueryInfo(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, \
(LPVOID)(&dwStatus), dwBufferSize, NULL); }
BOOL CWinInetUtility::QueryInfo( HINTERNET hRequest, DWORD dwQueryFlag, LPVOID \
pBuffer, DWORD& dwBufferSize, DWORD* pdwIndex /*= NULL*/ ) {
return HttpQueryInfo(hRequest, dwQueryFlag, pBuffer, &dwBufferSize, pdwIndex);
}
BOOL CWinInetUtility::WriteFileEx( HINTERNET hRequest, LPVOID pBuffer, DWORD \
dwBufferSize, LPDWORD pdwWritten ) {
BOOL bRet = InternetWriteFile(hRequest, pBuffer, dwBufferSize, pdwWritten);
return bRet;
}
#define DEFAULT_HEADERS_SIZE 4096
BOOL CWinInetUtility::GetHeaders( HINTERNET hRequest, CString& strHeaders )
{
BOOL bRet = TRUE;
DWORD dwBufSize = DEFAULT_HEADERS_SIZE;
LPVOID pBuffer = (LPVOID)malloc(dwBufSize);
ZeroMemory(pBuffer, dwBufSize);
if(!(bRet = QueryInfo(hRequest, HTTP_QUERY_RAW_HEADERS, pBuffer, dwBufSize)))
{
if(GetLastError () == ERROR_INSUFFICIENT_BUFFER)
{
free(pBuffer);
pBuffer = (LPVOID)malloc(dwBufSize);
ZeroMemory(pBuffer, dwBufSize);
bRet = QueryInfo(hRequest, HTTP_QUERY_RAW_HEADERS, pBuffer, dwBufSize);
}
}
if(bRet)
{
strHeaders = (TCHAR *)pBuffer;
}
free(pBuffer);
return bRet;
}
--- NEW FILE: WinHttpResponse.cpp ---
#include "WinHttpResponse.h"
#include "WinHttpRequest.h"
#include "WinInetUtility.h"
#define DEFAULT_CHUNK_SIZE 4096
CWinHttpResponse::CWinHttpResponse(CWinHttpRequest* pRequest, unsigned long \
ulSizePerTimeToReceive) :m_request(pRequest),
m_dwStatusCode(0),
m_dwSizeReceived(0),
m_dwSizeReceivedTotal(0),
m_dwSizeToReceivePerTime(ulSizePerTimeToReceive),
m_pContent(NULL),
m_dwContentLength(0),
m_strHeaders(_T("")),
m_strStatusText(_T("")),
m_bIsChunked(FALSE)
{
m_mapHeaders.clear();
}
CWinHttpResponse::~CWinHttpResponse(void)
{
free(m_pContent);
}
BOOL CWinHttpResponse::GetHeaders( CString& strHeaders ) const
{
strHeaders = m_strHeaders;
return TRUE;
}
BOOL CWinHttpResponse::GetContentLength( unsigned long& ulLength ) const
{
ulLength = m_dwContentLength;
return TRUE;
}
BOOL CWinHttpResponse::GetContent( BYTE *pBuffer, unsigned long ulBufferSize ) const
{
memcpy(pBuffer, m_pContent, ulBufferSize);
return TRUE;
}
BOOL CWinHttpResponse::GetStatusCode( unsigned long& ulStatus ) const
{
ulStatus = m_dwStatusCode;
return TRUE;
}
BOOL CWinHttpResponse::GetStatusText( CString& strStatus ) const
{
strStatus = m_strStatusText;
return TRUE;
}
BOOL CWinHttpResponse::GetHeader( const CString& strName, CString& strHeader) const
{
std::map<CString, CString>::const_iterator it = m_mapHeaders.find(strName);
if(it != m_mapHeaders.end())
{
strHeader = it->second;
return TRUE;
}
return FALSE;
}
int CWinHttpResponse::GetHeadersCount() const
{
return m_mapHeaders.size();
}
unsigned long CWinHttpResponse::ReceiveData()
{
CWinInetUtility::GetStatus(m_request->GetRequestHandle(), m_dwStatusCode);
CWinInetUtility::GetStatusText(m_request->GetRequestHandle(), m_strStatusText);
CWinInetUtility::GetHeaders(m_request->GetRequestHandle(), m_strHeaders);
// headers -> header-value map
// try to get content length
if(CWinInetUtility::GetContentLength(m_request->GetRequestHandle(), \
m_dwContentLength)) {
if(m_dwContentLength > 0)
{
m_pContent = (byte*)malloc(m_dwContentLength);
ZeroMemory(m_pContent, m_dwContentLength);
}
}
else
{
CString strHeader;
if(CWinInetUtility::GetHeader(m_request->GetRequestHandle(), strHeader, \
_T("Transfer-Encoding")) && strHeader.CompareNoCase(_T("chunked")) == 0) {
m_bIsChunked = TRUE;
m_pContent = (byte*)malloc(DEFAULT_CHUNK_SIZE);
ZeroMemory(m_pContent, DEFAULT_CHUNK_SIZE);
m_dwContentLength = DEFAULT_CHUNK_SIZE;
}
}
DWORD dwRet = NO_ERROR;
if(!m_bIsChunked && m_dwContentLength > 0)
{
while(m_dwSizeReceivedTotal < m_dwContentLength &&
CWinInetUtility::ReadFile(m_request->GetRequestHandle(), m_pContent + \
m_dwSizeReceivedTotal, m_dwSizeToReceivePerTime, &m_dwSizeReceived) && \
m_dwSizeReceived > 0) {
m_dwSizeReceivedTotal += m_dwSizeReceived;
}
}
else if(m_bIsChunked)
{
byte* pBuffer = (byte*)malloc(m_dwSizeToReceivePerTime);
while(CWinInetUtility::ReadFile(m_request->GetRequestHandle(), pBuffer, \
m_dwSizeToReceivePerTime, &m_dwSizeReceived) && m_dwSizeReceived > 0) {
if(m_dwSizeReceivedTotal + m_dwSizeReceived > m_dwContentLength)
{
m_dwContentLength *= 2;
m_pContent = (byte *)realloc(m_pContent, m_dwContentLength);
ZeroMemory(m_pContent + m_dwSizeReceivedTotal, m_dwContentLength - \
m_dwSizeReceivedTotal); }
memcpy(m_pContent + m_dwSizeReceivedTotal, pBuffer, m_dwSizeReceived); \
m_dwSizeReceivedTotal += m_dwSizeReceived;
}
m_dwContentLength = m_dwSizeReceivedTotal;
}
return dwRet;
}
--- NEW FILE: WinHttpRequest.h ---
#pragma once
#include "HttpDriver.h"
#include "WinHttpResponse.h"
#include <wininet.h>
#include <vector>
#include <list>
#include <map>
class CWinHttpRequest : public IHttpRequest
{
private:
enum Request_Status
{
ReqStatus_SendReq = 0,
ReqStatus_SendReqWithContent,
ReqStatus_PostSendData,
ReqStatus_PostComplete,
ReqStatus_ResponseRecvData,
ReqStatus_Complete
};
public:
CWinHttpRequest(HINTERNET hInternet, LPVOID pContext);
~CWinHttpRequest(void);
// IHttpRequest methods
virtual unsigned long Initialize( HTTPVerb verb,
const CString& strHost,
const CString& strObjectName,
int nPort,
const CString& strUserName,
const CString& strPassword,
BOOL bSecure = FALSE );
virtual unsigned long Initialize(const CString& strURL);
virtual void AppendByteRange( unsigned long ulStart, unsigned long ulEnd );
virtual void AppendLastBytes( unsigned long ulBytesCount );
virtual void AppendBytesFrom( unsigned long ulStartFrom );
virtual void AppendCookie( const CString& strCookieName, const CString& \
strCookieValue ); virtual void AppendCookies( const CString& strCookies );
virtual void AppendCustomHeader( const CString& strHeaderName, const CString& \
strHeaderValue ); virtual void AppendCustomHeaders( const CString& strHeaders );
virtual void SetTransferRate(unsigned long ulSizePerTimeToPost, unsigned long \
ulSizePerTimeToReceive); virtual void SetContent( const byte* pBuffer, unsigned long \
ulBufferSize ); virtual void SetRequestCallback( HttpRequestCallback fnCallback );
virtual IHttpResponse* GetResponse();
virtual void SetPostMultipart( BOOL bMultipart );
virtual void SetBoundary( const CString& strBoundary );
virtual void Execute();
virtual void UnInitialize();
virtual BOOL IsInitialized() const;
virtual LPVOID GetContext() { return m_pContext; }
public:
void OnStatusNofified(__in DWORD dwInternetStatus,
__in_bcount(dwStatusInformationLength) LPVOID lpvStatusInformation,
__in DWORD dwStatusInformationLength);
HINTERNET GetRequestHandle() const { return m_hRequest; }
private:
struct _InternetStatus
{
DWORD dwInternetStatus;
LPVOID lpvStatusInformation;
DWORD dwStatusInformationLength;
_InternetStatus()
{
dwInternetStatus = 0;
lpvStatusInformation = NULL;
dwStatusInformationLength = 0;
}
};
// working threads
static unsigned __stdcall _ProcessNotificationThread( void* pArguments );
static unsigned __stdcall _TriggerCallbackThread( void* pArguments );
void _ProcessNotification(DWORD dwInternetStatus, LPVOID lpvStatusInformation, \
DWORD dwStatusInformationLength); void _ProcessRequest(DWORD dwCode);
BOOL _PopFrontCallbackStatus(HTTPRequestStatus& status);
BOOL _PopFrontInternetStatus(_InternetStatus& status);
private:
HINTERNET m_hInternet;
LPVOID m_pContext;
BOOL m_bInitialized;
Request_Status m_currentStatus;
// connection information
HTTPVerb m_verb;
HINTERNET m_hConnection;
// write & post
DWORD m_dwSizePosted;
DWORD m_dwSizeToPostPerTime;
DWORD m_dwSizePostedTotal;
DWORD m_dwSizeToReceivePerTime;
BOOL m_bMultiPart;
// content
byte* m_pContentToPost;
DWORD m_dwContentLengthToPost;
// http request file handle
HINTERNET m_hRequest;
CString m_strObject;
CString m_strURL;
// byte-range
std::vector<CString> m_vecByteRanges;
// cookies
CString m_strCookies;
std::map<CString, CString> m_mapCookies;
// headers
CString m_strHeaders;
std::map<CString, CString> m_mapHeaders;
// boundary
CString m_strBoundary;
// response
CWinHttpResponse *m_response;
// callback
HttpRequestCallback m_hResonseCallback;
// threads
unsigned m_uThreadProcessNotify;
unsigned m_uThreadTriggerCallback;
HANDLE m_hThreadProcessNotify;
HANDLE m_hThreadTriggerCallback;
std::list<_InternetStatus> m_listInternetStatus;
std::list<HTTPRequestStatus> m_listCallbackStatus;
HANDLE m_hEventExit;
HANDLE m_hEventInternetStatusUpdated;
HANDLE m_hEventCallbackUpdated;
// lockers
CRITICAL_SECTION m_csInternetStatus;
CRITICAL_SECTION m_csCallbackStatus;
CRITICAL_SECTION m_csInitialize;
};
--- NEW FILE: WinHttpDriver.cpp ---
#include "WinHttpDriver.h"
#include "WinInetUtility.h"
#include "WinHttpRequest.h"
BOOL s_bIsUnInitialized = FALSE;
CWinHttpDriver::CWinHttpDriver(void)
:m_hInternet(NULL)
{
}
CWinHttpDriver::~CWinHttpDriver(void)
{
}
unsigned long CWinHttpDriver::Initialize( const CString& strName )
{
return Initialize(strName, INTERNET_OPEN_TYPE_PRECONFIG, _T(""), _T(""));
}
unsigned long CWinHttpDriver::Initialize( const CString& strName, unsigned long \
ulAccessType, const CString& strProxyName, const CString& strProxyByPass ) {
DWORD dwRet = NO_ERROR;
const TCHAR* szProxyName = NULL;
if(!strProxyName.IsEmpty())
szProxyName = strProxyName;
const TCHAR* szProxyByPass = NULL;
if(!strProxyName.IsEmpty())
szProxyName = strProxyName;
m_hInternet = CWinInetUtility::OpenInternet(strName, ulAccessType, szProxyName, \
szProxyByPass);
if(m_hInternet == NULL || m_hInternet == INVALID_HANDLE_VALUE)
dwRet = GetLastError();
else
{
s_bIsUnInitialized = FALSE;
CWinInetUtility::SetStatusCallback(m_hInternet, StatusNotifyCallback);
}
return dwRet;
}
IHttpRequest* CWinHttpDriver::CreateRequest(LPVOID pContext)
{
IHttpRequest* pRequest = new CWinHttpRequest(m_hInternet, pContext);
return pRequest;
}
void CWinHttpDriver::ReleaseRequest( IHttpRequest* pRequest)
{
pRequest->UnInitialize();
delete pRequest;
}
void CWinHttpDriver::UnInitialize()
{
OutputDebugString(_T("void CWinHttpDriver::UnInitialize\n"));
if(m_hInternet != NULL && m_hInternet != INVALID_HANDLE_VALUE)
{
s_bIsUnInitialized = TRUE;
CWinInetUtility::SetStatusCallback(m_hInternet, NULL);
CWinInetUtility::CloseInternet(m_hInternet);
}
m_hInternet = NULL;
}
void WINAPI CWinHttpDriver::StatusNotifyCallback( __in HINTERNET hInternet,
__in DWORD_PTR dwContext,
__in DWORD dwInternetStatus,
__in_bcount(dwStatusInformationLength) LPVOID lpvStatusInformation,
__in DWORD dwStatusInformationLength )
{
if(s_bIsUnInitialized)
{
return;
}
CWinHttpRequest* pRequest = (CWinHttpRequest*)dwContext;
pRequest->OnStatusNofified(dwInternetStatus, lpvStatusInformation, \
dwStatusInformationLength); }
--- NEW FILE: WinHttpRequest.cpp ---
#include "WinHttpRequest.h"
#include "WinInetUtility.h"
#include <assert.h>
using namespace std;
class CWinLocker
{
public:
CWinLocker(LPCRITICAL_SECTION cs)
:m_cs(cs)
{
EnterCriticalSection(cs);
}
~CWinLocker()
{
LeaveCriticalSection(m_cs);
}
private:
LPCRITICAL_SECTION m_cs;
};
CWinHttpRequest::CWinHttpRequest(HINTERNET hInternet, LPVOID pContext)
:m_bInitialized(FALSE),
m_hInternet(hInternet),
m_hConnection(NULL),
m_verb(Verb_Unknown),
m_hRequest(NULL),
m_strObject(_T("")),
m_strCookies(_T("")),
m_pContentToPost(NULL),
m_dwContentLengthToPost(0),
m_dwSizeToPostPerTime(DEFAULT_TRANSFER_SIZE),
m_dwSizeToReceivePerTime(DEFAULT_TRANSFER_SIZE),
m_dwSizePostedTotal(0),
m_response(NULL),
m_pContext(pContext)
{
m_vecByteRanges.clear();
m_mapCookies.clear();
m_mapHeaders.clear();
m_listInternetStatus.clear();
InitializeCriticalSection(&m_csCallbackStatus);
InitializeCriticalSection(&m_csInternetStatus);
InitializeCriticalSection(&m_csInitialize);
m_hEventExit = CreateEvent(NULL, TRUE, FALSE, NULL);
m_hEventInternetStatusUpdated = CreateEvent(NULL, FALSE, FALSE, NULL);
m_hEventCallbackUpdated = CreateEvent(NULL, FALSE, FALSE, NULL);
m_hThreadProcessNotify = (HANDLE)_beginthreadex(NULL, 0, \
&_ProcessNotificationThread, this, 0, &m_uThreadProcessNotify); \
m_hThreadTriggerCallback = (HANDLE)_beginthreadex(NULL, 0, &_TriggerCallbackThread, \
this, 0, &m_uThreadTriggerCallback); }
CWinHttpRequest::~CWinHttpRequest(void)
{
UnInitialize();
// stop threads
SetEvent(m_hEventExit);
WaitForSingleObject(m_hThreadProcessNotify, INFINITE);
WaitForSingleObject(m_hThreadTriggerCallback, INFINITE);
CloseHandle(m_hThreadProcessNotify);
CloseHandle(m_hThreadTriggerCallback);
// release objects
CloseHandle(m_hEventExit);
CloseHandle(m_hEventInternetStatusUpdated);
CloseHandle(m_hEventCallbackUpdated);
DeleteCriticalSection(&m_csCallbackStatus);
DeleteCriticalSection(&m_csInternetStatus);
DeleteCriticalSection(&m_csInitialize);
}
#pragma region "initialize and uninitialize"
unsigned long CWinHttpRequest::Initialize( HTTPVerb verb, const CString& strHost, \
const CString& strObjectName, int nPort, const CString& strUserName, const CString& \
strPassword, BOOL bSecure /*= FALSE */ ) {
CWinLocker locker(&m_csInitialize);
DWORD dwRet = NO_ERROR;
if(!m_bInitialized)
{
m_hConnection = CWinInetUtility::OpenConnection(m_hInternet, strHost, \
(DWORD_PTR)this, nPort, strUserName, strPassword); if(m_hConnection == NULL || \
m_hConnection == INVALID_HANDLE_VALUE) {
dwRet = GetLastError();
}
else
{
m_bInitialized = TRUE;
m_verb = verb;
m_strObject = strObjectName;
}
}
return dwRet;
}
unsigned long CWinHttpRequest::Initialize( const CString& strURL )
{
CWinLocker locker(&m_csInitialize);
DWORD dwRet = NO_ERROR;
if(!m_bInitialized)
{
m_strURL = strURL;
m_bInitialized = TRUE;
}
return dwRet;
}
void CWinHttpRequest::UnInitialize()
{
CWinLocker locker(&m_csInitialize);
if(m_bInitialized)
{
CWinInetUtility::CloseRequest(m_hRequest);
CWinInetUtility::CloseConnection(m_hConnection);
m_verb = Verb_Unknown;
m_strObject.Empty();
m_vecByteRanges.clear();
m_mapCookies.clear();
m_mapHeaders.clear();
m_strCookies.Empty();
m_strHeaders.Empty();
m_strBoundary.Empty();
m_bMultiPart = FALSE;
free(m_pContentToPost);
m_pContentToPost = NULL;
m_dwContentLengthToPost = 0;
m_dwSizePostedTotal = 0;
m_dwSizeToPostPerTime = DEFAULT_TRANSFER_SIZE;
m_dwSizeToReceivePerTime = DEFAULT_TRANSFER_SIZE;
delete m_response;
m_response = NULL;
m_hResonseCallback = NULL;
ResetEvent(m_hEventInternetStatusUpdated);
ResetEvent(m_hEventCallbackUpdated);
_InternetStatus status;
while(_PopFrontInternetStatus(status))
{
free(status.lpvStatusInformation);
}
{
CWinLocker locker(&m_csCallbackStatus);
m_listCallbackStatus.clear();
}
m_bInitialized = FALSE;
}
}
BOOL CWinHttpRequest::IsInitialized() const
{
CWinLocker locker((LPCRITICAL_SECTION)&m_csInitialize);
return m_bInitialized;
}
#pragma endregion
#pragma region "byte-range settings"
void CWinHttpRequest::AppendByteRange( unsigned long ulStart, unsigned long ulEnd )
{
if(ulStart <= ulEnd && ulStart >= 0)
{
CString strRangeItem;
strRangeItem.Format(_T("%d-%d"), ulStart, ulEnd);
m_vecByteRanges.push_back(strRangeItem);
}
}
void CWinHttpRequest::AppendLastBytes( unsigned long ulBytesCount )
{
if(ulBytesCount >= 0)
{
CString strRangeItem;
strRangeItem.Format(_T("-%d"), ulBytesCount);
m_vecByteRanges.push_back(strRangeItem);
}
}
void CWinHttpRequest::AppendBytesFrom( unsigned long ulStartFrom )
{
if(ulStartFrom >= 0)
{
CString strRangeItem;
strRangeItem.Format(_T("%d-%d"), ulStartFrom);
m_vecByteRanges.push_back(strRangeItem);
}
}
#pragma endregion
#pragma region "cookie settings"
void CWinHttpRequest::AppendCookie( const CString& strCookieName, const CString& \
strCookieValue ) {
if(!strCookieName.IsEmpty())
{
m_mapCookies[strCookieName] = strCookieValue;
}
}
void CWinHttpRequest::AppendCookies( const CString& strCookies )
{
m_strCookies = strCookies;
}
#pragma endregion
#pragma region "header settings"
// Append one specific header
void CWinHttpRequest::AppendCustomHeader( const CString& strHeaderName, const \
CString& strHeaderValue ) {
if(!strHeaderName.IsEmpty())
{
m_mapHeaders[strHeaderName] = strHeaderValue;
}
}
// append headers
void CWinHttpRequest::AppendCustomHeaders( const CString& strHeaders )
{
m_strHeaders = strHeaders;
}
#pragma endregion
void CWinHttpRequest::SetTransferRate(unsigned long ulSizePerTimeToPost, unsigned \
long ulSizePerTimeToReceive) {
m_dwSizeToPostPerTime = ulSizePerTimeToPost;
m_dwSizeToReceivePerTime = ulSizePerTimeToReceive;
}
// set content to post and post size one time
void CWinHttpRequest::SetContent( const byte* pBuffer, unsigned long ulBufferSize )
{
m_pContentToPost = (byte*)malloc(ulBufferSize);
memcpy(m_pContentToPost, pBuffer, ulBufferSize);
m_dwContentLengthToPost = ulBufferSize;
}
void CWinHttpRequest::SetPostMultipart( BOOL bMultiPart )
{
m_bMultiPart = bMultiPart;
}
void CWinHttpRequest::SetBoundary( const CString& strBoundary )
{
m_strBoundary = strBoundary;
}
void CWinHttpRequest::SetRequestCallback( HttpRequestCallback fnCallback )
{
m_hResonseCallback = fnCallback;
}
IHttpResponse* CWinHttpRequest::GetResponse()
{
return m_response;
}
// start to execute the request
void CWinHttpRequest::Execute()
{
static map<HTTPVerb, CString> s_mapVerbNames;
if(s_mapVerbNames.empty())
{
s_mapVerbNames[Verb_Unknown] = _T("Unknow");
s_mapVerbNames[Verb_Get] = _T("GET");
s_mapVerbNames[Verb_Post] = _T("POST");
s_mapVerbNames[Verb_Put] = _T("PUT");
s_mapVerbNames[Verb_Delete] = _T("DELETE");
s_mapVerbNames[Verb_More] = _T("More");
}
if(m_strURL.IsEmpty())
{
m_hRequest = CWinInetUtility::OpenRequest(m_hConnection, \
s_mapVerbNames[m_verb], m_strObject, (DWORD_PTR)this); }
else
{
m_currentStatus = ReqStatus_ResponseRecvData;
CWinInetUtility::OpenURL(m_hInternet, m_strURL, (DWORD_PTR)this);
}
// set headers
if(m_strURL.IsEmpty())
{
if(m_pContentToPost != NULL && m_dwContentLengthToPost > 0)
{
m_currentStatus = ReqStatus_PostSendData;
CWinInetUtility::SendRequestEx(m_hRequest, m_dwContentLengthToPost, \
(DWORD_PTR)this); }
else
{
m_currentStatus = ReqStatus_ResponseRecvData;
CWinInetUtility::SendRequest(m_hRequest);
}
}
}
#pragma region "Internet status notification"
void CWinHttpRequest::OnStatusNofified( __in DWORD dwInternetStatus, \
__in_bcount(dwStatusInformationLength) LPVOID lpvStatusInformation, __in DWORD \
dwStatusInformationLength ) {
_InternetStatus status;
status.dwInternetStatus = dwInternetStatus;
status.dwStatusInformationLength = dwStatusInformationLength;
if(dwStatusInformationLength > 0)
{
status.lpvStatusInformation = (LPVOID)malloc(dwStatusInformationLength);
memcpy(status.lpvStatusInformation, lpvStatusInformation, \
dwStatusInformationLength); }
// locker
{
CWinLocker locker(&m_csInternetStatus);
m_listInternetStatus.push_back(status);
}
SetEvent(m_hEventInternetStatusUpdated);
}
// thread to process callback values, so this will not block the raw Internet status \
callback unsigned __stdcall CWinHttpRequest::_ProcessNotificationThread( void* \
pArguments ) {
CWinHttpRequest *pRequest = (CWinHttpRequest *)pArguments;
HANDLE handles[2];
handles[0] = pRequest->m_hEventInternetStatusUpdated;
handles[1] = pRequest->m_hEventExit;
list<_InternetStatus> *pListInternetStatus = &pRequest->m_listInternetStatus;
_InternetStatus status;
while(WaitForMultipleObjects(2, handles, FALSE, INFINITE) == WAIT_OBJECT_0)
{
while(pRequest->_PopFrontInternetStatus(status))
{
pRequest->_ProcessNotification(status.dwInternetStatus, \
status.lpvStatusInformation, status.dwStatusInformationLength); \
free(status.lpvStatusInformation); }
}
_endthreadex(0);
return 0;
}
// Internet status notified callback procedure
void CWinHttpRequest::_ProcessNotification( DWORD dwInternetStatus, LPVOID \
lpvStatusInformation, DWORD dwStatusInformationLength ) {
InternetCookieHistory cookieHistory;
CString strDebugInfo;
switch(dwInternetStatus)
{
case INTERNET_STATUS_COOKIE_SENT:
OutputDebugString(_T("Status: Cookie found and will be sent with \
request\n")); break;
case INTERNET_STATUS_COOKIE_RECEIVED:
OutputDebugString(_T("Status: Cookie Received\n"));
break;
case INTERNET_STATUS_COOKIE_HISTORY:
OutputDebugString(_T("Status: Cookie History\n"));
assert(lpvStatusInformation);
assert(dwStatusInformationLength == sizeof(InternetCookieHistory));
cookieHistory = *((InternetCookieHistory*)lpvStatusInformation);
if(cookieHistory.fAccepted)
{
OutputDebugString(_T("Cookie Accepted\n"));
}
if(cookieHistory.fLeashed)
{
OutputDebugString(_T("Cookie Leashed\n"));
}
if(cookieHistory.fDowngraded)
{
OutputDebugString(_T("Cookie Downgraded\n"));
}
if(cookieHistory.fRejected)
{
OutputDebugString(_T("Cookie Rejected\n"));
}
break;
case INTERNET_STATUS_CLOSING_CONNECTION:
OutputDebugString(_T("Status: Closing Connection\n"));
break;
case INTERNET_STATUS_CONNECTED_TO_SERVER:
OutputDebugString(_T("Status: Connected to Server\n"));
break;
case INTERNET_STATUS_CONNECTING_TO_SERVER:
OutputDebugString(_T("Status: Connecting to Server\n"));
break;
case INTERNET_STATUS_CONNECTION_CLOSED:
OutputDebugString(_T("Status: Connection Closed\n"));
break;
case INTERNET_STATUS_HANDLE_CLOSING:
OutputDebugString(_T("Status: Handle Closing\n"));
break;
case INTERNET_STATUS_HANDLE_CREATED:
assert(lpvStatusInformation);
if(!m_strURL.IsEmpty())
{
m_hRequest = \
(HINTERNET)((LPINTERNET_ASYNC_RESULT)lpvStatusInformation)->dwResult; }
strDebugInfo.Format(_T("Handle %x created\n"), \
((LPINTERNET_ASYNC_RESULT)lpvStatusInformation)->dwResult); \
OutputDebugString(strDebugInfo); break;
case INTERNET_STATUS_INTERMEDIATE_RESPONSE:
OutputDebugString(_T("Status: Intermediate response\n"));
break;
case INTERNET_STATUS_RECEIVING_RESPONSE:
OutputDebugString(_T("Status: Receiving Response\n"));
break;
case INTERNET_STATUS_RESPONSE_RECEIVED:
assert(lpvStatusInformation);
assert(dwStatusInformationLength == sizeof(DWORD));
strDebugInfo.Format(_T("Status: Response Received (%d Bytes)\n"), \
*((LPDWORD)lpvStatusInformation)); OutputDebugString(strDebugInfo);
break;
case INTERNET_STATUS_REDIRECT:
OutputDebugString(_T("Status: Redirect\n"));
break;
case INTERNET_STATUS_REQUEST_COMPLETE:
OutputDebugString(_T("Status: Request complete\n"));
assert(lpvStatusInformation);
_ProcessRequest(((LPINTERNET_ASYNC_RESULT)lpvStatusInformation)->dwError);
break;
case INTERNET_STATUS_REQUEST_SENT:
assert(lpvStatusInformation);
assert(dwStatusInformationLength == sizeof(DWORD));
strDebugInfo.Format(_T("Status: Request sent (%d Bytes)\n"), \
*((LPDWORD)lpvStatusInformation)); OutputDebugString(strDebugInfo);
break;
case INTERNET_STATUS_DETECTING_PROXY:
OutputDebugString(_T("Status: Detecting Proxy\n"));
break;
case INTERNET_STATUS_RESOLVING_NAME:
OutputDebugString(_T("Status: Resolving Name\n"));
break;
case INTERNET_STATUS_NAME_RESOLVED:
OutputDebugString(_T("Status: Name Resolved\n"));
break;
case INTERNET_STATUS_SENDING_REQUEST:
OutputDebugString(_T("Status: Sending request\n"));
break;
case INTERNET_STATUS_STATE_CHANGE:
OutputDebugString(_T("Status: State Change\n"));
break;
case INTERNET_STATUS_P3P_HEADER:
OutputDebugString(_T("Status: Received P3P header\n"));
break;
default:
strDebugInfo.Format(_T("Status: Unknown (%d)\n"), dwInternetStatus);
OutputDebugString(strDebugInfo);
break;
}
}
// procedure to send request and receive response
void CWinHttpRequest::_ProcessRequest( DWORD dwCode )
{
OutputDebugString(_T("CWinHttpRequest::_ProcessRequest!!!!\n"));
while(dwCode == ERROR_SUCCESS && m_currentStatus != ReqStatus_Complete)
{
switch(m_currentStatus)
{
case ReqStatus_SendReq:
// send a simple request
m_currentStatus = ReqStatus_ResponseRecvData;
CWinInetUtility::SendRequest(m_hRequest);
return;
case ReqStatus_SendReqWithContent:
// start send request with content
m_currentStatus = ReqStatus_PostSendData;
CWinInetUtility::SendRequestEx(m_hRequest, m_dwContentLengthToPost, \
(DWORD_PTR)this); return;
case ReqStatus_PostSendData:
// send request content
m_dwSizePosted = 0;
dwCode = CWinInetUtility::WriteFileEx(m_hRequest, m_pContentToPost + \
m_dwSizePostedTotal, m_dwSizeToPostPerTime, &m_dwSizePosted); m_dwSizePostedTotal += \
m_dwSizePosted; if(m_dwSizePostedTotal == m_dwContentLengthToPost)
{
m_currentStatus = ReqStatus_PostComplete;
}
break;
case ReqStatus_PostComplete:
// all bytes are sent, need to end request
m_currentStatus = ReqStatus_ResponseRecvData;
dwCode = CWinInetUtility::EndRequest(m_hRequest);
break;
case ReqStatus_ResponseRecvData:
// start to receive response
{
CWinLocker locker(&m_csCallbackStatus);
m_listCallbackStatus.push_back(Status_Sent);
}
SetEvent(m_hEventCallbackUpdated);
if(m_response == NULL)
m_response = new CWinHttpResponse(this, m_dwSizeToReceivePerTime);
if((dwCode = m_response->ReceiveData()) == ERROR_SUCCESS)
{
// after all data are received, client callback should be triggered, \
then client can query data via IHttpResponse m_currentStatus = ReqStatus_Complete;
{
CWinLocker locker(&m_csCallbackStatus);
m_listCallbackStatus.push_back(Status_Received);
}
SetEvent(m_hEventCallbackUpdated);
}
break;
default:
assert(FALSE);
break;
}
}
// if it's pending, this function should be called in another \
ProcessNotification(INTERNET_STATUS_REQUEST_COMPLETE) if(dwCode != ERROR_IO_PENDING)
{
{
CWinLocker locker(&m_csCallbackStatus);
m_listCallbackStatus.push_back(Status_Error);
}
SetEvent(m_hEventCallbackUpdated);
}
return;
}
#pragma endregion
// get and pop the first element of Internet status list
BOOL CWinHttpRequest::_PopFrontInternetStatus( _InternetStatus& status )
{
BOOL bRet = FALSE;
CWinLocker locker(&m_csInternetStatus);
if(!m_listInternetStatus.empty())
{
status = *(m_listInternetStatus.begin());
m_listInternetStatus.pop_front();
bRet = TRUE;
}
return bRet;
}
// get and pop the first element of callback status list
BOOL CWinHttpRequest::_PopFrontCallbackStatus(HTTPRequestStatus& status)
{
BOOL bRet = FALSE;
CWinLocker locker(&m_csCallbackStatus);
if(!m_listCallbackStatus.empty())
{
status = *(m_listCallbackStatus.begin());
m_listCallbackStatus.pop_front();
bRet = TRUE;
}
return bRet;
}
// thread to trigger outer callback, then the callback procedure won't block any \
read/write process of current request unsigned __stdcall \
CWinHttpRequest::_TriggerCallbackThread( void* pArguments ) {
CWinHttpRequest *pRequest = (CWinHttpRequest *)pArguments;
HANDLE handles[2];
handles[0] = pRequest->m_hEventCallbackUpdated;
handles[1] = pRequest->m_hEventExit;
list<HTTPRequestStatus> *pListCallbackStatus = &pRequest->m_listCallbackStatus;
HTTPRequestStatus status = Status_Unknown;
while(WaitForMultipleObjects(2, handles, FALSE, INFINITE) == WAIT_OBJECT_0)
{
while(pRequest->_PopFrontCallbackStatus(status))
{
if(pRequest->m_hResonseCallback)
{
pRequest->m_hResonseCallback(status, pRequest);
}
}
}
_endthreadex(0);
return 0;
}
--- NEW FILE: WinInetUtility.h ---
#pragma once
#include <Windows.h>
#include <WinInet.h>
#include <atlstr.h>
class CWinInetUtility
{
public:
// Wininet HTTP methods - asynchronous mode
static void SetStatusCallback(HINTERNET hInternet, INTERNET_STATUS_CALLBACK \
lpCallback = NULL); static DWORD GetLastErrorCode();
static HINTERNET OpenInternet(LPCTSTR szUserAgent, DWORD dwAccessType = \
INTERNET_OPEN_TYPE_PRECONFIG, LPCTSTR szProxyName = NULL, LPCTSTR szProxyBypass = \
NULL); static void CloseInternet(HINTERNET& hInternet);
static HINTERNET OpenConnection(HINTERNET hInternet, LPCTSTR szServerAddr, \
DWORD_PTR dwContext, INTERNET_PORT nPort = INTERNET_DEFAULT_HTTP_PORT, LPCTSTR \
szUsrName = NULL, LPCTSTR szUsrPwd = NULL); static void CloseConnection(HINTERNET& \
hConnection); static HINTERNET OpenRequest(HINTERNET hConnection, LPCTSTR szMethod, \
LPCTSTR szObjectName, DWORD_PTR dwContext, DWORD dwFlags = INTERNET_FLAG_HYPERLINK
| INTERNET_FLAG_KEEP_CONNECTION
| INTERNET_FLAG_NO_UI
| INTERNET_FLAG_RESYNCHRONIZE
| INTERNET_FLAG_NO_CACHE_WRITE
| INTERNET_FLAG_PRAGMA_NOCACHE
| INTERNET_FLAG_RELOAD,
LPCTSTR szReferer = NULL);
static void CloseRequest(HINTERNET& hRequest);
static HINTERNET OpenURL(HINTERNET hInternet, LPCTSTR szURL,
DWORD_PTR dwContext,
DWORD dwFlags = INTERNET_FLAG_RELOAD);
static BOOL AddHeader(HINTERNET hRequest, LPCTSTR szName, LPCTSTR szValue);
static BOOL SendRequest(HINTERNET hRequest, LPVOID pPostedBuffer = NULL, DWORD \
dwBufferSize = 0); static BOOL SendRequestEx(HINTERNET hRequest, DWORD dwPostedSize, \
DWORD_PTR dwContext); static BOOL ReadFile(HINTERNET hRequest, LPVOID pBuffer, DWORD \
dwBytesToRead, LPDWORD pdwRead); static BOOL ReadFileEx(HINTERNET hRequest, LPVOID \
pBuffer, DWORD dwBytesToRead, LPDWORD pdwRead, DWORD_PTR dwContext); static BOOL \
WriteFile(HINTERNET hRequest, LPVOID pBuffer, DWORD dwBufferSize); static BOOL \
WriteFileEx(HINTERNET hRequest, LPVOID pBuffer, DWORD dwBufferSize, LPDWORD \
pdwWritten); static BOOL EndRequest(HINTERNET hRequest);
static BOOL GetStatus(HINTERNET hRequest, DWORD& dwStatus);
static BOOL GetStatusText(HINTERNET hRequest, CString& strStatusText);
static BOOL GetContentLength(HINTERNET hRequest, DWORD& dwContentLength);
static BOOL GetHeader(HINTERNET hRequest, CString& strHeader, LPCTSTR szName, \
DWORD* pdwIndex = NULL); static BOOL GetHeaders(HINTERNET hRequest, CString& \
strHeaders); static BOOL SetInternetOption(HINTERNET hInternet, DWORD dwOption, \
LPVOID lpBuffer, DWORD dwBufferLength);
private:
static void _CloseInternetHandler(HINTERNET& hHandler);
static BOOL QueryInfo(HINTERNET hRequest, DWORD dwQueryFlag, LPVOID pBuffer, \
DWORD& dwBufferSize, DWORD* pdwIndex = NULL); };
--- NEW FILE: WinHttpDriver.h ---
#pragma once
#include "HttpDriver.h"
#include <Wininet.h>
class CWinHttpDriver : public IHttpDriver
{
public:
CWinHttpDriver(void);
~CWinHttpDriver(void);
virtual unsigned long Initialize( const CString& strName );
virtual unsigned long Initialize( const CString& strName, unsigned long \
ulAccessType, const CString& strProxyName, const CString& strProxyByPass ); virtual \
IHttpRequest* CreateRequest(LPVOID pContext); virtual void ReleaseRequest( \
IHttpRequest* ); virtual void UnInitialize();
private:
static void WINAPI StatusNotifyCallback(__in HINTERNET hInternet,
__in DWORD_PTR dwContext,
__in DWORD dwInternetStatus,
__in_bcount(dwStatusInformationLength) LPVOID lpvStatusInformation,
__in DWORD dwStatusInformationLength);
private:
HINTERNET m_hInternet;
};
--- NEW FILE: WinHttpResponse.h ---
#pragma once
#include "HttpDriver.h"
#include <vector>
#include <map>
class CWinHttpRequest;
class CWinHttpResponse : public IHttpResponse
{
public:
CWinHttpResponse(CWinHttpRequest* pRequest, unsigned long \
ulSizePerTimeToReceive); ~CWinHttpResponse(void);
// IHttpResponse methods
virtual BOOL GetHeaders( CString& strHeaders ) const;
virtual int GetHeadersCount() const;
virtual BOOL GetContentLength( unsigned long& ulLength ) const;
virtual BOOL GetContent( BYTE *pBuffer, unsigned long ulBufferSize ) const;
virtual BOOL GetHeader( const CString& strName, CString& strHeader) const;
virtual BOOL GetStatusCode( unsigned long& ulStatus ) const;
virtual BOOL GetStatusText( CString& strStatus ) const;
public:
unsigned long ReceiveData();
private:
// cached data
std::map<CString, CString> m_mapHeaders;
CString m_strHeaders;
DWORD m_dwSizeToReceivePerTime;
DWORD m_dwSizeReceived;
DWORD m_dwSizeReceivedTotal;
// content
byte* m_pContent;
DWORD m_dwContentLength;
DWORD m_dwStatusCode;
CString m_strStatusText;
BOOL m_bIsChunked;
CWinHttpRequest* m_request;
};
_______________________________________________
Filesystem-cvs mailing list
Filesystem-cvs@helixcommunity.org
http://lists.helixcommunity.org/mailman/listinfo/filesystem-cvs
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic