|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995.
//
// File: cnethttp.cxx
//
// Contents:
//
// Classes:
//
// Functions:
//
// History: 2-06-96 JohannP (Johann Posch) Created
//
//----------------------------------------------------------------------------
#include <iapp.h>
#include "shlwapip.h"
#ifndef unix
#include "..\trans\transact.hxx"
#include "..\trans\oinet.hxx"
#else
#include "../trans/transact.hxx"
#include "../trans/oinet.hxx"
#endif /* unix */
PerfDbgTag(tagCINetHttp, "Urlmon", "Log CINetHttp", DEB_PROT);
extern LPSTR g_pszUAInfoString; static CHAR gszAcceptEncHeaders[] = "Accept-Encoding: gzip, deflate";
// http specifics
static char vszGet[] = "GET"; static char vszPost[] = "POST"; static char vszPut[] = "PUT"; static char vszAttachment[] = "attachment"; static char vszFileName[] = "filename"; static DWORD dwLstError; DWORD GetRedirectSetting();
// list of content-type we should not apply content-encoding onto it.
static LPSTR vszIgnoreContentEnc[] = { "application/x-tar" ,"x-world/x-vrml" ,"application/zip" ,"application/x-gzip" ,"application/x-zip-compressed" ,"application/x-compress" ,"application/x-compressed" ,"application/x-spoon" , 0 };
BOOL IgnoreContentEncoding(LPSTR szContentType, LPSTR szEnc, LPSTR szAccept) { DEBUG_ENTER((DBG_APP, Bool, "IgnoreContentEncoding", "%.80q, %.80q, %.80q", szContentType, szEnc, szAccept )); BOOL bRet = FALSE;
if( szEnc && szAccept && !StrStrI(szAccept, szEnc) ) { //
// some of the old web server will ignore the schemas indicated at
// Accept-Endocing: header, we need to add another check here
// to make sure the server returned content-encoding is the
// one we supported, otherwise, we will not init the decoder
//
bRet = TRUE; }
if( !bRet ) { for( int i = 0; vszIgnoreContentEnc[i]; i++) { if(!StrCmpI(szContentType, vszIgnoreContentEnc[i]) ) { bRet = TRUE; break; } } }
DEBUG_LEAVE(bRet); return bRet; }
//+---------------------------------------------------------------------------
//
// Function: GetRedirectSetting
//
// Synopsis: Reads the registry UrlMon Setting of Redirect
//
// Arguments: (none)
//
// Returns: 0 if redirect should be done by WinINet,
// 1 if should be done by UrlMon
//
// History: 4-22-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD GetRedirectSetting() { DEBUG_ENTER((DBG_APP, Dword, "GetRedirectSetting", NULL )); HKEY hUrlMonKey = NULL; DWORD dwType; static DWORD dwValue = 0xffffffff;
if (dwValue == 0xffffffff) { DWORD dwValueLen = sizeof(DWORD); dwValue = 0;
#define szUrlMonKey "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\UrlMon Settings"
#define szRedirect "Redirect"
if (RegOpenKeyEx(HKEY_CURRENT_USER, szUrlMonKey, 0, KEY_QUERY_VALUE, &hUrlMonKey) == ERROR_SUCCESS) { if (RegQueryValueEx(hUrlMonKey, szRedirect, NULL, &dwType, (LPBYTE)&dwValue, &dwValueLen) != ERROR_SUCCESS) { dwValue = 0; } RegCloseKey(hUrlMonKey); } }
DEBUG_LEAVE(dwValue); return dwValue; }
// max version strlen = (5)"HTTP/" + (4)digits + (1)'.' + (4)digits + (1)'\0'
#define MAXVERSIONLEN 15
BOOL RequestUsedHttp10( IN HINTERNET hHttpRequest ) { DEBUG_ENTER((DBG_APP, Bool, "RequestUsedHttp10", "%#x", hHttpRequest )); char lpszHttpVersion[MAXVERSIONLEN]; DWORD dwLen = MAXVERSIONLEN; BOOL fRet = FALSE;
if (HttpQueryInfo( hHttpRequest, HTTP_QUERY_FLAG_REQUEST_HEADERS | HTTP_QUERY_VERSION, (LPVOID)lpszHttpVersion, &dwLen, NULL)) { if (0 == StrCmpNI("HTTP/1.0", lpszHttpVersion, dwLen)) fRet = TRUE; }
DEBUG_LEAVE(fRet); return fRet; } //+---------------------------------------------------------------------------
//
// Method: CINetHttp::CINetHttp
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 2-06-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
CINetHttp::CINetHttp(REFCLSID rclsid, IUnknown *pUnkOuter) : CINet(rclsid,pUnkOuter) { DEBUG_ENTER((DBG_APP, None, "CINetHttp::CINetHttp", "this=%#x, %#x, %#x", this, &rclsid, pUnkOuter )); PerfDbgLog(tagCINetHttp, this, "+CINetHttp::CINetHttp");
_pHttpNeg = NULL; _pHttpNeg2 = NULL; _dwIsA = DLD_PROTOCOL_HTTP; _dwBufferSize = 0; _pBuffer = 0; _pszVerb = 0; _f2ndCacheKeySet = FALSE;
PerfDbgLog(tagCINetHttp, this, "-CINetHttp::CINetHttp");
DEBUG_LEAVE(0); }
//----------------------------------------------------------------------------
//
// Method: CINetHttp::~CINetHttp
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 2-06-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
CINetHttp::~CINetHttp() { DEBUG_ENTER((DBG_APP, None, "CINetHttp::~CINetHttp", "this=%#x", this )); PerfDbgLog(tagCINetHttp, this, "+CINetHttp::~CINetHttp"); PProtAssert(( !_hRequest )); PProtAssert(( !_hServer ));
delete [] _pBuffer; delete [] _pszHeader; delete [] _pszSendHeader; delete [] _pwzAddHeader; delete [] _pszVerb; if (_pbRootSecurityId != INVALID_P_ROOT_SECURITY_ID) delete [] _pbRootSecurityId; PProtAssert((_pHttpNeg == NULL)); PProtAssert((_pHttpNeg2 == NULL)); PProtAssert((_pWindow == NULL)); PProtAssert(( _pHttSecurity == NULL));
PerfDbgLog(tagCINetHttp, this, "-CINetHttp::~CINetHttp");
DEBUG_LEAVE(0); }
//+---------------------------------------------------------------------------
//
// Method: CINetHttp::INetAsyncOpenRequest
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINetHttp::INetAsyncOpenRequest() { DEBUG_ENTER((DBG_APP, Hresult, "CINetHttp::INetAsyncOpenRequest", "this=%#x", this )); PerfDbgLog1(tagCINetHttp, this, "+CINetHttp::INetAsyncOpenRequest (_szObject:%s)", GetObjectName()); HRESULT hr = NOERROR; DWORD dwBindF = 0; const ULONG culSize = 256; ULONG ulSize = culSize; LPCSTR rgszAcceptStr[culSize] = { 0 }; LPWSTR rgwzStr[culSize];
SetINetState(INetState_PROTOPEN_REQUEST); PProtAssert((g_hSession != NULL)); PProtAssert((GetStatePending() == NOERROR));
if (_pOIBindInfo) { LPWSTR *pwzStr; IEnumString *pEnumString = NULL; ULONG ulCount = culSize;
hr = _pOIBindInfo->GetBindString(BINDSTRING_ACCEPT_MIMES, (LPWSTR *)rgwzStr, ulSize, &ulCount);
if (hr == NOERROR) { ULONG c = 0;
for (c = 0; c < ulCount; c++) { rgszAcceptStr[c] = (LPCSTR) DupW2A(rgwzStr[c]); delete rgwzStr[c]; rgwzStr[c] = 0; } rgszAcceptStr[c] = 0; } else if( hr == INET_E_USE_DEFAULT_SETTING ) { rgszAcceptStr[0] = (LPCSTR) DupW2A(L"*/*"); rgszAcceptStr[1] = NULL; hr = NOERROR; }
} if (hr != NOERROR) { hr = INET_E_NO_VALID_MEDIA; _hrError = INET_E_NO_VALID_MEDIA; } else if (!_hServer) { // the download was probably aborted
if (_hrError == NOERROR) { SetBindResult(ERROR_INVALID_HANDLE, hr); hr = _hrError = INET_E_CANNOT_CONNECT; } else { hr = _hrError; } } else { PProtAssert((_hServer));
//PProtAssert((ppszAcceptStr && *ppszAcceptStr));
#if DBG==1
{ LPSTR *pszMime = (LPSTR *) &rgszAcceptStr; while (*pszMime) { PerfDbgLog1(tagCINetHttp, this, "=== CTransData::GetAcceptStr (szMime:%s)", *pszMime); pszMime++; } } #endif
dwBindF = GetBindFlags();
if (dwBindF & BINDF_IGNORESECURITYPROBLEM) { _dwOpenFlags |= INTERNET_FLAG_IGNORE_CERT_CN_INVALID; _dwOpenFlags |= INTERNET_FLAG_IGNORE_CERT_DATE_INVALID; _dwOpenFlags |= INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS; _dwOpenFlags |= INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP; }
if (dwBindF & BINDF_ENFORCERESTRICTED) { _dwOpenFlags |= INTERNET_FLAG_RESTRICTED_ZONE; }
if (GetRedirectSetting() != 0) { DbgLog(tagCINetHttp, this, "=== CINet::INetAsyncOpenRequest redirect done by UrlMon!"); _dwOpenFlags |= INTERNET_FLAG_NO_AUTO_REDIRECT; } else { DbgLog(tagCINetHttp, this, "=== CINet::INetAsyncOpenRequest redirect done by WinINet!"); }
//
// we always request keep-alive
//
_dwOpenFlags |= INTERNET_FLAG_KEEP_CONNECTION;
//
// Notify wininet if this is a multipart upload so it doesn't
// add a terminating 0x0d 0x0a to the first send
//
BINDINFO *pBndInfo = GetBindInfo(); if (IsUpLoad() // Add in extra check to make TYMED_ISTREAM work the same as
// TYMED_HGLOBAL for verbs that require a body, other than POST.
// We might consider doing away with this IF statement in the future:
&& (pBndInfo->dwBindVerb == BINDVERB_POST)) { _dwOpenFlags |= INTERNET_FLAG_NO_AUTO_REDIRECT; //BUGBUG: is the flag below needed?
//_dwOpenFlags |= INTERNET_FLAG_MULTIPART;
}
PrivAddRef(TRUE); SetStatePending(E_PENDING);
_HandleStateRequest = HandleState_Pending; HINTERNET hRequestTmp = HttpOpenRequest( _hServer, // hHttpSession
GetVerb(), // lpszVerb
GetObjectName(), // lpszObjectName
NULL, //HTTP_VERSION, // lpszVersion
NULL, // lpszReferer
rgszAcceptStr, // lplpszAcceptTypes
_dwOpenFlags, // flag
(DWORD_PTR) this // context
); if ( hRequestTmp == 0) { dwLstError = GetLastError(); if (dwLstError == ERROR_IO_PENDING) { // wait async for the handle
hr = E_PENDING; } else { PrivRelease(TRUE); SetStatePending(NOERROR); hr = _hrError = INET_E_RESOURCE_NOT_FOUND; SetBindResult(dwLstError,hr); } } else { _hRequest = hRequestTmp; SetStatePending(NOERROR); _HandleStateRequest = HandleState_Initialized;
if (_fUTF8hack) { DWORD dwSendUTF8 = 1; InternetSetOption(_hRequest, INTERNET_OPTION_SEND_UTF8_SERVERNAME_TO_PROXY, &dwSendUTF8, sizeof(DWORD)); InternetSetOption(_hRequest, INTERNET_OPTION_CODEPAGE, &_dwServerCodePage, sizeof(DWORD)); }
hr = INetAsyncSendRequest(); }
{ LPSTR *pszMime = (LPSTR *) &rgszAcceptStr; while (*pszMime) { LPSTR pszDel = *pszMime; delete pszDel; pszMime++; } } }
PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::INetAsyncOpenRequest (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINetHttp::INetAsyncSendRequest
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINetHttp::INetAsyncSendRequest() { DEBUG_ENTER((DBG_APP, Hresult, "CINetHttp::INetAsyncSendRequest", "this=%#x", this )); PerfDbgLog(tagCINetHttp, this, "+CINetHttp::INetAsyncSendRequest");
HRESULT hr = NOERROR; BOOL fRestarted; BOOL fRet; PProtAssert((GetStatePending() == NOERROR));
SetINetState(INetState_SEND_REQUEST);
LPVOID pBuffer = 0; DWORD dwBufferSize = 0; LPSTR szVerb = GetVerb();
//
// BUGBUG: move this into GetAdditionalHeader
//
if (_fRedirected == TRUE || (_cbProxyAuthenticate + _cbAuthenticate)) { if (_pszSendHeader) { delete _pszSendHeader; _pszSendHeader = NULL; }
}
if (_fRedirected == FALSE && !(_cbProxyAuthenticate + _cbAuthenticate)) { GetAdditionalHeader(); }
if (_fRedirected == FALSE || _fP2PRedirected ) { // Note: the buffer returned here will be freed
// by the destructor
GetDataToSend(&pBuffer, &dwBufferSize); _fP2PRedirected = FALSE; }
// Call HttpNeg only the first time in case of authentication
// i.e. both Auth counts == 0 ?
if (!(_cbAuthenticate || _cbProxyAuthenticate)) { //BUGBUG: does BeginingTrans need to be called for
// redirect and authentication resends?
if (_fRedirected == FALSE) hr = HttpNegBeginningTransaction(); // Note: the header is appended to the AddHeader
}
HttpNegGetRootSecurityId(); LONG lThirdParty; if (IsThirdPartyUrl(GetUrl())) { lThirdParty = 1; //MessageBoxW( 0, GetUrl(), L"cnethttp: THIRDPARTY!", 0 );
InternetSetOption(_hRequest, INTERNET_OPTION_COOKIES_3RD_PARTY, &lThirdParty, sizeof(LONG)); } else { lThirdParty = 0; //MessageBoxW( 0, GetUrl(), L"cnethttp: NOT THIRDPARTY!", 0 );
InternetSetOption(_hRequest, INTERNET_OPTION_COOKIES_3RD_PARTY, &lThirdParty, sizeof(LONG)); } if (hr == E_ABORT) { _hrError = hr; SetBindResult(ERROR_CANCELLED,hr); } else { PerfDbgLog1(tagCINetHttp, this, "+CINetHttp::INetAsyncSendRequest HttpSendRequest (_pszSendHeader:%s)", XDBG(_pszSendHeader,""));
if (GetBindInfo()->dwBindVerb == BINDVERB_POST && !_f2ndCacheKeySet) { // WININET request: send SECONDARY_CACHE_KEY only once
ULONG ulCount = 0; LPWSTR pwzPostCookieStr = 0; HRESULT hr1 = _pOIBindInfo->GetBindString(BINDSTRING_POST_COOKIE, (LPWSTR *)&pwzPostCookieStr, 1, &ulCount); if ((hr1 == NOERROR) && pwzPostCookieStr) { // BUGBUG: trident return s_ok and no string
PProtAssert((pwzPostCookieStr)); LPSTR pszStr = DupW2A(pwzPostCookieStr); if (pszStr) { _f2ndCacheKeySet = TRUE; InternetSetOption(_hRequest, INTERNET_OPTION_SECONDARY_CACHE_KEY, pszStr, strlen(pszStr)); delete pszStr; } else { hr = E_OUTOFMEMORY; _hrError = INET_E_DOWNLOAD_FAILURE; SetBindResult(hr,hr); } delete pwzPostCookieStr; }
}
/************ enable this after wininet sniff checked in *******
// set option for data sniff
DWORD dwDataSniff = 1; InternetSetOption(_hRequest, INTERNET_OPTION_DATASNIFF, &dwDataSniff, sizeof(DWORD)); ****************************************************************/
InternetSetOption(_hRequest, INTERNET_OPTION_REQUEST_PRIORITY, &_nPriority, sizeof(LONG));
if (_fRedirected || !_fUTF8hack) { /*
This is used in wininet now only to convert the MBCS servername supplied to UTF8 to send to the proxy if needed */ InternetSetOption(_hRequest, INTERNET_OPTION_CODEPAGE, &_BndInfo.dwCodePage, sizeof(DWORD)); } SetStatePending(E_PENDING);
if (hr == NOERROR) { if (IsUpLoad()) { // post verb
// DWORD dwSendFlags = HSR_ASYNC | HSR_CHUNKED | HSR_INITIATE;
DWORD dwSendFlags = HSR_CHUNKED | HSR_INITIATE; DWORD dwSendContext = 0;
if (!_pStm) { BINDINFO *pBI = GetBindInfo(); if (pBI && pBI->stgmedData.tymed == TYMED_ISTREAM) { _pStm = pBI->stgmedData.pstm; } } if (_pStm) { hr = GetNextSendBuffer(&_inetBufferSend,_pStm, TRUE); }
fRet = HttpSendRequestExA( _hRequest // IN HINTERNET hRequest,
,&_inetBufferSend // IN LPINTERNET_BUFFERSA lpBuffersIn OPTIONAL,
, NULL // OUT lpBuffersOut not used
,dwSendFlags // IN DWORD dwFlags,
,dwSendContext // IN DWORD dwContext
); } else { DWORD dwError;
// Allow ERROR_INTERNET_INSERT_CDROM to be returned from HttpSendRequest
#ifdef MSNJIT
DWORD dwErrorMask = INTERNET_ERROR_MASK_INSERT_CDROM | INTERNET_ERROR_MASK_COMBINED_SEC_CERT | INTERNET_ERROR_MASK_NEED_MSN_SSPI_PKG; #else
DWORD dwErrorMask = INTERNET_ERROR_MASK_INSERT_CDROM | INTERNET_ERROR_MASK_COMBINED_SEC_CERT; #endif
dwErrorMask = dwErrorMask | INTERNET_ERROR_MASK_LOGIN_FAILURE_DISPLAY_ENTITY_BODY;
InternetSetOption(_hRequest, INTERNET_OPTION_ERROR_MASK, &dwErrorMask, sizeof(DWORD));
fRet = HttpSendRequest(_hRequest, _pszSendHeader, // additional headers
(_pszSendHeader) ? (ULONG)-1L : 0L, // size of additional headers data
pBuffer, // Optional data (POST or put)
dwBufferSize); // optional data length
PerfDbgLog(tagCINetHttp, this, "-CINetHttp::INetAsyncSendRequest HttpSendRequest");
} // end else
if (fRet == FALSE) { dwLstError = GetLastError(); if (dwLstError == ERROR_IO_PENDING) { // wait async for the handle
hr = E_PENDING; } else if (dwLstError == ERROR_INTERNET_INSERT_CDROM) { _hrINet = INET_E_AUTHENTICATION_REQUIRED; _dwSendRequestResult = ERROR_INTERNET_INSERT_CDROM; _lpvExtraSendRequestResult = NULL; TransitState(INetState_DISPLAY_UI, TRUE); hr = E_PENDING; fRet = TRUE; } else { SetStatePending(NOERROR); hr = _hrError = INET_E_DOWNLOAD_FAILURE; SetBindResult(dwLstError,hr); PerfDbgLog3(tagCINetHttp, this, "CINetHttp::INetAsyncSendRequest (fRet:%d, _hrError:%lx, LstError:%ld)", fRet, _hrError, dwLstError); } } else { SetStatePending(NOERROR);
// in case of redirect, we need to reset all the
// _dwSendRequestResult from previous callback
_dwSendRequestResult = 0; _lpvExtraSendRequestResult = NULL; hr = INetQueryInfo(); } } }
if (_hrError != INET_E_OK) { // we need to terminate here
ReportResultAndStop(hr); }
PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::INetAsyncSendRequest (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINetHttp::QueryStatusOnResponse
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 2-06-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINetHttp::QueryStatusOnResponse() { DEBUG_ENTER((DBG_APP, Hresult, "CINetHttp::QueryStatusOnResponse", "this=%#x", this )); PerfDbgLog(tagCINetHttp, this, "+CINetHttp::QueryStatusOnResponse"); HRESULT hr = NOERROR;
DWORD dwStatus; char szBuffer[max(2 * MAX_URL_SIZE, 400)]; DWORD cbBufferLen = sizeof(szBuffer); DWORD cbLen = cbBufferLen;
if (_dwSendRequestResult) { // handle the sendrequest result
// zone crossing
switch (_dwSendRequestResult) { case ERROR_INTERNET_SEC_CERT_DATE_INVALID : case ERROR_INTERNET_SEC_CERT_CN_INVALID : case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR : case ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR : case ERROR_INTERNET_HTTPS_HTTP_SUBMIT_REDIR : case ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION : case ERROR_INTERNET_INVALID_CA : case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED : case ERROR_INTERNET_FORTEZZA_LOGIN_NEEDED : case ERROR_INTERNET_SEC_CERT_ERRORS : case ERROR_INTERNET_SEC_CERT_REV_FAILED : case ERROR_INTERNET_SEC_CERT_REVOKED : { hr = HttpSecurity(_dwSendRequestResult);
if ((hr != NOERROR) && (hr != E_PENDING)) { _hrError = INET_E_AUTHENTICATION_REQUIRED; } else { _hrError = INET_E_OK; }
} break;
case ERROR_INTERNET_LOGIN_FAILURE_DISPLAY_ENTITY_BODY : { _hrError = INET_E_OK; hr = NOERROR; } break;
#ifdef MSNJIT
case ERROR_INTERNET_NEED_MSN_SSPI_PKG : { const GUID MSN_AUTH_GUID = { 0x6fab99d0, 0xbab8, 0x11d1, {0x99, 0x4a, 0x00, 0xc0, 0x4f, 0x98, 0xbb, 0xc9} };
HWND hWnd = NULL; DWORD dwJITFlags = 0; uCLSSPEC classpec; classpec.tyspec=TYSPEC_TYPELIB; classpec.tagged_union.typelibID = (GUID)MSN_AUTH_GUID;
QUERYCONTEXT qc; memset(&qc, 0, sizeof(qc));
// fill in the minimum version number of the component you need
//qc.dwVersionHi =
//qc.dwVersionLo =
hr = FaultInIEFeature(hWnd, &classpec, &qc, dwJITFlags);
if (hr == S_OK) { hr = INET_E_AUTHENTICATION_REQUIRED; } else { hr = E_ABORT; } }
break; #endif
default: break; }
} else if (HttpQueryInfo(_hRequest, HTTP_QUERY_STATUS_CODE, szBuffer,&cbLen, NULL)) { dwStatus = atoi(szBuffer); _fProxyAuth = FALSE; switch (dwStatus) { case HTTP_STATUS_DENIED: { _hrINet = INET_E_AUTHENTICATION_REQUIRED; TransitState(INetState_AUTHENTICATE, TRUE); hr = E_PENDING; } break; case HTTP_STATUS_PROXY_AUTH_REQ : { _hrINet = INET_E_AUTHENTICATION_REQUIRED; TransitState(INetState_AUTHENTICATE, TRUE); _fProxyAuth = TRUE; hr = E_PENDING; } break; case HTTP_STATUS_MOVED: case HTTP_STATUS_REDIRECT: case HTTP_STATUS_REDIRECT_METHOD: case HTTP_STATUS_REDIRECT_KEEP_VERB: { cbLen = cbBufferLen; hr = RedirectRequest(szBuffer, &cbLen, dwStatus); if ((hr != S_FALSE) && (hr != NOERROR) && (hr != E_PENDING)) { _hrError = INET_E_INVALID_URL; } else { _hrError = INET_E_OK; hr = S_FALSE; SetINetState(INetState_DONE); } } break; case HTTP_STATUS_NO_CONTENT: { BINDINFO *pBndInfo = GetBindInfo();
if (pBndInfo && pBndInfo->dwBindVerb != BINDVERB_CUSTOM) { hr = _hrError = E_ABORT; SetBindResult(ERROR_CANCELLED, hr); } else { hr = QueryStatusOnResponseDefault(dwStatus); } } break; default: { hr = QueryStatusOnResponseDefault(dwStatus); } break; } }
if (_hrError != INET_E_OK) { SetINetState(INetState_DONE); }
PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::QueryStatusOnResponse (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINetHttp::QueryStatusOnResponseDefault
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 2-06-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINetHttp::QueryStatusOnResponseDefault(DWORD dwStat) { DEBUG_ENTER((DBG_APP, Hresult, "CINetHttp::QueryStatusOnResponseDefault", "this=%#x, %#x", this, dwStat )); PerfDbgLog(tagCINetHttp, this, "+CINetHttp::QueryStatusOnResponseDefault"); HRESULT hr = NOERROR;
DWORD dwStatus = 0; char szBuffer[max(2 * MAX_URL_SIZE, 400)]; DWORD cbBufferLen = sizeof(szBuffer); DWORD cbLen = cbBufferLen;
if( !dwStat ) { if (HttpQueryInfo(_hRequest, HTTP_QUERY_STATUS_CODE, szBuffer,&cbLen, NULL)) { dwStatus = atoi(szBuffer); } } else { dwStatus = dwStat; }
if( dwStatus ) { #if DBG==1
if ( !((dwStatus >= HTTP_STATUS_OK) && (dwStatus <= HTTP_STATUS_GATEWAY_TIMEOUT)) ) { DbgLog1(DEB_PROT|DEB_TRACE, this, "CINetHttp::QueryStatusOnResponse (dwStatus:%lx)", dwStatus); } PProtAssert(( (dwStatus >= HTTP_STATUS_BEGIN) && (dwStatus <= HTTP_STATUS_END) && L"WinINet returned an invalid status code: please contact a WININET developer" )); #endif //DBG==1
// check if we got redirected from a file to a directory
{ cbLen = cbBufferLen; InternetQueryOption(_hRequest, INTERNET_OPTION_URL, szBuffer, &cbLen); if (cbLen) { BOOL fRedirected; fRedirected = strcmp(szBuffer, _pszFullURL);
if (fRedirected) { cbLen = cbBufferLen; hr = RedirectRequest(szBuffer, &cbLen, dwStatus);
if ((hr != NOERROR) && (hr != E_PENDING)) { if (hr != INET_E_DOWNLOAD_FAILURE) { _hrError = INET_E_INVALID_URL; } // else set nothing
} else { _hrError = INET_E_OK; } } } }
cbLen = cbBufferLen; BOOL fRet = HttpQueryInfo(_hRequest, HTTP_QUERY_RAW_HEADERS_CRLF, szBuffer,&cbLen, NULL); BOOL fDeleteBuffer = FALSE; LPSTR lpszBuffer; if (!fRet) { DWORD dwError = GetLastError();
if (dwError == ERROR_INSUFFICIENT_BUFFER) { lpszBuffer = new char[cbLen]; if (!lpszBuffer) { hr = E_OUTOFMEMORY; goto End; } fDeleteBuffer = TRUE; fRet = HttpQueryInfo(_hRequest, HTTP_QUERY_RAW_HEADERS_CRLF, lpszBuffer, &cbLen, NULL); } } else lpszBuffer = szBuffer;
if (fRet) { if (IsStatusOk(dwStatus)) { hr = HttpNegOnHeadersAvailable(dwStatus, lpszBuffer); } else { hr = ErrorHandlingRequest(dwStatus, lpszBuffer); if ((hr != NOERROR) && (hr != E_PENDING)) { _hrError = hr; } else { _hrError = INET_E_OK; } } if (hr == E_ABORT) { SetBindResult(ERROR_CANCELLED,hr); } }
if (fDeleteBuffer) delete lpszBuffer; } End: PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::QueryStatusOnResponseDefault (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINetHttp::QueryHeaderOnResponse
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 2-06-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINetHttp::QueryHeaderOnResponse() { DEBUG_ENTER((DBG_APP, Hresult, "CINetHttp::QueryHeaderOnResponse", "this=%#x", this )); PerfDbgLog(tagCINetHttp, this, "+CINetHttp::QueryHeaderOnResponse"); HRESULT hr = NOERROR; DWORD dwStatus; char szBuffer[max(2 * MAX_URL_SIZE, 400)]; DWORD cbBufferLen = sizeof(szBuffer); DWORD dwFlags; char szMIMEType[SZMIMESIZE_MAX] = ""; char szENCType[SZMIMESIZE_MAX] = ""; BOOL fContentDisp = FALSE;
// Get file length
if(HttpQueryInfo(_hRequest, HTTP_QUERY_CONTENT_LENGTH, szBuffer,&cbBufferLen, NULL)) { _cbDataSize = atoi(szBuffer); }
// Get Content-Disposition
szBuffer[0] = '\0'; cbBufferLen = sizeof(szBuffer);
if(HttpQueryInfo( _hRequest, HTTP_QUERY_CONTENT_DISPOSITION, szBuffer, &cbBufferLen, NULL) ) { // Search for :Attachment, if found, report it
if( StrStrI(szBuffer, vszAttachment) ) { char szName[MAX_PATH]; char *pName = NULL;
// propogate the filename if available
if( StrStrI(szBuffer, vszFileName) ) { DWORD cbNameLen;
szName[0] = '\0'; cbNameLen = sizeof(szName);
if(InternetQueryOption(_hRequest, INTERNET_OPTION_DATAFILE_NAME, szName, &cbNameLen)) pName = PathFindFileName(szName); }
ReportNotification(BINDSTATUS_CONTENTDISPOSITIONATTACH, (pName?pName:NULL)); } if( StrStrI(szBuffer, vszFileName) ) { fContentDisp = TRUE; } }
// Get Accept-Ranges
szBuffer[0] = '\0'; cbBufferLen = sizeof(szBuffer); if(HttpQueryInfo( _hRequest, HTTP_QUERY_ACCEPT_RANGES, szBuffer, &cbBufferLen, NULL) ) { ReportNotification(BINDSTATUS_ACCEPTRANGES, NULL); }
// mimetype
cbBufferLen = sizeof(szMIMEType); szMIMEType[0] = 0; HttpQueryInfo(_hRequest, HTTP_QUERY_CONTENT_TYPE, szMIMEType, &cbBufferLen, NULL); if (cbBufferLen && (szMIMEType[0] != 0)) { //BUG-WORK
//_pCTransData->SetMimeType(szMIMEType);
//_pCTrans->ReportProgress();
DbgLog1(DEB_PROT|DEB_TRACE, this, "CINetHttp::QueryHeaderOnResponse MIME TYPE(szMime:%s)!", szMIMEType);
// work around image display problem, turn off report mime type
// for direct binding
if( _grfBindF & BINDF_FROMURLMON) { ReportNotification(BINDSTATUS_MIMETYPEAVAILABLE,szMIMEType); } else { ReportNotification(BINDSTATUS_RAWMIMETYPE, szMIMEType); }
/*** enable this block after wininet data sniff checked in ****
if( _cbDataSize ) {
// datasniff enabled ?
DWORD dwDataSniff = 0; DWORD dwSize = sizeof(DWORD);
if( InternetQueryOption( _hRequest, INTERNET_OPTION_DATASNIFF, &dwDataSniff, &dwSize ) )
{ char szVCType[SZMIMESIZE_MAX] = ""; cbBufferLen = SZMIMESIZE_MAX;
InternetQueryOption( _hRequest, INTERNET_OPTION_VERIFIED_CONTENT_TYPE, szVCType, &cbBufferLen );
} } ****************************************************************/ } else { DbgLog1(DEB_PROT|DEB_TRACE, this, "CINetHttp::QueryHeaderOnResponse NO MIME TYPE (szUrl:%s)!", GetBaseURL()); //BUGBUG: need data sniffing later on
//_pCTransData->SetMimeType("text/html");
// work around image display problem, turn off report mime type
// for direct binding
if( _grfBindF & BINDF_FROMURLMON) { ReportNotification(BINDSTATUS_MIMETYPEAVAILABLE,"text/html"); } }
// content encoding
cbBufferLen = sizeof(szENCType); HttpQueryInfo(_hRequest, HTTP_QUERY_CONTENT_ENCODING, szENCType, &cbBufferLen, NULL); if (cbBufferLen && (szENCType[0] != 0)) { DbgLog1(DEB_PROT|DEB_TRACE, this, "CINetHttp::QueryHeaderOnResponse ENCODING TYPE(szEnc :%s)!", szENCType); //
// existing http servers may mishandle the content-encoding
// header, we have to taken care of the following cases:
//
// 1. we do not send Accept-Encoding header(http1.1 disabled),
// however, server sends back Content-Encoding: foo
// (_pszHeaders contains the accept-encoding info, so if
// this is null, we should not invoke the decoder )
//
// 2. we send Accept-Encoding: A, server sends back
// Content-Encoding: B, this is a protocol violation
// IgnoreContentEncoding() takes care of that, it compares
// the _pszHeader and szENCType, and we should not invoke
// the decoder if they are mis-matched
//
// 3. server sends out content-encoding, but what they really
// mean is that let the application (e.g. gunzip.exe) to
// handle the compressed file, we can add the check for
// content-type, for a list of content-type we do not
// understand (e.g. application/x-compress, x-world/x-vrml..)
// do not invoke the decoder
//
// Wininet changes http version if http1.1 over proxy is disabled.
// This happens only after httpSendRequest is called, which is when
// Urlmon might have passed in the Accept-Encoding headers.
// If we did pass in the headers, we need to make sure that they
// were not stripped out because wininet finally used Http 1.0.
if( _pszHeader && !RequestUsedHttp10(_hRequest) && !IgnoreContentEncoding(szMIMEType, szENCType, _pszHeader) ) { ReportNotification(BINDSTATUS_ENCODING, szENCType);
// Load The decompression handler now...
COInetSession *pCOInetSession = NULL; IOInetProtocol *pProtHandler = NULL; IOInetProtocolSink *pProtSnkHandler = NULL; IOInetBindInfo *pBindInfo = NULL; LPWSTR pwzStr = DupA2W(szENCType); CLSID clsid;
hr = GetCOInetSession(0,&pCOInetSession,0); if( hr == NOERROR ) { hr = pCOInetSession->CreateHandler( pwzStr, 0, 0, &pProtHandler, &clsid);
if( hr == NOERROR ) { hr = pProtHandler->QueryInterface( IID_IOInetProtocolSink, (void **) &pProtSnkHandler);
//hr = QueryInterface(
// IID_IOInetBindInfo, (void **) &pBindInfo);
}
if( hr == NOERROR ) { HRESULT hr2 = NOERROR; hr2 = _pEmbdFilter->SwitchSink(pProtSnkHandler); if( hr2 == NOERROR ) { hr = _pEmbdFilter->StackFilter( pwzStr, pProtHandler, pProtSnkHandler, _pOIBindInfo ); } }
if( pBindInfo ) { pBindInfo->Release(); } }
if( szMIMEType[0] != '\0' ) { ReportNotification(BINDSTATUS_MIMETYPEAVAILABLE,szMIMEType); }
// Get Cache-Control
szBuffer[0] = '\0'; cbBufferLen = sizeof(szBuffer); if(HttpQueryInfo( _hRequest, HTTP_QUERY_CACHE_CONTROL, szBuffer, &cbBufferLen, NULL) ) { ReportNotification(BINDSTATUS_CACHECONTROL, szBuffer); }
if(fContentDisp) { // Get Content-Disposition
szBuffer[0] = '\0'; cbBufferLen = sizeof(szBuffer);
if(InternetQueryOption(_hRequest, INTERNET_OPTION_DATAFILE_NAME, szBuffer, &cbBufferLen)) { ReportNotification(BINDSTATUS_CONTENTDISPOSITIONATTACH, PathFindFileName(szBuffer)); } } // urlmon will create a decompressed cache-file, so we should not
// report the compressed file name to the client.
_fFilenameReported = TRUE;
if (pwzStr) { delete pwzStr; } } }
#ifdef TEST_STACK_FILTER_ONE
//test for stackable filter..
//need to include mft.hxx for sample implementation of the filter
{ IOInetProtocol* pFilter = (IOInetProtocol*) new CMft; IOInetProtocolSink* pFilterSink = NULL; pFilter->QueryInterface( IID_IOInetProtocolSink, (void**)&pFilterSink);
// connect the last filter sink with pFilter's Sink
HRESULT hr2 = NOERROR; hr2 = _pEmbdFilter->SwitchSink(pFilterSink);
if( hr2 == NOERROR ) { hr = _pEmbdFilter->StackFilter(NULL, pFilter, NULL, NULL); }
// this object gets created here, pFilter gets AddRef'd during
// the StackFilter(), we should release the additional Ref Count
// here
// this does not apply to the first filter stacked
if( _pEmbdFilter->FilterStacked() > 1 ) { pFilter->Release(); } } #endif
#ifdef TEST_STACK_FILTER_TWO
{ // another one...
IOInetProtocol* pFilter_2 = (IOInetProtocol*) new CMft; IOInetProtocolSink* pFilterSink_2 = NULL; pFilter_2->QueryInterface( IID_IOInetProtocolSink, (void**)&pFilterSink_2);
// connect the last filter sink with pFilter's Sink
HRESULT hr3 = NOERROR; hr3 = _pEmbdFilter->SwitchSink(pFilterSink_2);
if( hr3 == NOERROR ) { hr = _pEmbdFilter->StackFilter(NULL, pFilter_2, NULL, NULL); }
// this object gets created here, pFilter gets AddRef'd during
// the StackFilter(), we should release the additional Ref Count
// here
// this does not apply to the first filter stacked
if( _pEmbdFilter->FilterStacked() > 1 ) { pFilter_2->Release(); } } #endif
if (_hrError != INET_E_OK) { SetINetState(INetState_DONE); hr = S_FALSE; }
PerfDbgLog2(tagCINetHttp, this, "-CINetHttp::QueryHeaderOnResponse (hr:%lx, _cbDataSize:%ld)", hr, _cbDataSize);
DEBUG_LEAVE(hr); return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CINetHttp::RedirectRequest
//
// Synopsis:
//
// Arguments: [lpszBuffer] --
// [pdwBuffSize] --
//
// Returns:
//
// History: 2-06-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINetHttp::RedirectRequest(LPSTR lpszBuffer, DWORD *pdwBuffSize, DWORD dwStatus) { DEBUG_ENTER((DBG_APP, Hresult, "CINetHttp::RedirectRequest", "this=%#x, %#x, %#x, %d", this, lpszBuffer, pdwBuffSize, dwStatus )); PerfDbgLog(tagCINetHttp, this, "+CINetHttp::RedirectRequest"); HRESULT hr = INET_E_DOWNLOAD_FAILURE;
char *pszHeader; DWORD cbBufferLen; BOOL fDeleteBuffer = FALSE; BOOL fRet = FALSE; // we assume when we get here that we have recieved a redirection
// now we are going to see where we need to do the next send
cbBufferLen = *pdwBuffSize;
if (cbBufferLen <= strlen(vszLocationTag)) { goto End; } strcpy(lpszBuffer, vszLocationTag);
fRet = HttpQueryInfo(_hRequest, HTTP_QUERY_RAW_HEADERS, lpszBuffer,&cbBufferLen, NULL);
if (!fRet) { DWORD dwError = GetLastError();
if (dwError == ERROR_INSUFFICIENT_BUFFER) { lpszBuffer = new char[cbBufferLen]; if (!lpszBuffer) { hr = E_OUTOFMEMORY; goto End; } fDeleteBuffer = TRUE; fRet = HttpQueryInfo(_hRequest, HTTP_QUERY_RAW_HEADERS, lpszBuffer, &cbBufferLen, NULL); dwError = GetLastError(); } }
if (fRet) { LPSTR pszRedirect = 0; pszHeader = FindTagInHeader(lpszBuffer, vszLocationTag); if (!pszHeader) { goto End; }
//Bug 21294: 204 responses sometimes have Location: headers, which may not mean redirects.
//To prevent a bogus redirection message, ensure that the comparison with wininet's url
//is made after stripping username and password from the original url, since wininet returns
//the url without these.
//Don't make this check if it's one of the 3** or username/password not in url.
if ((dwStatus < HTTP_STATUS_AMBIGUOUS) && (_pszUserName[0] || _pszPassword[0])) { CHAR* szUrlmonUrl = new CHAR[INTERNET_MAX_URL_LENGTH]; CHAR* szWininetUrl = new CHAR[INTERNET_MAX_URL_LENGTH]; DWORD dwUrlmonSize = INTERNET_MAX_URL_LENGTH; DWORD dwWininetSize = INTERNET_MAX_URL_LENGTH; BOOL bIdentical = FALSE; URL_COMPONENTS url; if (!szUrlmonUrl || !szWininetUrl) goto deleteUrls; memset(&url, 0, sizeof(URL_COMPONENTS)); url.dwStructSize = sizeof(url); url.lpszScheme = _pszProtocol; url.lpszHostName = _pszServerName; url.lpszUrlPath = _pszObject; url.nPort = _ipPort;
if (InternetCreateUrl(&url, 0, szUrlmonUrl, &dwUrlmonSize) && InternetQueryOption(_hRequest, INTERNET_OPTION_URL, szWininetUrl, &dwWininetSize)) { if ((dwUrlmonSize == dwWininetSize) && !strcmp(szUrlmonUrl, szWininetUrl)) { bIdentical = TRUE; } DEBUG_ENTER((DBG_APP, Bool, "CINetHttp::RedirectRequestComparison", "this=%#x, %.80q, %d, %.80q, %d", this, szUrlmonUrl, dwUrlmonSize, szWininetUrl, dwWininetSize )); DEBUG_LEAVE(bIdentical); } deleteUrls: if (szUrlmonUrl) delete [] szUrlmonUrl; if (szWininetUrl) delete [] szWininetUrl;
if (bIdentical) goto End; }
if (dwStatus < HTTP_STATUS_AMBIGUOUS) { //Bug 33662: Location: headers are only allowed to be absolute URIs
//check for relative URI and, if found, pretend doesn't exist for 2** status codes.
char* pszHostname = new char[MAX_URL_SIZE]; DWORD dwHostname = MAX_URL_SIZE; HRESULT hrTemp;
if (!pszHostname) { hr = E_OUTOFMEMORY; goto End; } hrTemp = UrlGetPartA(pszHeader + strlen(vszLocationTag), pszHostname, &dwHostname, URL_PART_HOSTNAME, 0);
delete [] pszHostname; if (FAILED(hrTemp)) { //this is a relative URI since hostname couldn't be found.
//hr remains INET_E_DOWNLOAD_FAILURE
goto End; } } //
// _pszPartURL get allocated here!
//
if( _pszPartURL ) { delete [] _pszPartURL; _pszPartURL = NULL; }
DWORD dwPartUrlLen = strlen( (pszHeader + strlen(vszLocationTag) ) ); if( dwPartUrlLen > MAX_URL_SIZE) { hr = INET_E_DOWNLOAD_FAILURE; goto End; }
_pszPartURL = new char[dwPartUrlLen + 1]; if( !_pszPartURL ) { hr = E_OUTOFMEMORY; goto End; }
strcpy(_pszPartURL, pszHeader + strlen(vszLocationTag));
DbgLog1(DEB_PROT|DEB_TRACE, this, "=== CINetHttp::RedirectRequest (Location:%s)", _pszPartURL);
_fRedirected = TRUE; hr = S_FALSE;
if (!ParseUrl()) { pszRedirect = _pszPartURL; } else { pszRedirect = _pszFullURL; }
PProtAssert((pszRedirect)); ReportResultAndStop(INET_E_REDIRECTING, 0, 0, DupA2W(pszRedirect)); } End: if (fDeleteBuffer) delete lpszBuffer; PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::RedirectRequest(hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINetHttp::ErrorHandlingRequest
//
// Synopsis:
//
// Arguments: [dwstatus] --
// [szBuffer] --
//
// Returns:
//
// History: 2-28-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINetHttp::ErrorHandlingRequest(DWORD dwStatus, LPSTR szBuffer) { DEBUG_ENTER((DBG_APP, Hresult, "CINetHttp::ErrorHandlingRequest", "this=%#x, %#x, %.80q", this, dwStatus, szBuffer )); PerfDbgLog1(tagCINetHttp, this, "+CINetHttp::ErrorHandlingRequest (dwStatus:%ld)", dwStatus); HRESULT hr = NOERROR;
PProtAssert((szBuffer)); hr = HttpNegOnError(dwStatus,szBuffer);
if (hr == E_RETRY) { _hrINet = NOERROR; hr = INetAsyncSendRequest(); } else if (hr == E_ABORT) { _hrINet = E_ABORT; } else if (hr == S_FALSE) { // the error was not handled - stop download
_hrINet = hr = HResultFromHttpStatus(dwStatus); } else { _hrINet = hr; }
PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::ErrorHandlingRequest(hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINetHttp::GetVerb
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 2-05-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
LPSTR CINetHttp::GetVerb() { DEBUG_ENTER((DBG_APP, String, "CINetHttp::GetVerb", "this=%#x", this )); PerfDbgLog(tagCINetHttp, this, "+CINetHttp::GetVerb"); LPSTR pszRes = vszGet;
if (_fRedirected == TRUE) { // for HTTP 1.1, we have to check if this is an POST->POST redirect
INTERNET_VERSION_INFO httpVersion; DWORD dwBufferSize = sizeof(INTERNET_VERSION_INFO); if( InternetQueryOption( _hRequest, INTERNET_OPTION_HTTP_VERSION, &httpVersion, &dwBufferSize ) && httpVersion.dwMajorVersion >= 1 && httpVersion.dwMinorVersion >= 1 ) { CHAR szVerb[16]; DWORD dwIndex; DWORD dwLength = sizeof(szVerb); if( HttpQueryInfo(_hRequest, HTTP_QUERY_REQUEST_METHOD, szVerb, &dwLength, &dwIndex) && !lstrcmp(szVerb, vszPost) ) { // HACK HACK HACK !!
// Double check the status code to see if this is a real POST
// there is a HttpQueryInfo() bug which will send verb=POST
// on a POST->GET Redirect
//
DWORD dwStatus = 0; if ( HttpQueryInfo( _hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwStatus ,&dwLength, NULL) && dwStatus == HTTP_STATUS_REDIRECT_KEEP_VERB ) { _fP2PRedirected = TRUE; pszRes = vszPost; } } } } else { BINDINFO *pBndInfo = GetBindInfo();
if (pBndInfo) { switch (pBndInfo->dwBindVerb) { case BINDVERB_GET : pszRes = vszGet; break; case BINDVERB_POST : pszRes = vszPost; break; case BINDVERB_PUT : pszRes = vszPut; break; case BINDVERB_CUSTOM : { //BUGBUG: custom verb support
if (!_pszVerb && pBndInfo->szCustomVerb) { pszRes = _pszVerb = DupW2A(pBndInfo->szCustomVerb); } else if(_pszVerb) { pszRes = _pszVerb; } } break; } } }
PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::GetVerb (szRes:%s)", pszRes);
DEBUG_LEAVE(pszRes); return pszRes; }
//+---------------------------------------------------------------------------
//
// Method: CINetHttp::GetAdditionalHeader
//
// Synopsis:
//
// Arguments: [ppszRes] --
// [pdwSize] --
//
// Returns:
//
// History: 2-05-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINetHttp::GetAdditionalHeader() { DEBUG_ENTER((DBG_APP, Hresult, "CINetHttp::GetAdditionalHeader", "this=%#x", this )); PerfDbgLog(tagCINetHttp, this, "+CINetHttp::GetAdditionalHeader");
DWORD dwSizeData = 0; DWORD dwSizeHeader = 0; LPSTR szLocal;
szLocal = g_pszUAInfoString;
dwSizeHeader += strlen(szLocal);
ULONG dwSizeEncHeader = 0;
PProtAssert((_pOIBindInfo)); // only send Accept-Encoding header with HTTP 1.1 or higher
INTERNET_VERSION_INFO httpVersion; DWORD dwBufferSize = sizeof(INTERNET_VERSION_INFO); if( _hRequest && _pOIBindInfo && InternetQueryOption( _hRequest, INTERNET_OPTION_HTTP_VERSION, &httpVersion, &dwBufferSize ) && httpVersion.dwMajorVersion >= 1 && httpVersion.dwMinorVersion >= 1 ) { dwSizeEncHeader = 1; dwSizeHeader += strlen(gszAcceptEncHeaders); }
// delete the old header and allocate a new buffer
if (_pszHeader) { delete _pszHeader; _pszHeader = 0; }
if (dwSizeHeader || dwSizeEncHeader) { _pszHeader = new CHAR [dwSizeHeader + 1]; }
if (_pszHeader) { if (szLocal && szLocal[0] != 0) { strcat(_pszHeader, szLocal); }
if( dwSizeEncHeader) { strcat(_pszHeader, gszAcceptEncHeaders); } }
PerfDbgLog2(tagCINetHttp, this, "-CINetHttp::GetAdditionalHeader (pStr:>%s<, hr:%lx)", XDBG(_pszHeader,""), NOERROR);
DEBUG_LEAVE(NOERROR); return NOERROR; }
//+---------------------------------------------------------------------------
//
// Method: CINetHttp::GetDataToSend
//
// Synopsis:
//
// Arguments: [ppBuffer] --
// [pdwSize] --
//
// Returns:
//
// History: 2-05-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINetHttp::GetDataToSend(LPVOID *ppBuffer, DWORD *pdwSize) { DEBUG_ENTER((DBG_APP, Hresult, "CINetHttp::GetDataToSend", "this=%#x, %#x, %#x", this, ppBuffer, pdwSize )); HRESULT hr = INET_E_DOWNLOAD_FAILURE; PerfDbgLog(tagCINetHttp, this, "+CINetHttp::GetDataToSend");
*ppBuffer = NULL; *pdwSize = 0; BINDINFO *pBndInfo = GetBindInfo();
if (pBndInfo) { switch (pBndInfo->dwBindVerb) { default: case BINDVERB_CUSTOM : case BINDVERB_POST : case BINDVERB_PUT : { if (pBndInfo->stgmedData.tymed == TYMED_HGLOBAL) { *ppBuffer = pBndInfo->stgmedData.hGlobal; *pdwSize = pBndInfo->cbstgmedData; hr = NOERROR; } } break; case BINDVERB_GET : // nothing should be uploaded
break; } }
PerfDbgLog3(tagCINetHttp, this, "-CINetHttp::GetDataToSend (pBuffer:%lx, dwSize:%ld, hr:%lx)", *ppBuffer, *pdwSize, hr);
DEBUG_LEAVE(hr); return hr; }
HRESULT CINetHttp::HttpNegGetRootSecurityId() { HRESULT hr = NOERROR; BYTE bRootSID[MAX_SIZE_SECURITY_ID];
if (_pbRootSecurityId == NULL) { if (_pHttpNeg2 == NULL) { /*
if (_pHttpNeg == NULL) hr = QueryService(IID_IHttpNegotiate, (void **) &_pHttpNeg); if (!_pHttpNeg || (hr != NOERROR)) goto End; */ hr = QueryService(IID_IHttpNegotiate2, (void **) &_pHttpNeg2); if (!_pHttpNeg2) { _pbRootSecurityId = INVALID_P_ROOT_SECURITY_ID; goto End; } }
_cbRootSecurityId = MAX_SIZE_SECURITY_ID; hr = _pHttpNeg2->GetRootSecurityId( bRootSID, &_cbRootSecurityId, 0 );
if (FAILED(hr)) { _pbRootSecurityId = INVALID_P_ROOT_SECURITY_ID; goto End; } if (_cbRootSecurityId <= 0) goto End; _pbRootSecurityId = new BYTE[_cbRootSecurityId]; if (!_pbRootSecurityId) goto End;
memcpy (_pbRootSecurityId, bRootSID, _cbRootSecurityId); } End: return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINetHttp::HttpNegBeginningTransaction
//
// Synopsis:
//
// Arguments: [szURL] --
// [DWORD] --
// [dwReserved] --
// [pszAdditionalHeaders] --
//
// Returns:
//
// History: 2-08-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINetHttp::HttpNegBeginningTransaction() { DEBUG_ENTER((DBG_APP, Hresult, "CINetHttp::HttpNegBeginningTransaction", "this=%#x", this )); PerfDbgLog(tagCINetHttp, this, "+CINetHttp::HttpNegBeginningTransaction"); HRESULT hr = NOERROR; LPWSTR pwzAddHeaders = NULL;
if (_pHttpNeg == NULL) { hr = QueryService(IID_IHttpNegotiate, (void **) &_pHttpNeg); } if (_pHttpNeg && (hr == NOERROR)) { LPWSTR pwzUrl = GetUrl(); LPWSTR pwzHeaders = NULL; DWORD dwlen = 0; if (_pszHeader) { dwlen = strlen(_pszHeader); pwzHeaders = new WCHAR [dwlen +1]; if (pwzHeaders == NULL) { hr = E_OUTOFMEMORY; goto End;
} A2W(_pszHeader, pwzHeaders,dwlen + 1);
}
PProtAssert((pwzUrl)); hr = _pHttpNeg->BeginningTransaction(pwzUrl, pwzHeaders, NULL, &pwzAddHeaders);
if (SUCCEEDED(hr) ) { if (pwzAddHeaders) { // add the additional length
dwlen += wcslen(pwzAddHeaders) * sizeof(WCHAR); }
if (dwlen) {
if (_pszSendHeader) { if (strlen(_pszSendHeader) < (dwlen + 1)) { // delete the old header
delete _pszSendHeader; // allocate a new one
_pszSendHeader = new CHAR [dwlen + 1]; } } else { _pszSendHeader = new CHAR [dwlen + 1]; }
if (_pszSendHeader) { if ( pwzAddHeaders ) { W2A(pwzAddHeaders, _pszSendHeader, dwlen + 1);
// append the original header
if (_pszHeader) { strcat(_pszSendHeader,_pszHeader); } } else { // no additional header
strcpy(_pszSendHeader, _pszHeader); } } else { hr = E_OUTOFMEMORY; }
// delete the wchar header
if (pwzHeaders) { delete pwzHeaders; } } }
} else { PProtAssert((_pHttpNeg == NULL)); }
End:
// delete this buffer
if (pwzAddHeaders) { delete pwzAddHeaders; }
PerfDbgLog(tagCINetHttp, this, "-CINetHttp::HttpNegBeginningTransaction");
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINetHttp::HttpNegOnHeadersAvailable
//
// Synopsis:
//
// Arguments: [dwResponseCode] --
// [szHeaders] --
//
// Returns:
//
// History: 2-08-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINetHttp::HttpNegOnHeadersAvailable(DWORD dwResponseCode, LPSTR szResponseHeader) { DEBUG_ENTER((DBG_APP, Hresult, "CINetHttp::HttpNegOnHeadersAvailable", "this=%#x, %#x, %.80q", this, dwResponseCode, szResponseHeader )); PerfDbgLog2(tagCINetHttp, this, "+CINetHttp::HttpNegOnHeadersAvailable (dwResponseCode:%lx) (szResponseHeader:%s)", dwResponseCode, XDBG(szResponseHeader,"")); HRESULT hr = NOERROR;
PProtAssert((szResponseHeader != NULL));
if (_pHttpNeg) {
LPWSTR pwzResponseHeader; DWORD dwlen = strlen(szResponseHeader);
pwzResponseHeader = new WCHAR [dwlen +1]; if (pwzResponseHeader == NULL) { hr = E_OUTOFMEMORY; } else { PProtAssert((pwzResponseHeader)); A2W(szResponseHeader, pwzResponseHeader, dwlen + 1); if( _pHttpNeg ) { hr = _pHttpNeg->OnResponse(dwResponseCode, pwzResponseHeader,NULL ,NULL); }
// the only valid return code is NOERROR
PProtAssert((hr == NOERROR && "HttpNegotiate::OnHeaders returned ivalid hresult")); PProtAssert((pwzResponseHeader));
delete pwzResponseHeader; } }
PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::HttpNegOnHeadersAvailable (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINetHttp::HttpNegOnError
//
// Synopsis:
//
// Arguments: [dwResponseCode] --
// [szResponseHeaders] --
// [pszAdditionalRequestHeaders] --
//
// Returns:
//
// History: 2-08-96 JohannP (Johann Posch) Created
//
// Notes: return S_FALSE as default - will stop download
// and map to INET_E hresult
//----------------------------------------------------------------------------
HRESULT CINetHttp::HttpNegOnError(DWORD dwResponseCode, LPSTR szResponseHeader) { DEBUG_ENTER((DBG_APP, Hresult, "CINetHttp::HttpNegOnError", "this=%#x, %#x, %.80q", this, dwResponseCode, szResponseHeader )); PerfDbgLog(tagCINetHttp, this, "+CINetHttp::HttpNegOnError"); HRESULT hr = S_FALSE;
PProtAssert((szResponseHeader != NULL));
if (_pHttpNeg) { LPWSTR pwzNewSendHeader = 0; LPWSTR pwzSendHeader = 0; LPWSTR pwzResponseHeader = 0; DWORD dwLenSendHeader = 0; DWORD dwLenResponseHeader = 0;
if (_pszSendHeader) { dwLenSendHeader = strlen(_pszSendHeader); pwzSendHeader = new WCHAR [dwLenSendHeader + 1]; }
if (pwzSendHeader) { A2W(_pszSendHeader, pwzSendHeader, dwLenSendHeader + 1); }
if (szResponseHeader) { dwLenResponseHeader = strlen(szResponseHeader); pwzResponseHeader = new WCHAR [dwLenResponseHeader + 1]; }
if (pwzResponseHeader) { A2W(szResponseHeader, pwzResponseHeader, dwLenResponseHeader + 1); }
if( _pHttpNeg ) { hr = _pHttpNeg->OnResponse(dwResponseCode, pwzResponseHeader,pwzSendHeader ,&pwzNewSendHeader); }
if (pwzSendHeader) { delete pwzSendHeader; pwzSendHeader = 0; }
if (pwzResponseHeader) { delete pwzResponseHeader; pwzResponseHeader = 0; }
if ((hr == NOERROR) && (pwzNewSendHeader != NULL)) { LPSTR pszNewSendHeader = 0; DWORD dwLen = wcslen(pwzNewSendHeader); DWORD dwLen1 = 0; if (_pszSendHeader) { dwLen1 = strlen(_pszSendHeader); PProtAssert((dwLen + dwLen1));
pszNewSendHeader = new CHAR [dwLen + dwLen1 + 1];
if (pszNewSendHeader) { strcpy(pszNewSendHeader, _pszSendHeader); W2A(pwzNewSendHeader,pszNewSendHeader + dwLen1, dwLen + 1);
// retry the call
hr = E_RETRY; } else { hr = E_OUTOFMEMORY; } } else { hr = S_FALSE; } } else { // we should not have headers
PProtAssert((pwzNewSendHeader == NULL)); if (pwzNewSendHeader) { delete pwzNewSendHeader; } } } else { // the error should be mapped to an INET_E hresult
hr = S_FALSE; }
PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::HttpNegOnError (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::SecurityProblem
//
// Synopsis:
//
// Arguments: [lpszBuffer] --
// [pdwBuffSize] --
//
// Returns:
//
// History: 2-06-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINetHttp::HttpSecurity(DWORD dwProblem) { DEBUG_ENTER((DBG_APP, Hresult, "CINetHttp::HttpSecurity", "this=%#x, %#x", this, dwProblem )); PerfDbgLog(tagCINetHttp, this, "+CINetHttp::HttpSecurity"); HRESULT hr = NOERROR; HWND hwnd;
hr = HttpSecurityProblem(&hwnd, dwProblem);
if (hr == NOERROR) { if (hwnd) { DWORD dwBindF = GetBindFlags(); DWORD dwFlags = (FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA );
if ((dwBindF & BINDF_NO_UI) || (dwBindF & BINDF_SILENTOPERATION)) { dwFlags |= FLAGS_ERROR_UI_FLAGS_NO_UI; }
DWORD dwError;
if (SUCCEEDED(ZonesSecurityCheck(hwnd, dwProblem, &dwError))) { // dwError will be set by ZonesSecurityCheck.
} else { dwError = InternetErrorDlg(hwnd, _hRequest, dwProblem, dwFlags,NULL); }
switch (dwError) { case ERROR_CANCELLED : _hrINet = hr = E_ABORT; break;
case ERROR_SUCCESS : _hrINet = hr = E_RETRY; break;
default: _hrINet = hr = E_ABORT; break; } } else { hr = INET_E_SECURITY_PROBLEM; } } else if (hr == E_ABORT) { _hrINet = E_ABORT; }
if (hr == E_RETRY) { _hrINet = NOERROR; hr = INetAsyncSendRequest(); } else if (hr == E_ABORT) { _hrINet = E_ABORT; } else if (hr != NOERROR ) { // set the error to access denied
_hrINet = hr = INET_E_SECURITY_PROBLEM; }
PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::HttpSecurity(hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::ZonesSecurityCheck
//
// Synopsis:
//
// Arguments: [hwnd] --
// [dwProblem] --
// [pdwError] --
//
// Returns: SUCCESS if it was able to decide the action, INET_E_DEFAULT_ACTION otherwise.
//
// History: 8-14-97 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINetHttp::ZonesSecurityCheck(HWND hWnd, DWORD dwProblem, DWORD *pdwError) { DEBUG_ENTER((DBG_APP, Hresult, "CINetHttp::ZonesSecurityCheck", "this=%#x, %#x, %#x, %#x", this, hWnd, dwProblem, pdwError )); PerfDbgLog(tagCINetHttp, this, "+CINetHttp::HttpSecurity"); HRESULT hr = INET_E_DEFAULT_ACTION;
if (pdwError == NULL) { TransAssert(FALSE);
DEBUG_LEAVE(E_INVALIDARG); return E_INVALIDARG; }
// Right now the only error we check for is the redirect confirmation error.
if (dwProblem == ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION || dwProblem == ERROR_INTERNET_HTTPS_HTTP_SUBMIT_REDIR) { IInternetSecurityManager *pSecMgr = NULL;
if (SUCCEEDED(CoCreateInstance(CLSID_InternetSecurityManager, NULL, CLSCTX_INPROC_SERVER, IID_IInternetSecurityManager, (void **)&pSecMgr))) { char szUrl[MAX_URL_SIZE]; WCHAR wzUrl[MAX_URL_SIZE]; DWORD cbLen = MAX_URL_SIZE; DWORD dwPolicy;
TransAssert(pSecMgr != NULL);
InternetQueryOption(_hRequest, INTERNET_OPTION_URL, szUrl, &cbLen);
// First check if the redirect is to the same server. If that is the
// case we don't need to warn because we already did the first time around.
if (dwProblem == ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION) { URL_COMPONENTS uc = { 0 };
uc.dwStructSize = sizeof(uc); uc.dwHostNameLength = 1; // So we get back the host name.
if ( InternetCrackUrl(szUrl, 0, 0, &uc) && (StrCmpNI(uc.lpszHostName, GetServerName(), uc.dwHostNameLength) == 0) ) { *pdwError = ERROR_SUCCESS; hr = S_OK; } } if (hr == INET_E_DEFAULT_ACTION) { // Convert to widechar so we can call the security manager.
MultiByteToWideChar(CP_ACP, 0, szUrl, -1, wzUrl, MAX_URL_SIZE);
PARSEDURL pu; pu.cbSize = sizeof(pu);
DWORD dwPUAflags = (GetBindFlags() & BINDF_ENFORCERESTRICTED) ? PUAF_ENFORCERESTRICTED : 0; if (SUCCEEDED(ParseURLA(szUrl, &pu)) && pu.nScheme == URL_SCHEME_HTTPS) { // The forms submit zones policies are only supposed to apply to
// unencrypted posts. We will allow these to be posted silently.
*pdwError = ERROR_SUCCESS; hr = S_OK ; } else if (SUCCEEDED(pSecMgr->ProcessUrlAction(wzUrl, URLACTION_HTML_SUBMIT_FORMS_TO, (BYTE *)&dwPolicy, sizeof(dwPolicy), NULL, 0, dwPUAflags | PUAF_NOUI, 0))) { DWORD dwPermissions = GetUrlPolicyPermissions(dwPolicy); // If it is allow or deny don't call InternetErrorDlg, unless it is a encrypted to
// unencrypted redir in which case we still need to warn the user..
if (dwPermissions == URLPOLICY_ALLOW && dwProblem != ERROR_INTERNET_HTTPS_HTTP_SUBMIT_REDIR) { *pdwError = ERROR_SUCCESS; hr = S_OK; } else if (dwPermissions == URLPOLICY_DISALLOW) { *pdwError = ERROR_CANCELLED; hr = S_OK; } } }
pSecMgr->Release(); } }
PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::ZonesSecurityCheck(hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINetHttp::HttpSecurityProblem
//
// Synopsis: QI's for HttpSecurity or IWindow
//
// Arguments: [phwnd] -- window handle for security dialog
//
// Returns: S_OK if dialog should be displayed
//
// History: 2-08-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINetHttp::HttpSecurityProblem(HWND* phwnd, DWORD dwProblem) { DEBUG_ENTER((DBG_APP, Hresult, "CINetHttp::HttpSecurityProblem", "this=%#x, %#x, %#x", this, phwnd, dwProblem )); PerfDbgLog(tagCINetHttp, this, "+CINetHttp::HttpSecurityProblem"); HRESULT hr = NOERROR; *phwnd = 0;
if (_pHttSecurity == NULL) { hr = QueryService(IID_IHttpSecurity, (void **) &_pHttSecurity); }
if ((hr == NOERROR) && _pHttSecurity) { hr = _pHttSecurity->OnSecurityProblem(dwProblem); if (hr == S_OK) { // client wants to continue
} else if (hr == S_FALSE) { // client does not care
hr = _pHttSecurity->GetWindow(IID_IHttpSecurity, phwnd); UrlMkAssert(( ((hr == S_FALSE) && (*phwnd == NULL)) || ((hr == NOERROR) && (*phwnd != NULL)) )); } else if (hr != E_ABORT) { UrlMkAssert((FALSE && "Invalid result on IHttSecurity->OnSecurityProblem")); } } else { if (_pWindow == NULL) { hr = QueryService(IID_IWindowForBindingUI, (void **) &_pWindow); } else hr = NOERROR; //We need to reset this hr, since we cached _pWindow
if ((hr == NOERROR) && _pWindow) { hr = _pWindow->GetWindow(IID_IHttpSecurity, phwnd); UrlMkAssert(( (hr == S_FALSE) && (*phwnd == NULL) || (hr == S_OK) && (*phwnd != NULL))); } }
PerfDbgLog2(tagCINetHttp, this, "-CINetHttp::HttpSecurityProblem (hr:%lx, hwnd:%lx)", hr, *phwnd);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINetHttp::HResultFromInternetError
//
// Synopsis:
//
// Arguments: [dwStatus] --
//
// Returns:
//
// History: 3-22-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINetHttp::HResultFromHttpStatus(DWORD dwStatus) { DEBUG_ENTER((DBG_APP, Hresult, "CINetHttp::HResultFromHttpStatus", "this=%#x, %#x", this, dwStatus )); PerfDbgLog(tagCINetHttp, this, "+CINetHttp::HResultFromHttpStatus"); HRESULT hr = NOERROR; switch(dwStatus) { case HTTP_STATUS_OK : case HTTP_STATUS_NOT_MODIFIED : case HTTP_STATUS_RETRY_WITH : hr = NOERROR; break;
case HTTP_STATUS_NOT_FOUND : hr = INET_E_OBJECT_NOT_FOUND; break;
case HTTP_STATUS_NONE_ACCEPTABLE : // comes back if server can not handle mime type
hr = INET_E_NO_VALID_MEDIA; break;
case HTTP_STATUS_SERVICE_UNAVAIL : hr = INET_E_INVALID_REQUEST; break;
case HTTP_STATUS_GATEWAY_TIMEOUT : case HTTP_STATUS_REQUEST_TIMEOUT : hr = INET_E_CONNECTION_TIMEOUT; break;
case HTTP_STATUS_CREATED : case HTTP_STATUS_ACCEPTED : case HTTP_STATUS_PARTIAL : case HTTP_STATUS_NO_CONTENT : case HTTP_STATUS_AMBIGUOUS : case HTTP_STATUS_MOVED : case HTTP_STATUS_REDIRECT : case HTTP_STATUS_REDIRECT_METHOD : case HTTP_STATUS_REDIRECT_KEEP_VERB: case HTTP_STATUS_BAD_REQUEST : case HTTP_STATUS_DENIED : case HTTP_STATUS_PAYMENT_REQ : case HTTP_STATUS_FORBIDDEN : case HTTP_STATUS_BAD_METHOD : case HTTP_STATUS_PROXY_AUTH_REQ : case HTTP_STATUS_CONFLICT : case HTTP_STATUS_GONE : case HTTP_STATUS_LENGTH_REQUIRED : case HTTP_STATUS_SERVER_ERROR : case HTTP_STATUS_NOT_SUPPORTED : case HTTP_STATUS_BAD_GATEWAY : default: //PProtAssert((FALSE && "Mapping Ineternet error to generic hresult!"));
hr = INET_E_DOWNLOAD_FAILURE; DbgLog2(DEB_PROT|DEB_TRACE, this, "=== Mapping Internet error to generic hresult!(dwStatus:%ld, hr:%lx)", dwStatus, hr); break; }
PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::HResultFromHttpStatus (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINetHttp::Terminate
//
// Synopsis: Close the server and request handle - wininet will make a
// callback on each handle closed
//
// Arguments: [dwOptions] --
//
// Returns:
//
// History: 07-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CINetHttp::Terminate(DWORD dwOptions) { DEBUG_ENTER((DBG_APP, Hresult, "CINetHttp::Terminate", "this=%#x, %#x", this, dwOptions )); PerfDbgLog(tagCINetHttp, this, "+CINetHttp::Terminate"); HRESULT hr = NOERROR; //PProtAssert(( IsApartmentThread() ));
if (_pHttpNeg) { PerfDbgLog1(tagCINetHttp, this, "=== CINetHttp::Terminate Release on _pHttpNeg (%lx)", _pHttpNeg); _pHttpNeg->Release(); _pHttpNeg = NULL; } if (_pHttpNeg2) { PerfDbgLog1(tagCINetHttp, this, "=== CINetHttp::Terminate Release on _pHttpNeg2 (%lx)", _pHttpNeg2); _pHttpNeg2->Release(); _pHttpNeg2 = NULL; } if (_pWindow) { PerfDbgLog1(tagCINetHttp, this, "+CINetHttp::Terminate Release on _pWindow (%lx)", _pWindow); _pWindow->Release(); _pWindow = NULL; }
if (_pHttSecurity) { PerfDbgLog1(tagCINetHttp, this, "+CINetHttp::Terminate Release on _pHttSecurity (%lx)", _pHttSecurity); _pHttSecurity->Release(); _pHttSecurity = NULL; }
hr = CINet::Terminate(dwOptions);
PerfDbgLog1(tagCINetHttp, this, "-CINetHttp::Terminate (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINetHttpS::CINetHttpS
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 2-06-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
CINetHttpS::CINetHttpS(REFCLSID rclsid, IUnknown *pUnkOuter) : CINetHttp(rclsid,pUnkOuter) { DEBUG_ENTER((DBG_APP, None, "CINetHttpS::CINetHttpS", "this=%#x, %#x, %#x", this, &rclsid, pUnkOuter )); PerfDbgLog(tagCINetHttp, this, "+CINetHttpS::CINetHttpS");
_dwIsA = DLD_PROTOCOL_HTTPS; _dwConnectFlags = INTERNET_FLAG_SECURE; _dwOpenFlags = INTERNET_FLAG_SECURE;
PerfDbgLog(tagCINetHttp, this, "-CINetHttpS::CINetHttpS");
DEBUG_LEAVE(0); }
//+---------------------------------------------------------------------------
//
// Method: CINetHttpS::~CINetHttpS
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 2-06-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
CINetHttpS::~CINetHttpS() { DEBUG_ENTER((DBG_APP, None, "CINetHttpS::~CINetHttpS", "this=%#x", this )); PerfDbgLog(tagCINetHttp, this, "+CINetHttpS::~CINetHttpS");
PerfDbgLog(tagCINetHttp, this, "-CINetHttpS::~CINetHttpS");
DEBUG_LEAVE(0); }
//+---------------------------------------------------------------------------
//
// Method: CINetHttp::INetWrite
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINetHttp::INetWrite() { DEBUG_ENTER((DBG_APP, Hresult, "CINetHttp::INetWrite", "this=%#x", this )); TransDebugOut((DEB_PROT, "%p OUT CINetHttp::INetWrite\n", this)); HRESULT hr = NOERROR;
BOOL fRet; DWORD dwSendFlags = HSR_CHUNKED | HSR_INITIATE; DWORD dwSendContext = 0;
// If our caller gave us a TYMED_ISTREAM, then we need to pick it up
// now.
if (!_pStm) { BINDINFO *pBI = GetBindInfo(); if (pBI && pBI->stgmedData.tymed == TYMED_ISTREAM) { _pStm = pBI->stgmedData.pstm; } }
TransAssert((_pStm)); if( _fSendAgain && _pStm ) { LARGE_INTEGER li; li.LowPart = 0; li.HighPart = 0; hr = _pStm->Seek(li, STREAM_SEEK_SET, NULL); if( SUCCEEDED(hr) ) { _fSendEnd = FALSE; } else { _fCompleted = TRUE; }
_fSendAgain = FALSE; }
// loop until pending
if (_fSendEnd) { _hrError = INET_E_DONE; } else do { _dwBytesSent = 0;
SetStatePending(E_PENDING);
hr = GetNextSendBuffer(&_inetBufferSend,_pStm); if (FAILED(hr)) { break; }
if (hr == S_FALSE) { // end of stream
_fCompleted = TRUE; }
if (!_fCompleted) { if (_inetBufferSend.dwBufferLength) { fRet = InternetWriteFile( _hRequest //IN HINTERNET hFile,
,_inetBufferSend.lpvBuffer //IN LPCVOID lpBuffer,
,_inetBufferSend.dwBufferLength //IN DWORD dwNumberOfBytesToWrite,
,&_dwBytesSent //OUT LPDWORD lpdwNumberOfBytesWritten
); } else { fRet = TRUE; } } else { fRet = HttpEndRequestA( _hRequest //IN HINTERNET hRequest,
,NULL ,dwSendFlags //IN DWORD dwFlags,
,dwSendContext //IN DWORD dwContext
);
_fSendEnd = TRUE; }
//PerfDbgLog(tagCINetHttp, this, "-CINetHttp::INetAsyncSendRequest HttpSendRequest");
if (fRet == FALSE) { DWORD dwLstError = GetLastError(); if (dwLstError == ERROR_IO_PENDING) { // wait async for the handle
hr = E_PENDING; } else { SetStatePending(NOERROR); hr = _hrError = INET_E_DOWNLOAD_FAILURE; SetBindResult(dwLstError,hr); //PerfDbgLog3(tagCINetHttp, this, "CINetHttp::INetAsyncSendRequest (fRet:%d, _hrError:%lx, LstError:%ld)", fRet, _hrError, dwLstError);
} } else { SetStatePending(NOERROR); }
} while ((fRet == TRUE) && (_fCompleted == FALSE));
if (_hrError != INET_E_OK) { // we need to terminate here
ReportResultAndStop((_hrError == INET_E_DONE) ? NOERROR : _hrError); }
TransDebugOut((DEB_PROT, "%p OUT CINetHttp::INetWrite (hr:%lx)\n", this, hr));
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINetHttp::GetNextSendBuffer
//
// Synopsis:
//
// Arguments: [pIB] --
// [pStm] --
// [fFirst] --
//
// Returns:
//
// History: 4-28-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINetHttp::GetNextSendBuffer(INTERNET_BUFFERS *pIB, IStream *pStm, BOOL fFirst) { DEBUG_ENTER((DBG_APP, Hresult, "CINetHttp::GetNextSendBuffer", "this=%#x, %#x, %#x, %B", this, pIB, pStm, fFirst )); TransDebugOut((DEB_PROT, "%p OUT CINetHttp::GetNextSendBuffer\n", this)); HRESULT hr = NOERROR;
TransAssert(pIB);
do { BINDINFO *pBndInfo = GetBindInfo(); DWORD dwBufferFilled = 0;
if (!pStm) { hr = E_FAIL; break; }
if (!fFirst) { TransAssert((_pBuffer)); hr = pStm->Read(_pBuffer, _dwBufferSize, &dwBufferFilled);
if (FAILED(hr)) { break; } else if (!dwBufferFilled) { hr = S_FALSE; } } else { LARGE_INTEGER li; li.LowPart = 0; li.HighPart = 0;
// We do not need to addref this here
pStm->Seek(li, STREAM_SEEK_SET, NULL);
if( !_pBuffer ) { _pBuffer = new char [SENDBUFFER_MAX];
if (!_pBuffer) { hr = E_OUTOFMEMORY; break; } _dwBufferSize = SENDBUFFER_MAX; } }
pIB->dwStructSize = sizeof (INTERNET_BUFFERSA); pIB->Next = 0; pIB->lpcszHeader = (fFirst) ? _pszSendHeader : 0; pIB->dwHeadersLength = (fFirst) ? ((_pszSendHeader) ? (ULONG)-1L : 0L) : 0; pIB->dwHeadersTotal = (fFirst) ? ((_pszSendHeader) ? (ULONG)-1L : 0L) : 0; pIB->lpvBuffer = (fFirst) ? 0 : _pBuffer; pIB->dwBufferLength = (fFirst) ? 0 : dwBufferFilled; pIB->dwBufferTotal = (fFirst) ? pBndInfo->cbstgmedData : 0; // :_dwBufferSize;
pIB->dwOffsetLow = 0; pIB->dwOffsetHigh = 0;
break; } while (TRUE);
TransDebugOut((DEB_PROT, "%p OUT CINetHttp::GetNextSendBuffer (hr:%lx)\n", this, hr));
DEBUG_LEAVE(hr); return hr; }
|