//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1995. // // File: cnethttp.cxx // // Contents: // // Classes: // // Functions: // // History: 2-06-96 JohannP (Johann Posch) Created // //---------------------------------------------------------------------------- #include #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; }