|
|
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995.
//
// File: cnet.cxx
//
// Contents:
//
// Classes:
//
// Functions:
//
// History: 12-04-95 JohannP (Johann Posch) Created
//
//----------------------------------------------------------------------------
#include <iapp.h>
#include <winineti.h> // contains bogus INTERNET_FLAG_NO_UI
#include <shlwapip.h>
CMutexSem g_mxsSession; // single access to InternetOpen
PerfDbgTag(tagCINet, "Urlmon", "Log CINet", DEB_PROT); PerfDbgTag(tagCINetErr, "Urlmon", "Log CINet Errors", DEB_PROT|DEB_ERROR); LONG UrlMonInvokeExceptionFilter( DWORD lCode, LPEXCEPTION_POINTERS lpep ); DWORD StrLenMultiByteWithMlang(LPCWSTR, DWORD); BOOL ConvertUnicodeUrl(LPCWSTR, LPSTR, INT, DWORD, BOOL, BOOL*); DWORD CountUnicodeToUtf8(LPCWSTR, DWORD, BOOL); extern BOOL g_bGlobalUTF8Enabled;
#define INTERNET_POLICIES_KEY "SOFTWARE\\Policies\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
typedef UINT (WINAPI *GetSystemWow64DirectoryPtr) (LPTSTR lpBuffer, UINT uSize);
// Need this in GetUserAgentString.
HRESULT CallRegInstall(LPSTR szSection);
HRESULT EnsureSecurityManager ();
class CInetState { enum WHAT_STATE { INETSTATE_NONE = 0 ,INETSTATE_SET = 1 ,INETSTATE_HANDLED = 2 };
public: void SetState(DWORD dwState) { DEBUG_ENTER((DBG_APP, None, "CInetState::SetState", "this=%#x, %#x", this, dwState )); CLock lck(_mxs); _dwState = dwState; _What = INETSTATE_SET;
DEBUG_LEAVE(0); } HRESULT HandleState() { DEBUG_ENTER((DBG_APP, Hresult, "CInetState::HandleState", "this=%#x", this )); HRESULT hr = NOERROR; DWORD dwStateNow; BOOL fPropagate;
{ CLock lck(_mxs); dwStateNow = _dwState; fPropagate = (_What == INETSTATE_SET) ? TRUE : FALSE; _What = INETSTATE_HANDLED; }
if (fPropagate) { hr = PropagateStateChange(dwStateNow); }
DEBUG_LEAVE(hr); return hr; }
HRESULT PropagateStateChange(DWORD dwState);
CInetState() { DEBUG_ENTER((DBG_APP, None, "CInetState::CInetState", "this=%#x", this )); _dwState = 0; _What = INETSTATE_NONE;
DEBUG_LEAVE(0); }
~CInetState() { DEBUG_ENTER((DBG_APP, None, "CInetState::~CInetState", "this=%#x", this )); DEBUG_LEAVE(0); }
private: CMutexSem _mxs; DWORD _dwState; WHAT_STATE _What; };
//+---------------------------------------------------------------------------
//
// Method: CInetState::PropagateStateChange
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-22-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CInetState::PropagateStateChange(DWORD dwWhat) { DEBUG_ENTER((DBG_APP, Hresult, "CInetState::PropagateStateChange", "this=%#x, %#x", this, dwWhat )); PerfDbgLog(tagCINet, this, "+CInetState::PropagateStateChange"); HRESULT hr = NOERROR;
// BUGBUG: IE5 need to implement these!
#if 0
if (dwWhat & INTERNET_STATE_CONNECTED) { NotfDeliverNotification( NOTIFICATIONTYPE_CONNECT_TO_INTERNET // REFNOTIFICATIONTYPE rNotificationType
,CLSID_PROCESS_BROADCAST // REFCLSID rClsidDest
,(DELIVERMODE)0 // DELIVERMODE deliverMode
,0 // DWORD dwReserved
);
} if (dwWhat & INTERNET_STATE_DISCONNECTED) { NotfDeliverNotification( NOTIFICATIONTYPE_DISCONNECT_FROM_INTERNET // REFNOTIFICATIONTYPE rNotificationType
,CLSID_PROCESS_BROADCAST // REFCLSID rClsidDest
,(DELIVERMODE)0 // DELIVERMODE deliverMode
,0 // DWORD dwReserved
); } if (dwWhat & INTERNET_STATE_DISCONNECTED_BY_USER) { NotfDeliverNotification( NOTIFICATIONTYPE_CONFIG_CHANGED // REFNOTIFICATIONTYPE rNotificationType
,CLSID_PROCESS_BROADCAST // REFCLSID rClsidDest
,(DELIVERMODE)0 // DELIVERMODE deliverMode
,0 // DWORD dwReserved
);
}
#ifdef _with_idle_and_busy_
//
// NOTE: wininet will send idle with every state change
// will be fixed by RFirth
if (dwWhat & INTERNET_STATE_IDLE) { NotfDeliverNotification( NOTIFICATIONTYPE_INET_IDLE // REFNOTIFICATIONTYPE rNotificationType
,CLSID_PROCESS_BROADCAST // REFCLSID rClsidDest
,(DELIVERMODE)0 // DELIVERMODE deliverMode
,0 // DWORD dwReserved
); } if (dwWhat & INTERNET_STATE_BUSY) { NotfDeliverNotification( NOTIFICATIONTYPE_INET_BUSY // REFNOTIFICATIONTYPE rNotificationType
,CLSID_PROCESS_BROADCAST // REFCLSID rClsidDest
,(DELIVERMODE)0 // DELIVERMODE deliverMode
,0 // DWORD dwReserved
);
} #endif //_with_idle_and_busy_
#endif // 0
PerfDbgLog1(tagCINet, this, "-CInetState:PropagateStateChange (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//
// REMOVE THIS joHANNP
//
extern LPSTR g_pszUserAgentString; HINTERNET g_hSession; CInetState g_cInetState;
char vszLocationTag[] = "Location: ";
static DWORD dwLstError;
typedef struct tagProtocolInfo { LPWSTR pwzProtocol; LPSTR pszProtocol; DWORD dwId; CLSID *pClsID; int protlen; } ProtocolInfo;
extern IInternetSecurityManager* g_pSecurityManager; // to handle GetSecurityId for cookies fix.
/*
This function is not heavy on error-checking: The ASSERTS in the code MUST be satisfied for this function to work
NOTE: don't care about OPAQUE urls since they are NOT http by definition. */
enum ComparisonState { seenZone=1, seen1Dot, seen2Dots, seen3Dots, domainSame };
#define MAKELOWER(val) (((val) > 'a') ? (val) : ((val)-'A'+'a'))
BOOL IsKnown2ndSubstring(BYTE* pStart, BYTE* pEnd) { static const char *s_pachSpecialDomains[] = {"COM", "EDU", "NET", "ORG", "GOV", "MIL", "INT"}; static const DWORD s_padwSpecialDomains[] = {0x00636f6d, 0x00656475, 0x006e6574, 0x006f7267, 0x00676f76, 0x006d696c, 0x00696e74}; BOOL bKnown = FALSE; int nLen = (int) (pEnd-pStart+1);
if ((nLen==2) && !StrCmpNI((LPCSTR)pStart, "CO", nLen)) { bKnown = TRUE; } else if (nLen==3) { DWORD dwExt, dwByte;
dwByte = *pStart++; dwExt = MAKELOWER(dwByte); dwExt <<= 8; dwByte = *pStart++; dwExt |= MAKELOWER(dwByte); dwExt <<= 8; dwByte = *pStart++; dwExt |= MAKELOWER(dwByte);
for (int i=0; i<sizeof(s_padwSpecialDomains);) { if (dwExt == s_padwSpecialDomains[i++]) { bKnown = TRUE; break; } } }
return bKnown; } BOOL SecurityIdsMatch(BYTE* pbSecurityId1, DWORD dwLen1, BYTE* pbSecurityId2, DWORD dwLen2) { //ASSERT((pbSecurityId1 && pbSecurityId2 && (dwLen1 > 0) && (dwLen2 > 0)));
ComparisonState currState; BOOL bRetval = FALSE; //BOOL bRetval = ((dwLen1 == dwLen2) && (0 == memcmp(pbSecurityId1, pbSecurityId2, dwLen1)));
BYTE *pCurr1, *pCurr2; DWORD dwDomainLen1, dwDomainLen2; //sizes of securityId w/o protocol.
pCurr1 = pbSecurityId1; while(*pCurr1++ != ':'); dwDomainLen1 = (DWORD)(pCurr1-pbSecurityId1);
pCurr2 = pbSecurityId2; while(*pCurr2++ != ':'); dwDomainLen2 = (DWORD)(pCurr2-pbSecurityId2); DEBUG_ENTER((DBG_APP, Bool, "SecurityIdsMatch", "%#x, %d, domainLen=%d %#x, %d, domainLen=%d", pbSecurityId1, dwLen1, dwDomainLen1, pbSecurityId2, dwLen2, dwDomainLen2 ));
BYTE *pBase1, *pBase2; BYTE bLeftByte, bRightByte; DWORD cbSubstring1 = 0; BYTE *pSubstring2Start = NULL; BYTE *pSubstring2End = NULL; //pCurr1 is the shorter one
if (dwDomainLen1 < dwDomainLen2) { pCurr1 = pbSecurityId1+dwLen1-1-sizeof(DWORD); pBase1 = pbSecurityId1; pCurr2 = pbSecurityId2+dwLen2-1-sizeof(DWORD); pBase2 = pbSecurityId2; } else { pCurr2 = pbSecurityId1+dwLen1-1-sizeof(DWORD); pBase2 = pbSecurityId1; pCurr1 = pbSecurityId2+dwLen2-1-sizeof(DWORD); pBase1 = pbSecurityId2; } /* compare zone dword
if (memcmp(pCurr1, pCurr2, sizeof(DWORD))) goto End; */ /* compare domains */ currState = seenZone; while ((pCurr1 > pBase1) && (pCurr2 > pBase2)) { if ((bLeftByte=*pCurr1--) == (bRightByte=*pCurr2--)) { /* valid assumption? no ':' in domain name */ //ASSERT(((currState==seenZone) && (bLeftByte == ':')))
if ((bLeftByte == '.') && (currState < seen3Dots)) { currState = (ComparisonState)(currState+1); switch (currState) { case seen1Dot: pSubstring2End = pCurr1; break; case seen2Dots: pSubstring2Start = pCurr1+2; break; } } else if (bLeftByte == ':') { currState = domainSame; break; } else if (currState == seenZone) cbSubstring1++; } else break; }
switch (currState) { case seenZone: /* NOTE: this rules out http:ieinternal and http:foo.ieinternal not to be INCLUDED */ /* The alternative is to risk http:com and http:www.microsoft.com */ goto End; case seen1Dot: /* INCLUDE http:microsoft.com and http:www.microsoft.com,
( http:a.micro.com and http:b.micro.com included by seen2Dots ) EXCLUDE http:co.uk and http:www.microsoft.co.uk and all else eg. http:amicrosoft.com and http:www.microsoft.com & http:microsoft.com and http:amicrosoft.com */ if ((bLeftByte != ':') || (bRightByte != '.') || ((cbSubstring1 == 2) && IsKnown2ndSubstring(pCurr1+2, pSubstring2End))) goto End; break; case seen2Dots: /* INCLUDE http:ood.microsoft.com and http:food.microsoft.com
INCLUDE http:a.co.uk and http:b.a.co.uk EXCLUDE http:www.microsoft.co.uk and http:www.amicrosoft.co.uk */ if ((cbSubstring1 == 2) && IsKnown2ndSubstring(pSubstring2Start, pSubstring2End) && ((bLeftByte != ':') || (bRightByte != '.'))) goto End; break; case seen3Dots: /* INCLUDES all cases including
http:food.microsoft.co.uk and http:drink.microsoft.co.uk */ case domainSame: /* INCLUDES all equal domain cases of all substring sizes, including intranet sites */ break; }
/* no longer compare the protocols.
if we get to this point, then the SecurityId's match. */ bRetval = TRUE; End: DEBUG_LEAVE(bRetval);
return bRetval; }
BOOL SecurityIdContainsScheme(BYTE* pbSecurityId, DWORD dwLen) { BYTE* pCurr = pbSecurityId; BOOL fRet = TRUE;
while ( (DWORD)(pCurr-pbSecurityId) < dwLen ) { if (*pCurr++ == ':') { goto End; break; } } fRet = FALSE;
End: return fRet; } //returns S_OK if they match,
// S_FALSE if they don't ( i.e. THIRD PARTY )
STDAPI CompareSecurityIds(BYTE* pbSecurityId1, DWORD dwLen1, BYTE* pbSecurityId2, DWORD dwLen2, DWORD dwReserved) { DEBUG_ENTER((DBG_APP, Hresult, "CompareSecurityIds", "%#x, %#x, %#x, %#x, %#x", pbSecurityId1, dwLen1, pbSecurityId2, dwLen2, dwReserved )); HRESULT hr = E_INVALIDARG; BOOL fRet;
//parameter validation
if ((dwLen1 <= 0) || (!pbSecurityId1) || (dwLen2 <= 0) || (!pbSecurityId2)) goto End;
if (!SecurityIdContainsScheme(pbSecurityId1, dwLen1) || !SecurityIdContainsScheme(pbSecurityId2, dwLen2)) goto End;
fRet = SecurityIdsMatch(pbSecurityId1, dwLen1, pbSecurityId2, dwLen2);
if (fRet == TRUE) hr = S_OK; else hr = S_FALSE; End: DEBUG_LEAVE(hr); return hr; }
BOOL CINet::IsThirdPartyUrl(LPCWSTR pwszUrl) { DEBUG_ENTER((DBG_APP, Bool, "CINet::IsThirdPartyUrl", "this=%#x, %.80wq", this, pwszUrl )); BOOL bRetval = TRUE; // be safe or sorry?
HRESULT hr = NOERROR; BYTE bSID[MAX_SIZE_SECURITY_ID]; DWORD cbSID = MAX_SIZE_SECURITY_ID;
if(!SUCCEEDED(hr = EnsureSecurityManager())) { goto End; }
if (_pbRootSecurityId == NULL) { // ASSERT(FALSE);
goto End; } else if (_pbRootSecurityId == INVALID_P_ROOT_SECURITY_ID) { bRetval = FALSE; goto End; } hr = g_pSecurityManager->GetSecurityId( pwszUrl, bSID, &cbSID, 0 );
if (FAILED(hr)) goto End;
bRetval = !SecurityIdsMatch(bSID, cbSID, _pbRootSecurityId, _cbRootSecurityId);
End: DEBUG_LEAVE(bRetval); return bRetval;
} BOOL CINet::IsThirdPartyUrl(LPCSTR pszUrl) { DEBUG_ENTER((DBG_APP, Bool, "CINet::IsThirdPartyUrl", "this=%#x, %.80q", this, pszUrl )); WCHAR pwszUrl[MAX_URL_SIZE]; BOOL bRetval = TRUE; // be safe or sorry?
if(MultiByteToWideChar(CP_ACP, 0, pszUrl, -1, pwszUrl, MAX_URL_SIZE)) bRetval = IsThirdPartyUrl(pwszUrl);
DEBUG_LEAVE(bRetval); return bRetval; }
//+---------------------------------------------------------------------------
//
// Function: CreateKnownProtocolInstance
//
// Synopsis:
//
// Arguments: [dwProtId] --
// [rclsid] --
// [pUnkOuter] --
// [riid] --
// [ppUnk] --
//
// Returns:
//
// History: 11-01-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CreateKnownProtocolInstance(DWORD dwProtId, REFCLSID rclsid, IUnknown *pUnkOuter, REFIID riid, IUnknown **ppUnk) { DEBUG_ENTER((DBG_APP, Hresult, "CreateKnownProtocolInstance", "%#x, %#x, %#x, %#x, %#x", dwProtId, &rclsid, pUnkOuter, &riid, ppUnk )); PerfDbgLog(tagCINet, NULL, "+CreateKnownProtocolInstance"); HRESULT hr = NOERROR; CINet *pCINet = NULL;
PProtAssert((ppUnk));
if (!ppUnk || (pUnkOuter && (riid != IID_IUnknown)) ) { // Note: aggregation only works if asked for IUnknown
PProtAssert((FALSE && "Dude, look up aggregation rules - need to ask for IUnknown")); hr = E_INVALIDARG; } #if 0
else if (riid == IID_IOInetProtocolInfo) { PProtAssert((dwProtId != DLD_PROTOCOL_NONE)); COInetProtocolInfo *pProtInfo = new COInetProtocolInfo(dwProtId); if (pProtInfo) { hr = pProtInfo->QueryInterface(IID_IOInetProtocolInfo, (void **)ppUnk); } else { hr = E_OUTOFMEMORY; } } #endif // 0
else if (dwProtId != DLD_PROTOCOL_NONE) { CINet *pCINet = NULL;
switch (dwProtId) { case DLD_PROTOCOL_LOCAL : case DLD_PROTOCOL_FILE : pCINet = new CINetFile(CLSID_FileProtocol,pUnkOuter); break; case DLD_PROTOCOL_HTTP : pCINet = new CINetHttp(CLSID_HttpProtocol,pUnkOuter); break; case DLD_PROTOCOL_FTP : pCINet = new CINetFtp(CLSID_FtpProtocol,pUnkOuter); break; case DLD_PROTOCOL_GOPHER : pCINet = new CINetGopher(CLSID_GopherProtocol,pUnkOuter); break; case DLD_PROTOCOL_HTTPS : pCINet = new CINetHttpS(CLSID_HttpSProtocol,pUnkOuter); break; case DLD_PROTOCOL_STREAM : pCINet = new CINetStream(CLSID_MkProtocol,pUnkOuter); break; default: PProtAssert((FALSE)); hr = E_FAIL; }
if (hr == NOERROR) { if (pCINet) { if (riid == IID_IUnknown) { // pCINet has refcount of 1 now
// get the pUnkInner
// pUnkInner does not addref pUnkOuter
if (pUnkOuter && ppUnk) { *ppUnk = pCINet->GetIUnkInner(TRUE); // addref the outer object since releasing pCINet will go cause a release on pUnkOuter
TransAssert((*ppUnk)); } } else { if (riid == IID_IOInetProtocol) { // ok, got the right interface already
*ppUnk = (IOInetProtocol *)pCINet; } else { hr = pCINet->QueryInterface(riid, (void **)ppUnk); // remove extra refcount
pCINet->Release(); } } } else { hr = E_OUTOFMEMORY; }
} } else { //load the protocol by looking up the registry
hr = E_FAIL; }
PerfDbgLog1(tagCINet, NULL, "-CreateKnownProtocolInstance(hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
ProtocolInfo rgKnownProts[] = { { L"http" , "http" , DLD_PROTOCOL_HTTP , (CLSID *) &CLSID_HttpProtocol , sizeof("http") - 1 } ,{ L"file" , "file" , DLD_PROTOCOL_FILE , (CLSID *) &CLSID_FileProtocol , sizeof("file") - 1 } ,{ L"ftp" , "ftp" , DLD_PROTOCOL_FTP , (CLSID *) &CLSID_FtpProtocol , sizeof("ftp") - 1 } ,{ L"https" , "https" , DLD_PROTOCOL_HTTPS , (CLSID *) &CLSID_HttpSProtocol , sizeof("http") - 1 } ,{ L"mk" , "mk" , DLD_PROTOCOL_STREAM , (CLSID *) &CLSID_MkProtocol , sizeof("mk") - 1 } ,{ L"gopher", "Gopher" , DLD_PROTOCOL_GOPHER , (CLSID *) &CLSID_GopherProtocol, sizeof("gopher") - 1 } ,{ L"local" , "local" , DLD_PROTOCOL_LOCAL , (CLSID *) &CLSID_FileProtocol , sizeof("local") - 1 } };
typedef struct tagInterErrorToHResult { DWORD dwError; HRESULT hresult; } InterErrorToHResult;
InterErrorToHResult INetError[] = { 0 ,NOERROR ,ERROR_INTERNET_OUT_OF_HANDLES ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_TIMEOUT ,INET_E_CONNECTION_TIMEOUT ,ERROR_INTERNET_EXTENDED_ERROR ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_INTERNAL_ERROR ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_INVALID_URL ,INET_E_INVALID_URL ,ERROR_INTERNET_UNRECOGNIZED_SCHEME ,INET_E_UNKNOWN_PROTOCOL ,ERROR_INTERNET_NAME_NOT_RESOLVED ,INET_E_RESOURCE_NOT_FOUND ,ERROR_INTERNET_PROTOCOL_NOT_FOUND ,INET_E_UNKNOWN_PROTOCOL ,ERROR_INTERNET_INVALID_OPTION ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_BAD_OPTION_LENGTH ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_OPTION_NOT_SETTABLE ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_SHUTDOWN ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_INCORRECT_USER_NAME ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_INCORRECT_PASSWORD ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_LOGIN_FAILURE ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_INVALID_OPERATION ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_OPERATION_CANCELLED ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_INCORRECT_HANDLE_TYPE ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_INCORRECT_HANDLE_STATE ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_NOT_PROXY_REQUEST ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_REGISTRY_VALUE_NOT_FOUND ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_BAD_REGISTRY_PARAMETER ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_NO_DIRECT_ACCESS ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_NO_CONTEXT ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_NO_CALLBACK ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_REQUEST_PENDING ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_INCORRECT_FORMAT ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_ITEM_NOT_FOUND ,INET_E_OBJECT_NOT_FOUND ,ERROR_INTERNET_CANNOT_CONNECT ,INET_E_RESOURCE_NOT_FOUND ,ERROR_INTERNET_CONNECTION_ABORTED ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_CONNECTION_RESET ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_FORCE_RETRY ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_INVALID_PROXY_REQUEST ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_NEED_UI ,INET_E_DOWNLOAD_FAILURE ,0 ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_HANDLE_EXISTS ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_SEC_CERT_DATE_INVALID ,INET_E_SECURITY_PROBLEM ,ERROR_INTERNET_SEC_CERT_CN_INVALID ,INET_E_SECURITY_PROBLEM ,ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_MIXED_SECURITY ,INET_E_SECURITY_PROBLEM ,ERROR_INTERNET_CHG_POST_IS_NON_SECURE ,INET_E_SECURITY_PROBLEM ,ERROR_INTERNET_POST_IS_NON_SECURE ,INET_E_SECURITY_PROBLEM ,ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED ,INET_E_SECURITY_PROBLEM ,ERROR_INTERNET_INVALID_CA ,INET_E_SECURITY_PROBLEM ,ERROR_INTERNET_CLIENT_AUTH_NOT_SETUP ,INET_E_SECURITY_PROBLEM ,ERROR_INTERNET_SEC_CERT_REV_FAILED ,INET_E_SECURITY_PROBLEM ,ERROR_INTERNET_SEC_CERT_REVOKED ,INET_E_SECURITY_PROBLEM ,ERROR_INTERNET_FORTEZZA_LOGIN_NEEDED ,INET_E_SECURITY_PROBLEM ,ERROR_INTERNET_ASYNC_THREAD_FAILED ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_REDIRECT_SCHEME_CHANGE ,INET_E_DOWNLOAD_FAILURE };
// list of non-sequential errors
InterErrorToHResult INetErrorExtended[] = { ERROR_FTP_TRANSFER_IN_PROGRESS ,INET_E_DOWNLOAD_FAILURE ,ERROR_FTP_DROPPED ,INET_E_DOWNLOAD_FAILURE ,ERROR_GOPHER_PROTOCOL_ERROR ,INET_E_DOWNLOAD_FAILURE ,ERROR_GOPHER_NOT_FILE ,INET_E_DOWNLOAD_FAILURE ,ERROR_GOPHER_DATA_ERROR ,INET_E_DOWNLOAD_FAILURE ,ERROR_GOPHER_END_OF_DATA ,INET_E_DOWNLOAD_FAILURE ,ERROR_GOPHER_INVALID_LOCATOR ,INET_E_DOWNLOAD_FAILURE ,ERROR_GOPHER_INCORRECT_LOCATOR_TYPE ,INET_E_DOWNLOAD_FAILURE ,ERROR_GOPHER_NOT_GOPHER_PLUS ,INET_E_DOWNLOAD_FAILURE ,ERROR_GOPHER_ATTRIBUTE_NOT_FOUND ,INET_E_DOWNLOAD_FAILURE ,ERROR_GOPHER_UNKNOWN_LOCATOR ,INET_E_DOWNLOAD_FAILURE ,ERROR_HTTP_HEADER_NOT_FOUND ,INET_E_DOWNLOAD_FAILURE ,ERROR_HTTP_DOWNLEVEL_SERVER ,INET_E_DOWNLOAD_FAILURE ,ERROR_HTTP_INVALID_SERVER_RESPONSE ,INET_E_DOWNLOAD_FAILURE ,ERROR_HTTP_INVALID_HEADER ,INET_E_DOWNLOAD_FAILURE ,ERROR_HTTP_INVALID_QUERY_REQUEST ,INET_E_DOWNLOAD_FAILURE ,ERROR_HTTP_HEADER_ALREADY_EXISTS ,INET_E_DOWNLOAD_FAILURE ,ERROR_HTTP_REDIRECT_FAILED ,INET_E_REDIRECT_FAILED ,ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_SECURITY_CHANNEL_ERROR ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_UNABLE_TO_CACHE_FILE ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_TCPIP_NOT_INSTALLED ,INET_E_DOWNLOAD_FAILURE ,ERROR_HTTP_NOT_REDIRECTED ,INET_E_DOWNLOAD_FAILURE ,ERROR_INTERNET_HTTPS_HTTP_SUBMIT_REDIR ,INET_E_DOWNLOAD_FAILURE };
//+---------------------------------------------------------------------------
//
// Function: IsKnownOInetProtocolClass
//
// Synopsis:
//
// Arguments: [pclsid] --
//
// Returns:
//
// History: 11-01-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD IsKnownOInetProtocolClass(CLSID *pclsid) { DEBUG_ENTER((DBG_APP, Dword, "IsKnownOInetProtocolClass", "%#x", pclsid )); PProtAssert((pclsid)); DWORD dwRet = DLD_PROTOCOL_NONE; int i = 0; int cSize = sizeof(rgKnownProts)/sizeof(ProtocolInfo);
if (pclsid) { for (i = 0; i < cSize; ++i) { if (*pclsid == *rgKnownProts[i].pClsID) { dwRet = rgKnownProts[i].dwId; i = cSize; } } }
DEBUG_LEAVE(dwRet); return dwRet; }
//+---------------------------------------------------------------------------
//
// Function: IsKnownProtocol
//
// Synopsis: looks up if an protocol handler exist for a given url
//
// Arguments: [wzProtocol] --
//
// Returns:
//
// History: 11-01-1996 JohannP (Johann Posch) Created
//
// Notes: used at many place inside urlmon
//
//----------------------------------------------------------------------------
DWORD IsKnownProtocol(LPCWSTR wzProtocol) { DEBUG_ENTER((DBG_APP, Dword, "IsKnownProtocol", "%#.80wq", wzProtocol )); DWORD dwRet = DLD_PROTOCOL_NONE; int i = 0; int cSize = sizeof(rgKnownProts)/sizeof(ProtocolInfo);
for (i = 0; i < cSize; ++i) { if (!StrCmpNICW(wzProtocol, rgKnownProts[i].pwzProtocol, rgKnownProts[i].protlen)) { dwRet = rgKnownProts[i].dwId;
if ((DLD_PROTOCOL_HTTP == dwRet) && ((wzProtocol[4] == L's') || (wzProtocol[4] == L'S')))
{ dwRet = DLD_PROTOCOL_HTTPS; } break; } }
DEBUG_LEAVE(dwRet); return dwRet; }
//+---------------------------------------------------------------------------
//
// Function: GetKnownOInetProtocolClsID
//
// Synopsis:
//
// Arguments: [dwProtoId] --
//
// Returns:
//
// History: 11-01-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
CLSID *GetKnownOInetProtocolClsID(DWORD dwProtoId) { DEBUG_ENTER((DBG_APP, Pointer, "GetKnownOInetProtocolClsID", "%#x", dwProtoId )); PerfDbgLog1(tagCINet, NULL, "GetKnownOInetProtocolClsID (dwProtoId:%lx)", dwProtoId); CLSID *pclsid = 0;
int cSize = sizeof(rgKnownProts)/sizeof(ProtocolInfo);
for (int i = 0; i < cSize; ++i) { if (dwProtoId == rgKnownProts[i].dwId ) { pclsid = rgKnownProts[i].pClsID; i = cSize; } }
DEBUG_LEAVE(pclsid); return pclsid; }
//+---------------------------------------------------------------------------
//
// Method: CINet::QueryInterface
//
// Synopsis:
//
// Arguments: [riid] --
// [ppvObj] --
//
// Returns:
//
// History: 10-29-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CINet::QueryInterface(REFIID riid, void **ppvObj) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::IUnknown::QueryInterface", "this=%#x, %#x, %#x", this, &riid, ppvObj )); VDATEPTROUT(ppvObj, void *); VDATETHIS(this); HRESULT hr = NOERROR;
PerfDbgLog(tagCINet, this, "+CINet::QueryInterface");
if (riid == IID_IOInetPriority) { *ppvObj = (IOInetPriority *) this; AddRef(); } else { hr = _pUnkOuter->QueryInterface(riid, ppvObj); }
PerfDbgLog1(tagCINet, this, "-CINet::QueryInterface (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: CINet::AddRef
//
// Synopsis:
//
// Arguments: [ULONG] --
//
// Returns:
//
// History: 10-29-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CINet::AddRef(void) { DEBUG_ENTER((DBG_APP, Dword, "CINet::IUnknown::AddRef", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::AddRef");
LONG lRet = _pUnkOuter->AddRef();
PerfDbgLog1(tagCINet, this, "-CINet::AddRef (cRefs:%ld)", lRet);
DEBUG_LEAVE(lRet); return lRet; }
//+---------------------------------------------------------------------------
//
// Function: CINet::Release
//
// Synopsis:
//
// Arguments: [ULONG] --
//
// Returns:
//
// History: 10-29-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CINet::Release(void) { DEBUG_ENTER((DBG_APP, Dword, "CINet::IUnknown::Release", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::Release");
LONG lRet = _pUnkOuter->Release();
PerfDbgLog1(tagCINet, this, "-CINet::Release (cRefs:%ld)", lRet);
DEBUG_LEAVE(lRet); return lRet; }
//+---------------------------------------------------------------------------
//
// Method: CINet::Start
//
// Synopsis:
//
// Arguments: [pwzUrl] --
// [pTrans] --
// [pOIBindInfo] --
// [grfSTI] --
// [dwReserved] --
//
// Returns:
//
// History: 10-29-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CINet::Start(LPCWSTR pwzUrl, IOInetProtocolSink *pTrans, IOInetBindInfo *pOIBindInfo, DWORD grfSTI, DWORD_PTR dwReserved) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::IInternetProtocolRoot::Start", "this=%#x, %.200wq, %#x, %#x, %#x, %#x", this, pwzUrl, pTrans, pOIBindInfo, grfSTI, dwReserved )); PerfDbgLog(tagCINet, this, "+CINet::Start"); HRESULT hr = NOERROR; //char szURL[MAX_URL_SIZE];
DWORD dwUrlSize = 0; DWORD dwMaxUTF8Len = 0; BOOL fUTF8Enabled = FALSE; BOOL fUTF8Required = FALSE;
PProtAssert((!_pCTrans && pOIBindInfo && pTrans)); PProtAssert((_pwzUrl == NULL));
if ( !(grfSTI & PI_PARSE_URL)) { _pCTrans = pTrans; _pCTrans->AddRef();
_pOIBindInfo = pOIBindInfo; _pOIBindInfo->AddRef();
_pwzUrl = OLESTRDuplicate((LPWSTR)pwzUrl); }
_BndInfo.cbSize = sizeof(BINDINFO);
hr = pOIBindInfo->GetBindInfo(&_grfBindF, &_BndInfo); DEBUG_ENTER((DBG_APP, Hresult, "EXTERNAL_CLIENT::GetBindInfo", "this=%#x, flags=%#x, pBindInfo=%#x", this, _grfBindF, pOIBindInfo ));
DEBUG_LEAVE(hr); if( hr != NOERROR ) { goto End; }
/************************************************************************
// szURL does not seem to be used, am I missing something?
// szURL is 2K buffer on stack! Let's remove this code at all.
// DanpoZ (98/02/20)
// Do we need to append the extra data to the url?
if (_BndInfo.szExtraInfo) { // append extra info at the end of the url
// Make sure we don't overflow the URL
if (CchWzLen(_BndInfo.szExtraInfo) + CchWzLen(pwzUrl) >= MAX_URL_SIZE) { hr = E_INVALIDARG; goto End; }
W2A(pwzUrl, szURL, MAX_URL_SIZE, _BndInfo.dwCodePage);
// Append the extra data to the url. Note that we have already
// checked for overflow, so we need not worry about it here.
W2A(_BndInfo.szExtraInfo, szURL + CchSzLen(szURL), MAX_URL_SIZE, _BndInfo.dwCodePage); } else { // Make sure we don't overflow the URL
if (CchWzLen(pwzUrl) + 1 > MAX_URL_SIZE) { hr = E_INVALIDARG; goto End; } W2A(pwzUrl, szURL, MAX_URL_SIZE, _BndInfo.dwCodePage); } ************************************************************************/
// no need to check the length of pwzUrl, this has been done already
if( !_BndInfo.dwCodePage ) _BndInfo.dwCodePage = GetACP();
// utf8 enabled?
fUTF8Enabled = UTF8Enabled();
if( fUTF8Enabled ) { dwUrlSize = CountUnicodeToUtf8(pwzUrl, wcslen(pwzUrl), TRUE); DWORD dwMB = StrLenMultiByteWithMlang(pwzUrl, _BndInfo.dwCodePage); if( dwMB > dwUrlSize ) { dwUrlSize = dwMB; } } else { dwUrlSize = StrLenMultiByteWithMlang(pwzUrl, _BndInfo.dwCodePage); }
if( !dwUrlSize ) { hr = E_INVALIDARG; goto End; }
if( CUrlInitBasic(dwUrlSize) ) { //W2A(pwzUrl, _pszBaseURL, dwUrlSize, _BndInfo.dwCodePage);
ConvertUnicodeUrl( pwzUrl, // (IN) unicode URL
_pszBaseURL, // (OUT) multibyte URL
dwUrlSize, // (IN) multibyte URL length
_BndInfo.dwCodePage, // (IN) codepage
fUTF8Enabled, // (IN) UTF-8 conversion enabled?
&fUTF8Required ); } else { hr = E_OUTOFMEMORY; goto End; }
{ // Init the Embedded Filter
if( _pEmbdFilter ) { delete _pEmbdFilter; _pEmbdFilter = NULL; } _pEmbdFilter = new CINetEmbdFilter( this, _pCTrans ); if( !_pEmbdFilter ) { hr = E_OUTOFMEMORY; goto End; } if(!_pEmbdFilter->IsInited()) { delete _pEmbdFilter; _pEmbdFilter = NULL; hr = E_OUTOFMEMORY; goto End; }
// For sanity checks later via IsEmbdFilterOk():
_dwEmbdFilter = *(DWORD *)_pEmbdFilter; }
if (!ParseUrl(fUTF8Required, pwzUrl, _BndInfo.dwCodePage)) { _hrError = INET_E_INVALID_URL; hr = MK_E_SYNTAX; } else if ( !(grfSTI & PI_PARSE_URL)) { g_cInetState.HandleState(); PProtAssert((_pCTrans)); if( !(_grfBindF & BINDF_FROMURLMON) && IsEmbdFilterOk() ) { _pEmbdFilter->ReportProgress(BINDSTATUS_DIRECTBIND, 0); } hr = INetAsyncStart(); } End:
PerfDbgLog1(tagCINet, this, "-CINet::Start (hr:%lx)", hr); if( hr == E_PENDING ) { // hack, CTransact will warp E_PENDING with NOERROR and return
// it to client, if we do not have CTrans wrapper (not aggregrated)
// we should return NOERROR.
if( _pUnkOuter == &_Unknown ) { hr = NOERROR; } }
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::Continue
//
// Synopsis:
//
// Arguments: [pStateInfoIn] --
//
// Returns:
//
// History: 10-29-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CINet::Continue(PROTOCOLDATA *pStateInfoIn) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::IInternetProtocolRoot::Continue", "this=%#x, %#x", this, pStateInfoIn )); HRESULT hr = E_FAIL; if(IsEmbdFilterOk()) hr = _pEmbdFilter->Continue(pStateInfoIn);
DEBUG_LEAVE(hr); return hr; }
STDMETHODIMP CINet::MyContinue(PROTOCOLDATA *pStateInfoIn) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::MyContinue", "this=%#x, %#x", this, pStateInfoIn )); PerfDbgLog(tagCINet, this, "+CINet::Continue"); HRESULT hr = NOERROR;
PProtAssert((pStateInfoIn->pData && !pStateInfoIn->cbData));
// check if the inete state changed
g_cInetState.HandleState();
OnINetInternal((DWORD_PTR) pStateInfoIn->pData);
if( !(_grfBindF & BINDF_FROMURLMON) ) { //
// if the BindInfo is created from heap by CINet
// we need to delete it from here
//
delete pStateInfoIn; }
PerfDbgLog1(tagCINet, this, "-CINet::Continue (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::Abort
//
// Synopsis:
//
// Arguments: [hrReason] --
// [dwOptions] --
//
// Returns:
//
// History: 10-29-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CINet::Abort(HRESULT hrReason, DWORD dwOptions) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::IInternetProtocolRoot::Abort", "this=%#x, %#x, %#x", this, hrReason, dwOptions )); HRESULT hr = NOERROR; if( _pEmbdFilter ) { hr = _pEmbdFilter->Abort(hrReason, dwOptions); }
DEBUG_LEAVE(hr); return hr; }
STDMETHODIMP CINet::MyAbort(HRESULT hrReason, DWORD dwOptions) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::MyAbort", "this=%#x, %#x, %#x", this, hrReason, dwOptions )); PerfDbgLog(tagCINet, this, "+CINet::Abort"); HRESULT hr = NOERROR;
PProtAssert((_pCTrans));
hr = ReportResultAndStop(hrReason);
PerfDbgLog1(tagCINet, this, "-CINet::Abort (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::Terminate
//
// Synopsis:
//
// Arguments: [dwOptions] --
//
// Returns:
//
// History: 10-29-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CINet::Terminate(DWORD dwOptions) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::IInternetProtocolRoot::Terminate", "this=%#x, %#x", this, dwOptions )); // in case we failed on :Start, _pEmbdFilter is
// not in place, however, Terminate might be
// called so we have to call MyTerminate directly
HRESULT hr = NOERROR; if( _pEmbdFilter ) { hr = _pEmbdFilter->Terminate(dwOptions); } else { hr = MyTerminate(dwOptions); }
DEBUG_LEAVE(hr); return hr; }
/*
* This function will only be called into after MyTerminate has been called - * since only InternetCloseHandle called in MyTerminate should trigger a handle-closing callback. * * No synchronization may be required because : * * 1. all operations at this point using the handle should have been done with since the handle has been destroyed ( hence no Reads in progress. ) 2. if we find that we need to synchronize access to this, we must correspondinly synchronize all access to the _pCTrans object from CINet. Hopefully, this is not required because we should get handleclosing callback from wininet only after we have exited all callbacks. 3. the only other place _pCTrans can be touched from is Reads from above which shouldn't be happening if this is closed as a result of being aborted or terminated cleanly. * The objective of this new function is to let the _pCTrans connection live until wininet is done with context use - else witness ugly race condition in bug 2270.
ReleaseBindInfo() happening here to get around bug 19809, which again is triggered by IBinding::Abort situations in stress. */ VOID CINet::ReleaseTransAndBindInfo() { DEBUG_ENTER((DBG_APP, None, "CINet::ReleaseTransAndBindInfo", "this=%#x, %#x", this, _pCTrans ));
if (!_fHandlesRecycled) { PProtAssert((_pCTrans)); PProtAssert((_dwState == INetState_DONE) || (_dwState == INetState_ERROR)); PProtAssert((_dwIsA == DLD_PROTOCOL_HTTP) || (_dwIsA == DLD_PROTOCOL_HTTPS) || (_dwIsA == DLD_PROTOCOL_FILE) || (_dwIsA == DLD_PROTOCOL_GOPHER)); // Hopefully, this stays an assert.
// scenario where abort is called before/during the OpenRequest/OpenUrl call.
PProtAssert((_HandleStateRequest == HandleState_Closed));
if (_pCTrans) { _pCTrans->Release(); _pCTrans = NULL; } ReleaseBindInfo(&_BndInfo); }
DEBUG_LEAVE(0); } STDMETHODIMP CINet::MyTerminate(DWORD dwOptions) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::MyTerminate", "this=%#x, %#x", this, dwOptions )); PerfDbgLog(tagCINet, this, "+CINet::Terminate"); HRESULT hr = NOERROR; BOOL fReleaseBindInfo = FALSE;
//should be called once
PProtAssert((_pCTrans));
if (_pOIBindInfo) { _pOIBindInfo->Release(); _pOIBindInfo = NULL; }
if (_pServiceProvider) { _pServiceProvider->Release(); _pServiceProvider = NULL; }
if (_pCTrans) { // release all the handles if unless
// the request was locked
if (!_fLocked && !_hLockHandle) { TerminateRequest(); }
// sync block
{ CLock lck(_mxs); // only one thread should be in here
if ((_dwState != INetState_DONE) && (_dwState != INetState_ERROR)) { _dwState = INetState_DONE; }
if ( (_dwIsA == DLD_PROTOCOL_FILE) || (_dwIsA == DLD_PROTOCOL_LOCAL) || (_dwIsA == DLD_PROTOCOL_STREAM) || _fHandlesRecycled || (_HandleStateServer == HandleState_Aborted)) { fReleaseBindInfo = TRUE; _pCTrans->Release(); _pCTrans = NULL; } }
}
#if DBG == 1
if ( _BndInfo.stgmedData.tymed != TYMED_NULL ) PerfDbgLog1(tagCINet, this, "--- CINet::Stop ReleaseStgMedium (%lx)", _BndInfo.stgmedData); #endif
if ( fReleaseBindInfo || (_dwIsA == DLD_PROTOCOL_FILE) || (_dwIsA == DLD_PROTOCOL_LOCAL) || (_dwIsA == DLD_PROTOCOL_STREAM) || _fHandlesRecycled || (_HandleStateServer == HandleState_Aborted)) { ReleaseBindInfo(&_BndInfo); }
PerfDbgLog1(tagCINet, this, "-CINet::Terminate (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::Suspend
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 10-29-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CINet::Suspend() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::IInternetProtocolRoot::Suspend", "this=%#x", this )); HRESULT hr = _pEmbdFilter->Suspend();
DEBUG_LEAVE(hr); return hr; }
STDMETHODIMP CINet::MySuspend() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::MySuspend", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::Suspend");
HRESULT hr = E_NOTIMPL;
PerfDbgLog1(tagCINet, this, "-CINet::Suspend (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::Resume
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 10-29-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CINet::Resume() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::IInternetProtocolRoot::Resume", "this=%#x", this )); HRESULT hr = _pEmbdFilter->Resume();
DEBUG_LEAVE(hr); return hr; }
STDMETHODIMP CINet::MyResume() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::MyResume", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::Resume");
HRESULT hr = E_NOTIMPL;
PerfDbgLog1(tagCINet, this, "-CINet::Resume (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::SetPriority
//
// Synopsis:
//
// Arguments: [nPriority] --
//
// Returns:
//
// History: 10-29-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CINet::SetPriority(LONG nPriority) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::IInternetPriority::SetPriority", "this=%#x, %#x", this, nPriority )); PerfDbgLog1(tagCINet, this, "+CINet::SetPriority (%ld)", nPriority);
HRESULT hr = S_OK;
_nPriority = nPriority;
PerfDbgLog1(tagCINet, this, "-CINet::SetPriority (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::GetPriority
//
// Synopsis:
//
// Arguments: [pnPriority] --
//
// Returns:
//
// History: 10-29-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CINet::GetPriority(LONG * pnPriority) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::IInternetPriority::GetPriority", "this=%#x, %#x", this, pnPriority )); PerfDbgLog(tagCINet, this, "+CINet::GetPriority");
HRESULT hr = S_OK;
*pnPriority = _nPriority;
PerfDbgLog1(tagCINet, this, "-CINet::GetPriority (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::Read
//
// Synopsis:
//
// Arguments: [ULONG] --
// [ULONG] --
// [pcbRead] --
//
// Returns:
//
// History: 10-29-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CINet::Read(void *pv,ULONG cb,ULONG *pcbRead) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::IInternetProtocol::Read", "this=%#x, %#x, %#x, %#x", this, pv, cb, pcbRead )); HRESULT hr = _pEmbdFilter->Read(pv, cb, pcbRead);
DEBUG_LEAVE(hr); return hr; }
STDMETHODIMP CINet::MyRead(void *pv,ULONG cb,ULONG *pcbRead) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::MyRead", "this=%#x, %#x, %#x, %#x", this, pv, cb, pcbRead )); PerfDbgLog(tagCINet, this, "+CINet::Read"); HRESULT hr = NOERROR;
if(GetBindFlags() & BINDF_DIRECT_READ) { hr = ReadDirect((BYTE *)pv, cb, pcbRead); } else { hr = ReadDataHere((BYTE *)pv, cb, pcbRead); }
PerfDbgLog1(tagCINet, this, "-CINet::Read (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::Seek
//
// Synopsis:
//
// Arguments: [DWORD] --
// [ULARGE_INTEGER] --
// [plibNewPosition] --
//
// Returns:
//
// History: 10-29-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CINet::Seek(LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER *plibNewPosition) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::IInternetProtocol::Seek", "this=%#x, %#x, %#x, %#x", this, dlibMove, dwOrigin, plibNewPosition )); HRESULT hr = _pEmbdFilter->Seek(dlibMove, dwOrigin, plibNewPosition);
DEBUG_LEAVE(hr); return hr; }
STDMETHODIMP CINet::MySeek(LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER *plibNewPosition) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::MySeek", "this=%#x, %#x, %#x, %#x", this, dlibMove, dwOrigin, plibNewPosition )); PerfDbgLog(tagCINet, this, "+CINet::Seek"); HRESULT hr;
hr = INetSeek(dlibMove, dwOrigin,plibNewPosition);
PerfDbgLog1(tagCINet, this, "-CINet::Seek (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::LockRequest
//
// Synopsis:
//
// Arguments: [dwOptions] --
//
// Returns:
//
// History: 10-29-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CINet::LockRequest(DWORD dwOptions) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::IInternetProtocol::LockRequest", "this=%#x, %#x", this, dwOptions )); HRESULT hr = _pEmbdFilter->LockRequest(dwOptions);
DEBUG_LEAVE(hr); return hr; }
STDMETHODIMP CINet::MyLockRequest(DWORD dwOptions) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::MyLockRequest", "this=%#x, %#x", this, dwOptions )); PerfDbgLog(tagCINet, this, "+CINet::LockRequest"); HRESULT hr = NOERROR;
hr = LockFile(FALSE);
PerfDbgLog1(tagCINet, this, "-CINet::LockRequest (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::UnlockRequest
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 10-29-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CINet::UnlockRequest() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::IInternetProtocol::UnlockRequest", "this=%#x", this )); HRESULT hr = _pEmbdFilter->UnlockRequest();
DEBUG_LEAVE(hr); return hr; }
STDMETHODIMP CINet::MyUnlockRequest() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::MyUnlockRequest", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::UnlockRequest"); HRESULT hr = NOERROR;
TerminateRequest(); hr = UnlockFile();
PerfDbgLog1(tagCINet, this, "-CINet::UnlockRequest (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::QueryOption
//
// Synopsis:
//
// Arguments: [dwOption] --
// [pBuffer] --
// [pcbBuf] --
//
// Returns:
//
// History: 4-16-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CINet::QueryOption(DWORD dwOption, LPVOID pBuffer, DWORD *pcbBuf) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::IWininetInfo::QueryOption", "this=%#x, %#x, %#x, %#x", this, dwOption, pBuffer, pcbBuf )); PerfDbgLog1(tagCINet, this, "+CINet::QueryOptions dwOption:%ld", dwOption); HRESULT hr;
if (!pcbBuf || (*pcbBuf == 0)) { hr = E_INVALIDARG; } else if (!_hRequest) { *pcbBuf = 0; hr = E_FAIL; } else if (dwOption == WININETINFO_OPTION_LOCK_HANDLE) { if ( *pcbBuf >= sizeof(HANDLE) && InternetLockRequestFile(_hRequest, (HANDLE *)pBuffer)) { *pcbBuf = sizeof(HANDLE); hr = S_OK; } else { *pcbBuf = 0; hr = E_FAIL; } } else { if (InternetQueryOption(_hRequest, dwOption, pBuffer, pcbBuf)) { hr = S_OK; } else { hr = S_FALSE; } }
PerfDbgLog2(tagCINet, this, "-CINet::QueryOptions (hr:%lx,szStr:%s)", hr, pBuffer);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::QueryInfo
//
// Synopsis:
//
// Arguments: [dwOption] --
// [pBuffer] --
// [pcbBuf] --
// [pdwFlag] --
//
// Returns:
//
// History: 4-16-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CINet::QueryInfo(DWORD dwOption, LPVOID pBuffer, DWORD *pcbBuf, DWORD *pdwFlags, DWORD *pdwReserved) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::IWininetHttpInfo::QueryInfo", "this=%#x, %#x, %#x, %#x, %#x, %#x", this, dwOption, pBuffer, pcbBuf, pdwFlags, pdwReserved )); PerfDbgLog1(tagCINet, this, "+CINet::QueryInfo dwOption:%ld", dwOption); HRESULT hr;
if (!pcbBuf) { hr = E_INVALIDARG; } else if (!_hRequest) { *pcbBuf = 0; hr = E_FAIL; } else { if (HttpQueryInfo(_hRequest, dwOption, pBuffer, pcbBuf, pdwFlags)) { hr = S_OK; } else { if (pBuffer && (*pcbBuf >= sizeof(HRESULT)) ) { HRESULT *phr = (HRESULT *)pBuffer; *phr = HRESULT_FROM_WIN32(GetLastError()); *pcbBuf = sizeof(HRESULT); } hr = S_FALSE; } }
PerfDbgLog2(tagCINet, this, "-CINet::QueryInfo (hr:%lx,szStr:%s)", hr, XDBG(pBuffer&&!hr?pBuffer:"",""));
DEBUG_LEAVE(hr); return hr; }
STDMETHODIMP CINet::Prepare() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::IInternetThreadSwitch::Prepare", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::Prepare"); HRESULT hr = NOERROR;
PerfDbgLog1(tagCINet, this, "-CINet::Prepare (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
STDMETHODIMP CINet::Continue() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::IInternetThreadSwitch::Continue", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::Continue"); HRESULT hr = NOERROR;
_dwThreadID = GetCurrentThreadId();
PerfDbgLog1(tagCINet, this, "-CINet::Continue (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::CINet
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
CINet::CINet(REFCLSID rclsid, IUnknown *pUnkOuter) : _CRefs(), _CRefsHandles(0), _cReadCount(0), _pclsidProtocol(rclsid), _Unknown() { DEBUG_ENTER((DBG_APP, None, "CINet::CINet", "this=%#x, %#x, %#x", this, &rclsid, pUnkOuter )); PerfDbgLog(tagCINet, this, "+CINet::CINet"); _dwEmbdFilter = NULL; _pEmbdFilter = NULL; _dwState = INetState_START; _dwIsA = DLD_PROTOCOL_NONE; _fRedirected = FALSE; _fP2PRedirected = FALSE; _fLocked = FALSE; _fFilenameReported = FALSE; _fHandlesRecycled = FALSE; _fSendAgain = FALSE; _fSendRequestAgain = FALSE; _hLockHandle = NULL; _hFile = NULL; _dwThreadID = GetCurrentThreadId(); _fDone = 0; _hwndAuth = NULL; _bscf = BSCF_FIRSTDATANOTIFICATION; _pOIBindInfo = 0; _pszUserAgentStr = 0; _nPriority = THREAD_PRIORITY_NORMAL; _cbSizeLastReportData = 0; _fForceSwitch = FALSE; _cbAuthenticate = 0; _cbProxyAuthenticate = 0;
_fDoSimpleRetry = FALSE;
if (!pUnkOuter) { pUnkOuter = &_Unknown; } _pUnkOuter = pUnkOuter; _pWindow = 0;
_hServer = 0; _hRequest = 0;
PerfDbgLog(tagCINet, this, "-CINet::CINet");
DEBUG_LEAVE(0); }
CINet::~CINet() { DEBUG_ENTER((DBG_APP, None, "CINet::~CINet", "this=%#x", this )); delete _pwzUrl; #if DBG == 1
_pwzUrl = NULL; #endif
delete _pszUserAgentStr;
// release Embedded Filter
if( _pEmbdFilter ) { CINetEmbdFilter* pEmbdFilter = _pEmbdFilter; _pEmbdFilter = NULL; delete pEmbdFilter; }
PerfDbgLog(tagCINet, this, "CINet::~CINet");
DEBUG_LEAVE(0); }
// Helper function for _pEmbdFilter sanity check:
bool CINet::IsEmbdFilterOk() { if(_pEmbdFilter && !::IsBadReadPtr(_pEmbdFilter, sizeof(DWORD)) && *(DWORD *)_pEmbdFilter == _dwEmbdFilter) return true;
// Shouldn't happen, but is happening in rare cases.
// Filter got released because someone likely deleted an incorrect offset.
PProtAssert((FALSE)); PerfDbgLog(tagCINet, this, "+CINet::IsEmbdFilterOk: EmbedFilter missing, recreating."); if(_pCTrans) { CLock lck(_mxs); // only one thread should be in here
// Do the check again just in case we have two threads entering:
if(_pEmbdFilter && !::IsBadReadPtr(_pEmbdFilter, sizeof(DWORD)) && *(DWORD *)_pEmbdFilter == _dwEmbdFilter) return true;
// Release _pCTrans to compensate for the AddRef in
// the CINetEmbdFilter constructor, since the CINetEmbdFilter destructor would not have been called:
_pCTrans->Release();
// Recreate the filter here if possible:
_pEmbdFilter = new CINetEmbdFilter( this, _pCTrans ); if( !_pEmbdFilter || !_pEmbdFilter->IsInited()) { // Something failed (deleting NULL is fine):
delete _pEmbdFilter; goto End; } // For sanity checks later via IsEmbdFilterOk():
_dwEmbdFilter = *(DWORD *)_pEmbdFilter; return true; }
End: PerfDbgLog(tagCINetErr, this, "+CINet::IsEmbdFilterOk: Unable to recreate EmbedFilter, possibly out of memory."); SetINetState(INetState_ERROR); // Null out and return false:
_pEmbdFilter = NULL; return false; }
//+---------------------------------------------------------------------------
//
// Method: CINet::ReportResultAndStop
//
// Synopsis: Post the termination package
//
// Arguments: [hr] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::ReportResultAndStop(HRESULT hr, ULONG ulProgress,ULONG ulProgressMax, LPWSTR pwzStr) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::ReportResultAndStop", "this=%#x, %#x, %#x, %#x, %.80wq", this, hr, ulProgress, ulProgressMax, pwzStr )); PerfDbgLog1(tagCINet, this, "+CINet::ReportResultAndStop (hr:%lx)", hr);
HRESULT hrOut = NOERROR; BOOL fReportResult = FALSE; BOOL fReportData = FALSE;
{ CLock lck(_mxs); // only one thread should be in here
// set the state to error and report error
// must go in queue since other messages might be ahead
if ((_dwState != INetState_DONE) && (_dwState != INetState_ERROR)) { _hrINet = hr; _dwState = (hr != NOERROR) ? INetState_ERROR : INetState_DONE; if (_dwState == INetState_DONE) { if (ulProgress == 0) { ulProgress = _cbTotalBytesRead; ulProgressMax = _cbDataSize; } if ( ( (ulProgress != _cbSizeLastReportData ) || (!ulProgress && !ulProgressMax) ) && ( _grfBindF & BINDF_FROMURLMON ) ) { //
// last notification
// NOTE: we need to report data for empty page
// we might have report this data already,
// so check for the _cbSizeLastReportData
// if they are same, do not report data
// again. (this might give hard time for
// IEFeatuer handler )
//
_bscf |= BSCF_LASTDATANOTIFICATION; fReportData = TRUE; }
//
// HACK: for prodegy's ocx
// if we have not send out ReportData(BSCF_LAST...) and
// we are doing BindToStorage but the data has been
// reported, we have to report it again with LAST flag
// tuned on
//
if( !fReportData && !(_bscf & BSCF_LASTDATANOTIFICATION ) && !(_BndInfo.dwOptions & BINDINFO_OPTIONS_BINDTOOBJECT) ) { // need to send out last notifiation for whatever
// client depend on it...
_bscf |= BSCF_LASTDATANOTIFICATION; fReportData = TRUE; } } else if (_dwState == INetState_ERROR) { SetINetState(INetState_ERROR); }
PProtAssert((_pCTrans)); fReportResult = TRUE; } }
if (_pCTrans) { if (fReportData) { _cbSizeLastReportData = ulProgress; _pEmbdFilter->ReportData(_bscf, ulProgress, ulProgressMax); } // teminate might have occured on ReportData
if (fReportResult && _pCTrans) { _pEmbdFilter->ReportResult(hr,_dwResult,pwzStr); }
if( !fReportResult ) { hrOut = INET_E_RESULT_DISPATCHED; } }
PerfDbgLog1(tagCINet, this, "-CINet::ReportResultAndStop (hrOut:%lx)", hrOut);
DEBUG_LEAVE(hrOut); return hrOut; }
//+---------------------------------------------------------------------------
//
// Method: CINet::ReportNotification
//
// Synopsis:
//
// Arguments: [NMsg] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::ReportNotification(BINDSTATUS NMsg, LPCSTR szStr) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::ReportNotification", "this=%#x, %#x, %.80q", this, NMsg, szStr )); PerfDbgLog1(tagCINet, this, "+CINet::ReportNotification (NMsg:%lx)", NMsg); HRESULT hr = E_FAIL;
BOOL fReport = FALSE; LPWSTR pwzStr = 0;
{ // ssync block begin
CLock lck(_mxs); // only one thread should be in here
if ((_dwState != INetState_DONE) && (_dwState != INetState_ERROR)) { if (szStr) { pwzStr = DupA2W((const LPSTR)szStr); } if (szStr && !pwzStr) { hr = E_OUTOFMEMORY; } else { fReport = TRUE; } } } // sync block end
if (fReport) { if ( _pCTrans && IsEmbdFilterOk() ) { hr = _pEmbdFilter->ReportProgress((ULONG)NMsg, pwzStr); } }
delete pwzStr;
PerfDbgLog(tagCINet, this, "-CINet::ReportNotification");
DEBUG_LEAVE(hr); return hr; }
HRESULT CINet::ReportNotificationW(BINDSTATUS NMsg, LPCWSTR wzStr) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::ReportNotificationW", "this=%#x, %#x, %.80q", this, NMsg, wzStr )); PerfDbgLog1(tagCINet, this, "+CINet::ReportNotificationW (NMsg:%lx)", NMsg); HRESULT hr = E_FAIL;
BOOL fReport = FALSE;
{ // ssync block begin
CLock lck(_mxs); // only one thread should be in here
if ((_dwState != INetState_DONE) && (_dwState != INetState_ERROR)) fReport = TRUE;
} // sync block end
if (fReport) { if ( _pCTrans && _pEmbdFilter ) { hr = _pEmbdFilter->ReportProgress((ULONG)NMsg, wzStr); } }
PerfDbgLog(tagCINet, this, "-CINet::ReportNotificationW");
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::SetPending
//
// Synopsis:
//
// Arguments: [hrNew] --
//
// Returns:
//
// History: 3-28-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::SetStatePending(HRESULT hrNew) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::SetStatePending", "this=%#x, %#x", this, hrNew )); CLock lck(_mxs); // only one thread should be in here
HRESULT hr;
PerfDbgLog2(tagCINet, this, "CINet::SetStatePending (hrOld:%lx, hrNew:%lx)", _hrPending, hrNew);
//BUGBUG: turn this assertion on again
PProtAssert(( ( ((_hrPending != E_PENDING) && (hrNew == E_PENDING)) || ((_hrPending == E_PENDING) && (hrNew != E_PENDING))) ));
hr = _hrPending; _hrPending = hrNew;
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::GetStatePending
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 4-08-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::GetStatePending() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::GetStatePending", "this=%#x", this )); CLock lck(_mxs); // only one thread should be in here
//PerfDbgLog1(tagCINet, this, "CINet::GetStatePending (hr:%lx)", _hrPending);
DEBUG_LEAVE(_hrPending); return _hrPending; }
//+---------------------------------------------------------------------------
//
// Method: CINet::SetByteCountReadyToRead
//
// Synopsis:
//
// Arguments: [cbReadyReadNow] --
//
// Returns:
//
// History: 6-25-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
void CINet::SetByteCountReadyToRead(LONG cbReadyReadNow) { DEBUG_ENTER((DBG_APP, None, "CINet::SetByteCountReadyToRead", "this=%#x, %#x", this, cbReadyReadNow )); CLock lck(_mxs); // only one thread should be in here
PerfDbgLog3(tagCINet, this, "CINet::SetByteCountReadyToRead (cbReadReturn:%ld, cbReadyRead:%ld, cbReadyLeft:%ld)", _cbReadyToRead, cbReadyReadNow, _cbReadyToRead + cbReadyReadNow); _cbReadyToRead += cbReadyReadNow ;
DEBUG_LEAVE(0); }
//+---------------------------------------------------------------------------
//
// Method: CINet::GetByteCountReadyToRead
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 6-25-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
ULONG CINet::GetByteCountReadyToRead() { DEBUG_ENTER((DBG_APP, None, "CINet::GetByteCountReadyToRead", "this=%#x", this )); CLock lck(_mxs); // only one thread should be in here
PerfDbgLog1(tagCINet, this, "CINet::GetByteCountReadyToRead (_cbReadyToRead:%ld)", _cbReadyToRead);
DEBUG_LEAVE(_cbReadyToRead); return _cbReadyToRead; }
//+---------------------------------------------------------------------------
//
// Method: CINet::SetINetState
//
// Synopsis:
//
// Arguments: [inState] --
//
// Returns:
//
// History: 2-25-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
INetState CINet::SetINetState(INetState inState) { DEBUG_ENTER((DBG_APP, Dword, "CINet::SetINetState", "this=%#x, %#x", this, inState )); CLock lck(_mxs); // only one thread should be in here
PerfDbgLog1(tagCINet, this, "+CINet::SetINetState (State:%lx)", inState);
INetState in = _INState; _INState = inState;
PerfDbgLog1(tagCINet, this, "-CINet::SetINetState (hr:%lx)", in);
DEBUG_LEAVE(in); return in; }
//+---------------------------------------------------------------------------
//
// Method: CINet::GetINetState
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 2-25-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
INetState CINet::GetINetState() { DEBUG_ENTER((DBG_APP, Dword, "CINet::GetINetState", "this=%#x", this )); CLock lck(_mxs); // only one thread should be in here
PerfDbgLog(tagCINet, this, "+CINet::GetINetState");
INetState in = _INState;
PerfDbgLog1(tagCINet, this, "-CINet::GetINetState (hr:%lx)", in);
DEBUG_LEAVE(in); return in; }
//+---------------------------------------------------------------------------
//
// Method: CINet::INetAsyncStart
//
// Synopsis:
//
// Arguments:
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::INetAsyncStart() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::INetAsyncStart", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::INetAsyncStart"); HRESULT hr = NOERROR; BOOL fAsyncStart = FALSE;
// guard the object
PrivAddRef();
if (fAsyncStart) { // post notification for next step
SetINetState(INetState_START); TransitState(INetState_START); } else { hr = INetAsyncOpen(); }
if (_hrError != INET_E_OK) { if (hr != S_OK && hr != E_PENDING && hr != INET_E_DONE) { PProtAssert(( (hr >= INET_E_ERROR_FIRST && hr <= INET_E_ERROR_LAST) ||(hr == E_OUTOFMEMORY) ||(hr == E_ABORT) ));
ReportResultAndStop(hr); } else { // he will do inetdone notifications
ReportResultAndStop(NOERROR); } }
PrivRelease();
PerfDbgLog1(tagCINet, this, "-CINet::INetAsyncStart (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::OnINetStart
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::OnINetStart() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::OnINetStart", "this=%#x", this )); HRESULT hr; PerfDbgLog(tagCINet, this, "+CINet::OnINetStart");
// nothing to do - just call
hr = INetAsyncOpen();
PerfDbgLog1(tagCINet, this, "-CINet::OnINetStart (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::INetAsyncOpen
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::INetAsyncOpen() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::INetAsyncOpen", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::INetAsyncOpen"); PProtAssert((GetStatePending() == NOERROR)); DWORD dwFlags = INTERNET_FLAG_ASYNC; DWORD dwBindF = 0;
HRESULT hr = NOERROR;
if (g_hSession == NULL) { // Only 1 thread should be in here, this is to protect
// two global variables g_hSession and g_pszUserAgentString
{ CLock lck(g_mxsSession); if( g_hSession == NULL ) { SetINetState(INetState_OPEN_REQUEST);
PerfDbgLog1(tagCINet, this, "___ INetAysncOpen calling InternetOpen %ld", GetTickCount()); SetStatePending(E_PENDING);
g_hSession = InternetOpen( GetUserAgentString() , INTERNET_OPEN_TYPE_PRECONFIG , NULL , NULL , dwFlags); PerfDbgLog1(tagCINet, this, "___ INetAysncOpen done InternetOpen %ld", GetTickCount());
if (g_hSession == NULL) { dwLstError = GetLastError(); if (dwLstError == ERROR_IO_PENDING) { hr = E_PENDING; } else { SetStatePending(NOERROR); hr = _hrError = INET_E_NO_SESSION; SetBindResult(dwLstError, hr); } } else { if (g_pszUserAgentString) { // Open was successful, so we don't need the replacement
// User Agent string anymore.
delete g_pszUserAgentString; g_pszUserAgentString = NULL; }
SetStatePending(NOERROR); InternetSetStatusCallbackA(g_hSession, CINetCallback); hr = INetAsyncConnect(); } } else { hr = INetAsyncConnect(); } } // single access block
} else { hr = INetAsyncConnect(); }
PerfDbgLog1(tagCINet, this, "-CINet::INetAsyncOpen (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::OnINetAsyncOpen
//
// Synopsis:
//
// Arguments: [dwResult] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::OnINetAsyncOpen(DWORD_PTR dwResult) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::OnINetAsyncOpen", "this=%#x, %#x", this, dwResult )); PerfDbgLog(tagCINet, this, "+CINet::OnINetAsyncOpen"); HRESULT hr = NOERROR;
PProtAssert((GetStatePending() == E_PENDING)); // set state to normal - no pending transaction
SetStatePending(NOERROR);
if (dwResult) { // set the handle and the callback
g_hSession = (HINTERNET) dwResult; InternetSetStatusCallbackA(g_hSession, CINetCallback); } // notification for next request
TransitState(INetState_OPEN_REQUEST);
PerfDbgLog1(tagCINet, this, "-CINet::OnINetAsyncOpen (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::INetAsyncConnect
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::INetAsyncConnect() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::INetAsyncConnect", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::INetAsyncConnect"); PProtAssert((GetStatePending() == NOERROR));
HRESULT hr = NOERROR; BOOL fRestarted; DWORD dwBindF = 0; DWORD dwService = INTERNET_SERVICE_HTTP;
// get the open flags
dwBindF = GetBindFlags();
if (dwBindF & BINDF_GETNEWESTVERSION) { _dwOpenFlags |= INTERNET_FLAG_RELOAD; PerfDbgLog1(tagCINet, this, "***CINet::****RELOAD***** %lx", dwBindF);
} else { PerfDbgLog1(tagCINet, this, "---CINet::----NO-RELOAD %lx --", dwBindF); }
if (dwBindF & BINDF_NOWRITECACHE) { _dwOpenFlags |= INTERNET_FLAG_DONT_CACHE ; }
if (dwBindF & BINDF_NEEDFILE) { PerfDbgLog(tagCINet, this, "CINet::INetAsyncConnect: turn on: INTERNET_FLAG_NEED_FILE"); _dwOpenFlags |= INTERNET_FLAG_NEED_FILE; }
if (dwBindF & (BINDF_NO_UI | BINDF_SILENTOPERATION)) { _dwOpenFlags |= INTERNET_FLAG_NO_UI; }
// BUGBUG OFFLINE, RELOAD, RESYNCHRONIZE and HYPERLINK are mutually
// exclusive. But inside wininet there is priority, so
// the priority is OFFLINE, RELOAD, RESYNCHRONIZE, HYPERLINK in that order
if (dwBindF & BINDF_RESYNCHRONIZE) { // caller asking to do if-modified-since
_dwOpenFlags |= INTERNET_FLAG_RESYNCHRONIZE; }
if (dwBindF & BINDF_HYPERLINK) { // caller says this is a hyperlink access
_dwOpenFlags |= INTERNET_FLAG_HYPERLINK; }
if (dwBindF & BINDF_FORMS_SUBMIT) { // caller says this is a forms submit.
_dwOpenFlags |= INTERNET_FLAG_FORMS_SUBMIT; }
if (dwBindF & BINDF_OFFLINEOPERATION ) { _dwOpenFlags |= INTERNET_FLAG_OFFLINE; }
// connect flags
if (dwBindF & BINDF_OFFLINEOPERATION ) { _dwConnectFlags |= INTERNET_FLAG_OFFLINE; }
if (dwBindF & BINDF_PRAGMA_NO_CACHE ) { _dwOpenFlags |= INTERNET_FLAG_PRAGMA_NOCACHE; }
if( dwBindF & BINDF_GETFROMCACHE_IF_NET_FAIL) { _dwOpenFlags |= INTERNET_FLAG_CACHE_IF_NET_FAIL; }
if( dwBindF & BINDF_FWD_BACK ) { _dwOpenFlags |= INTERNET_FLAG_FWD_BACK; }
// additional wininet flags are passed with bindinfo
if( _BndInfo.dwOptions == BINDINFO_OPTIONS_WININETFLAG ) { _dwOpenFlags |= _BndInfo.dwOptionsFlags; }
SetINetState(INetState_CONNECT_REQUEST);
PrivAddRef(TRUE);
_HandleStateServer = HandleState_Pending; SetStatePending(E_PENDING);
HINTERNET hServerTmp = InternetConnect( g_hSession, // hInternetSession
GetServerName(), // lpszServerName
_ipPort, // nServerPort
(_pszUserName[0])?_pszUserName:NULL, // lpszUserName
(_pszPassword[0])?_pszPassword:NULL, // lpszPassword
dwService, // INTERNET_SERVICE_HTTP
_dwConnectFlags, // dwFlags
(DWORD_PTR) this ); //
// Note: do not remove this state setting here!
// there is a timing window - needs to
// be fixed in wininet/urlmon!!!
SetINetState(INetState_CONNECT_REQUEST);
if ( hServerTmp == 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_CANNOT_CONNECT; SetBindResult(dwLstError, hr); } } else { _hServer = hServerTmp; SetStatePending(NOERROR); // wininet holds on to CINet - Release called on the callback on close handle
_HandleStateServer = HandleState_Initialized; PerfDbgLog1(tagCINet, this, "=== CINet::INetAsyncConnect (hServer:%lx)", _hServer); PProtAssert((_hServer)); hr = INetAsyncOpenRequest(); }
PerfDbgLog1(tagCINet, this, "-CINet::INetAsyncConnect (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::OnINetConnect
//
// Synopsis:
//
// Arguments: [dwResult] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::OnINetConnect(DWORD_PTR dwResult) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::OnINetConnect", "this=%#x, %#x", this, dwResult )); PerfDbgLog(tagCINet, this, "+CINet::OnINetConnect"); HRESULT hr = NOERROR;
PProtAssert((GetStatePending() == E_PENDING)); // set state to normal - no pending transaction
SetStatePending(NOERROR); TransAssert((_hServer == 0));
if (dwResult) { CLock lck(_mxs); // only one thread should be in here
if (_HandleStateServer == HandleState_Pending) { TransAssert((_hServer == 0)); // set the server handle
_HandleStateServer = HandleState_Initialized; _hServer = (HANDLE)dwResult; }
// wininet holds on to CINet - Release called on the callback on close handle
PerfDbgLog1(tagCINet, this, "=== CINet::OnINetConnect (hServer:%lx)", _hServer); }
if (_hServer) { TransitState(INetState_CONNECT_REQUEST); } else { PProtAssert((_HandleStateServer == HandleState_Aborted)); PrivRelease(TRUE); }
PerfDbgLog1(tagCINet, this, "-CINet::OnINetConnect (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::INetAsyncOpenRequest
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::INetAsyncOpenRequest() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::INetAsyncOpenRequest", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::INetAsyncOpenRequest");
HRESULT hr = E_FAIL;
PerfDbgLog1(tagCINet, this, "-CINet::INetAsyncOpenRequest (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::OnINetOpenRequest
//
// Synopsis:
//
// Arguments: [dwResult] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::OnINetOpenRequest(DWORD_PTR dwResult) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::OnINetOpenRequest", "this=%#x, %#x", this, dwResult )); PerfDbgLog1(tagCINet, this, "+CINet::OnINetOpenRequest (dwResult:%lx)", dwResult); HRESULT hr = NOERROR;
PProtAssert((GetStatePending() == E_PENDING)); // set state to normal - no pending transaction
SetStatePending(NOERROR); TransAssert((_hRequest == 0));
if (dwResult) { CLock lck(_mxs); // only one thread should be in here
if (_HandleStateRequest == HandleState_Pending) { // set the request handle
_HandleStateRequest = HandleState_Initialized; _hRequest = (HANDLE)dwResult; PProtAssert((_hServer != _hRequest)); } }
if (_hRequest) { if (_fUTF8hack) { DWORD dwSendUTF8 = 1; InternetSetOption(_hRequest, INTERNET_OPTION_SEND_UTF8_SERVERNAME_TO_PROXY, &dwSendUTF8, sizeof(DWORD)); } hr = INetAsyncSendRequest(); } else { PProtAssert((_HandleStateRequest == HandleState_Aborted)); PrivRelease(TRUE); }
PerfDbgLog1(tagCINet, this, "-CINet::OnINetOpenRequest (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr;
}
//+---------------------------------------------------------------------------
//
// Method: CINet::INetAsyncSendRequest
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::INetAsyncSendRequest() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::INetAsyncSendRequest", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::INetAsyncSendRequest");
HRESULT hr = E_FAIL;
PerfDbgLog1(tagCINet, this, "-CINet::INetAsyncSendRequest (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::OnINetSendRequest
//
// Synopsis:
//
// Arguments: [dwResult] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::OnINetSendRequest( DWORD dwResult) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::OnINetSendRequest", "this=%#x, %#x", this, dwResult )); PerfDbgLog(tagCINet, this, "+CINet::OnINetSendRequest"); HRESULT hr = NOERROR;
PProtAssert((GetStatePending() == E_PENDING)); // set state to normal - no pending transaction
SetStatePending(NOERROR);
_dwSendRequestResult = dwResult; _lpvExtraSendRequestResult = NULL;
if( dwResult == ERROR_INTERNET_FORCE_RETRY ) { PerfDbgLog(tagCINet, this, " --dwResult = FORCE_RETRY! "); _fSendRequestAgain = TRUE; }
if (OperationOnAparmentThread(INetState_SEND_REQUEST)) { // query for content-encoding header, if we find one,
// we will have to force TransitState to do thread switching
// since the compression filter can not be loaded on worker
// thread
char szEncType[SZMIMESIZE_MAX] = ""; DWORD cbLen = sizeof(szEncType); if( _hRequest && HttpQueryInfo(_hRequest, HTTP_QUERY_CONTENT_ENCODING, szEncType, &cbLen, NULL) ) { if( cbLen && szEncType[0] ) _fForceSwitch = TRUE; }
// if sec problem shows up on UI thread, we need to
// force switch
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_FORCE_RETRY : case ERROR_INTERNET_SEC_CERT_ERRORS : case ERROR_INTERNET_SEC_CERT_REV_FAILED : case ERROR_INTERNET_SEC_CERT_REVOKED : _fForceSwitch = TRUE; }
TransitState(INetState_SEND_REQUEST); } else if (!IsUpLoad()) { hr = INetQueryInfo(); } else { if( _fSendRequestAgain ) { _fCompleted = FALSE; _fSendAgain = TRUE; _fSendRequestAgain = FALSE; hr = INetAsyncSendRequest(); } }
PerfDbgLog1(tagCINet, this, "-CINet::OnINetSendRequest (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::OnINetSuspendSendRequest
//
// Synopsis: called on a wininet callback to indicate the suspentition
// of request processing until UI is displayed to the user.
//
// Arguments: [dwResult] -- error code to generate dialog for
// [lpvExtraResult] -- extra void pointer used pass dialog specific data
//
// Returns:
//
// History: 5-24-98 ArthurBi (Arthur Bierer) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::OnINetSuspendSendRequest(DWORD dwResult, LPVOID lpvExtraResult) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::OnINetSuspendSendRequest", "this=%#x, %#x, %#x", this, dwResult, lpvExtraResult )); PerfDbgLog(tagCINet, this, "+CINet::OnINetSuspendSendRequest"); HRESULT hr = NOERROR;
PProtAssert((GetStatePending() == E_PENDING));
// set state to normal - no pending transaction
SetStatePending(NOERROR);
_dwSendRequestResult = dwResult; _lpvExtraSendRequestResult = lpvExtraResult;
//if (OperationOnAparmentThread(INetState_SEND_REQUEST))
// even though we're not doing auth, we need to do UI
_hrINet = INET_E_AUTHENTICATION_REQUIRED; TransitState(INetState_DISPLAY_UI, TRUE);
PerfDbgLog1(tagCINet, this, "-CINet::OnINetSuspendSendRequest (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::INetStateChange
//
// Synopsis: called on the apartment thread
//
// Arguments: (none)
//
// Returns:
//
// History: 1-22-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::INetStateChange() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::INetStateChange", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::INetStateChange");
HRESULT hr = NOERROR;
g_cInetState.HandleState();
PerfDbgLog1(tagCINet, this, "-CINet::INetStateChange (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::OnINetStateChange
//
// Synopsis: called on the wininet worker thread whenever the
// wininet state changes
//
// Arguments: [dwResult] --
//
// Returns:
//
// History: 1-22-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::OnINetStateChange( DWORD dwResult) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::OnINetStateChange", "this=%#x, %#x", this, dwResult )); PerfDbgLog(tagCINet, this, "+CINet::OnINetStateChange"); HRESULT hr = NOERROR;
// set the new state and ping the apartment thread
g_cInetState.SetState(dwResult);
TransitState(INetState_INETSTATE_CHANGE);
PerfDbgLog1(tagCINet, this, "-CINet::OnINetStateChange (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::INetQueryInfo
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::INetQueryInfo() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::INetQueryInfo", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::INetQueryInfo");
HRESULT hr = NOERROR;
// Here we check if we need to do redirection, or
// whether authentication is needed etc.
if (!IsUpLoad()) { hr = QueryInfoOnResponse(); } if (hr == NOERROR) { // read more data from wininet
hr = INetRead(); } else if (hr == S_FALSE) { // S_FALSE means successful redirecting occured
hr = NOERROR; }
if (_hrError != INET_E_OK) { // we need to terminate here
ReportResultAndStop(hr); } PerfDbgLog1(tagCINet, this, "-CINet::INetQueryInfo (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::OnINetRead
//
// Synopsis:
//
// Arguments: [dwResult] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::OnINetRead(DWORD_PTR dwResult) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::OnINetRead", "this=%#x, %#x", this, dwResult )); PerfDbgLog(tagCINet, this, "+CINet::OnINetRead"); HRESULT hr = NOERROR;
PProtAssert((GetStatePending() == E_PENDING)); // set state to normal - no pending transaction
SetStatePending(NOERROR);
if (OperationOnAparmentThread(INetState_SEND_REQUEST)) { TransitState(INetState_READ); } else { hr = INetRead(); }
PerfDbgLog1(tagCINet, this, "-CINet::OnINetRead (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::INetRead
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::INetRead() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::INetRead", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::INetRead"); HRESULT hr = NOERROR; if (IsUpLoad()) { hr = INetWrite(); } else if(GetBindFlags() & BINDF_DIRECT_READ) { hr = INetReadDirect(); } else { // this is the no-copy case
// read data to users buffer
hr = INetDataAvailable(); }
if (_hrError != INET_E_OK) { // we need to terminate here
ReportResultAndStop((_hrError == INET_E_DONE) ? NOERROR : _hrError); }
PerfDbgLog1(tagCINet, this, "-CINet::INetRead (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; } //+---------------------------------------------------------------------------
//
// Method: CINet::INetwrite
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::INetWrite() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::INetWrite", "this=%#x", this )); HRESULT hr = E_FAIL;
TransAssert((FALSE && "HAS TO BE OVERWRITTEN"));
DEBUG_LEAVE(hr); return hr; }
#define COOKIES_BLOCKED_STRING "CookiesBlocked"
BINDSTATUS BindStatusFromCookieAction(DWORD dwCookieAction) { BINDSTATUS nMsg; switch(dwCookieAction) { case COOKIE_STATE_PROMPT: nMsg = BINDSTATUS_COOKIE_STATE_PROMPT; break; case COOKIE_STATE_ACCEPT: nMsg = BINDSTATUS_COOKIE_STATE_ACCEPT; break; case COOKIE_STATE_REJECT: nMsg = BINDSTATUS_COOKIE_STATE_REJECT; break; case COOKIE_STATE_LEASH: nMsg = BINDSTATUS_COOKIE_STATE_LEASH; break; case COOKIE_STATE_DOWNGRADE: nMsg = BINDSTATUS_COOKIE_STATE_DOWNGRADE; break; default: nMsg = BINDSTATUS_COOKIE_STATE_UNKNOWN; break; }
return nMsg; }
HRESULT CINet::OnCookieNotification(DWORD dwStatus, IN LPVOID pvInfo) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::OnCookieNotification", "this=%#x, %#x, %#x", this, dwStatus, pvInfo ));
HRESULT hr = ERROR_SUCCESS;
BINDSTATUS nMsg; DWORD dwBlock = 0;
switch (dwStatus) { case INTERNET_STATUS_P3P_HEADER: { TransAssert(pvInfo && "pvInfo should be a pointer to the P3P header");
hr = ReportNotification(BINDSTATUS_P3P_HEADER, (LPSTR)pvInfo); break; }
case INTERNET_STATUS_P3P_POLICYREF: { TransAssert(pvInfo && "pvInfo should be pointer to policy-ref URL");
if (char *pszPolicyRef = (char*) pvInfo) hr = ReportNotification(BINDSTATUS_POLICY_HREF, (LPSTR)pszPolicyRef);
break; }
case INTERNET_STATUS_COOKIE_HISTORY: { InternetCookieHistory *pPastActions = (InternetCookieHistory*) pvInfo;
if (!pPastActions) break;
if (pPastActions->fAccepted) ReportNotification(BINDSTATUS_COOKIE_STATE_ACCEPT, NULL);
if (pPastActions->fLeashed) ReportNotification(BINDSTATUS_COOKIE_STATE_LEASH, NULL);
if (pPastActions->fDowngraded) ReportNotification(BINDSTATUS_COOKIE_STATE_DOWNGRADE, NULL);
if (pPastActions->fRejected) ReportNotification(BINDSTATUS_COOKIE_STATE_REJECT, NULL);
break; }
case INTERNET_STATUS_COOKIE_SENT: { OutgoingCookieState* pOutgoing = (OutgoingCookieState *)pvInfo;
TransAssert(pOutgoing && "pvInfo should be OutgoingCookieState*"); if (pOutgoing->cSent) { hr = ReportNotification(BINDSTATUS_COOKIE_SENT, pOutgoing->pszLocation); } if (pOutgoing->cSuppressed) { hr = ReportNotification(BINDSTATUS_COOKIE_SUPPRESSED, pOutgoing->pszLocation); } break; } case INTERNET_STATUS_COOKIE_RECEIVED: { IncomingCookieState* pIncoming = (IncomingCookieState *)pvInfo;
TransAssert(pIncoming && "pvInfo should be OutgoingCookieState*"); if (pIncoming->cAccepted) hr = ReportNotification(BINDSTATUS_COOKIE_STATE_ACCEPT, pIncoming->pszLocation); if (SUCCEEDED(hr) && pIncoming->cLeashed) hr = ReportNotification(BINDSTATUS_COOKIE_STATE_LEASH, pIncoming->pszLocation); if (SUCCEEDED(hr) && pIncoming->cDowngraded) hr = ReportNotification(BINDSTATUS_COOKIE_STATE_DOWNGRADE, pIncoming->pszLocation);
if (SUCCEEDED(hr) && pIncoming->cBlocked) hr = ReportNotification(BINDSTATUS_COOKIE_STATE_REJECT, pIncoming->pszLocation); break; }
default: TransAssert(FALSE); break; } DEBUG_LEAVE(hr); return hr; } #define HRESULT_FROM_WININET(pv) HRESULT_FROM_WIN32( (((LPINTERNET_ASYNC_RESULT) (pv) )->dwError) )
//+---------------------------------------------------------------------------
//
// Method: CINet::CINetCallback
//
// Synopsis:
//
// Arguments: [hInternet] --
// [dwContext] --
// [dwStatus] --
// [pvInfo] --
// [dwStatusLen] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
VOID CALLBACK CINet::CINetCallback(IN HINTERNET hInternet, IN DWORD_PTR dwContext, IN DWORD dwStatus, IN LPVOID pvInfo, IN DWORD dwStatusLen) { DEBUG_ENTER((DBG_APP, None, "CINet::CINetCallback", "%#x, %#x, %#x, %#x, %#x", hInternet, dwContext, dwStatus, pvInfo, dwStatusLen )); // If this is a request, then we know the cookie type
CINet *pCINet = (CINet *) dwContext; HRESULT hrError = INET_E_OK;
//
// handle callback without a context
if (!dwContext) { switch (dwStatus) { default: //PProtAssert((FALSE));
break;
case INTERNET_STATUS_STATE_CHANGE : { DWORD dwState = *(DWORD *) pvInfo;
g_cInetState.SetState(dwState); } break; } // end switch
} else { PerfDbgLog2(tagCINet, pCINet, "+CINet::CINetCallback Status:%ld, State:%ld", dwStatus, pCINet->_INState);
DWORD_PTR dwAsyncResult;
// from here the original thread needs to be told of various things
// such as errors, operation done etc.
PProtAssert((pCINet));
// guard this call - request might be aborted
//pCINet->AddRef();
DWORD dwFault; #ifdef INET_CALLBACK_EXCEPTION
_try #endif // INET_CALLBACK_EXCEPTION
{
switch (dwStatus) { // the net connection state changed
case INTERNET_STATUS_STATE_CHANGE : { DWORD dwState = *(DWORD *) pvInfo; pCINet->OnINetStateChange(dwState); } break;
// callback to put up UI
case INTERNET_STATUS_USER_INPUT_REQUIRED: { // guard this call - request might be aborted
pCINet->PrivAddRef();
PProtAssert(pCINet->_INState == INetState_SEND_REQUEST); //PProtAssert(!((LPINTERNET_ASYNC_RESULT)pvInfo)->dwResult);
LPVOID lpvSendRequestResultData = (LPVOID) ((LPINTERNET_ASYNC_RESULT)pvInfo)->dwResult; DWORD dwSendRequestResult = ((LPINTERNET_ASYNC_RESULT) (pvInfo) )->dwError;
// handle the error here in particular pass on info for zone crossing
pCINet->OnINetSuspendSendRequest(dwSendRequestResult, lpvSendRequestResultData);
// unguard - release
pCINet->PrivRelease(); } break;
// request completed
case INTERNET_STATUS_REQUEST_COMPLETE: { // guard this call - request might be aborted
pCINet->PrivAddRef(); if (pCINet->_INState != INetState_ERROR) { PProtAssert((pCINet->GetStatePending() == E_PENDING)); }
switch (pCINet->_INState) { case INetState_OPEN_REQUEST: // the internet session handle is supposed to be returned
dwAsyncResult = ((LPINTERNET_ASYNC_RESULT)pvInfo)->dwResult; if (dwAsyncResult) { // got the internet session handle back
pCINet->OnINetAsyncOpen(dwAsyncResult); } else { hrError = pCINet->SetBindResult(((LPINTERNET_ASYNC_RESULT) (pvInfo))->dwError, INET_E_NO_SESSION); } break;
case INetState_CONNECT_REQUEST: // the server handle is supposed to be returned
dwAsyncResult = ((LPINTERNET_ASYNC_RESULT)pvInfo)->dwResult; if (dwAsyncResult) { pCINet->OnINetConnect(dwAsyncResult); } else { hrError = pCINet->SetBindResult(((LPINTERNET_ASYNC_RESULT) (pvInfo))->dwError,INET_E_CANNOT_CONNECT); } break;
case INetState_PROTOPEN_REQUEST: // the request handle is suppost to be returned
dwAsyncResult = ((LPINTERNET_ASYNC_RESULT)pvInfo)->dwResult; if (dwAsyncResult) { pCINet->OnINetOpenRequest(dwAsyncResult); } else { hrError = pCINet->SetBindResult(((LPINTERNET_ASYNC_RESULT) (pvInfo))->dwError,INET_E_OBJECT_NOT_FOUND); } break;
case INetState_SEND_REQUEST: { // SendRequest returns a BOOL
dwAsyncResult = ((LPINTERNET_ASYNC_RESULT)pvInfo)->dwResult; if (dwAsyncResult) { // pass on 0 and look up the status code with HttpQueryInfo
pCINet->OnINetSendRequest(0); } else { DWORD dwSendRequestResult = ((LPINTERNET_ASYNC_RESULT) (pvInfo) )->dwError; // handle the error here in particular pass on info for zone crossing
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_FORCE_RETRY : case ERROR_INTERNET_SEC_CERT_ERRORS : case ERROR_INTERNET_SEC_CERT_REV_FAILED : case ERROR_INTERNET_SEC_CERT_REVOKED : case ERROR_INTERNET_LOGIN_FAILURE_DISPLAY_ENTITY_BODY:
pCINet->OnINetSendRequest(dwSendRequestResult); break; default: hrError = pCINet->SetBindResult(((LPINTERNET_ASYNC_RESULT) (pvInfo))->dwError); break; } } else { hrError = pCINet->SetBindResult(((LPINTERNET_ASYNC_RESULT) (pvInfo))->dwError); } } } break;
case INetState_READ: // InternetRead returns TRUE of FALSE
dwAsyncResult = ((LPINTERNET_ASYNC_RESULT)pvInfo)->dwResult; if (dwAsyncResult) { pCINet->OnINetRead(dwAsyncResult); } else { hrError = pCINet->SetBindResult(((LPINTERNET_ASYNC_RESULT) (pvInfo))->dwError); } break;
case INetState_DATA_AVAILABLE: { DWORD_PTR dwResult = ((LPINTERNET_ASYNC_RESULT)(pvInfo))->dwResult;
if (dwResult) { DWORD dwBytes = ((LPINTERNET_ASYNC_RESULT) (pvInfo) )->dwError; pCINet->OnINetDataAvailable(dwBytes); } else { hrError = pCINet->SetBindResult(((LPINTERNET_ASYNC_RESULT) (pvInfo))->dwError); } } break;
case INetState_READ_DIRECT: { pCINet->OnINetReadDirect(0); } break;
case INetState_DATA_AVAILABLE_DIRECT: { PProtAssert((FALSE)); } break;
default: break; }
// unguard - release
pCINet->PrivRelease();
} break;
case INTERNET_STATUS_RESOLVING_NAME : { // get server name or proxy as string
//pCINet->ReportNotification(Notify_FindingServer, (LPSTR) pvInfo);
pCINet->ReportNotification(BINDSTATUS_FINDINGRESOURCE, (LPSTR) pvInfo); } break;
case INTERNET_STATUS_DETECTING_PROXY : { // indicate that auto-proxy detection is in progress
pCINet->ReportNotification(BINDSTATUS_PROXYDETECTING, (LPSTR) NULL); } break;
case INTERNET_STATUS_CONNECTING_TO_SERVER : { // get ip address as string
//pCINet->ReportNotification(Notify_Connecting, (LPSTR) pvInfo);
pCINet->ReportNotification(BINDSTATUS_CONNECTING, (LPSTR) pvInfo); } break;
case INTERNET_STATUS_SENDING_REQUEST : { // no data passed back
//pCINet->ReportNotification(Notify_SendingRequest);
pCINet->ReportNotification(BINDSTATUS_SENDINGREQUEST); } break;
case INTERNET_STATUS_REDIRECT : { PerfDbgLog1(tagCINet, pCINet, "+CINet::CINetCallback Redirected by WinINet (szRedirectUrl:%s)", (LPSTR) pvInfo);
// pvinfo contains the new url
pCINet->OnRedirect((LPSTR) pvInfo); } break;
case INTERNET_STATUS_HANDLE_CLOSING : { if ((*(LPHINTERNET)pvInfo) == pCINet->_hServer) { hrError = INET_E_OK; PerfDbgLog1(tagCINet, pCINet, "=== CINet::CINetCallback (Close Service Handle:%lx)", (*(LPHINTERNET) pvInfo)); PProtAssert((pCINet->_HandleStateServer == HandleState_Closed)); // this is the connect handle - call Release
pCINet->_hServer = 0; pCINet->PrivRelease(TRUE);
} else if ((*(LPHINTERNET)pvInfo) == pCINet->_hRequest) { hrError = INET_E_OK; PerfDbgLog1(tagCINet, pCINet, "=== CINet::CINetCallback (Close Request Handle:%lx)", (*(LPHINTERNET) pvInfo)); PProtAssert(( pCINet->_HandleStateRequest == HandleState_Closed)); // this is the connect handle - call Release
pCINet->_hRequest = 0; pCINet->ReleaseTransAndBindInfo(); pCINet->PrivRelease(TRUE); }
} break;
case INTERNET_STATUS_COOKIE_SENT: case INTERNET_STATUS_COOKIE_RECEIVED: case INTERNET_STATUS_COOKIE_HISTORY: case INTERNET_STATUS_PRIVACY_IMPACTED: case INTERNET_STATUS_P3P_HEADER: case INTERNET_STATUS_P3P_POLICYREF: { pCINet->OnCookieNotification(dwStatus, pvInfo); } break; case INTERNET_STATUS_HANDLE_CREATED : case INTERNET_STATUS_NAME_RESOLVED : case INTERNET_STATUS_CONNECTED_TO_SERVER : case INTERNET_STATUS_REQUEST_SENT : case INTERNET_STATUS_RECEIVING_RESPONSE : case INTERNET_STATUS_RESPONSE_RECEIVED : case INTERNET_STATUS_CTL_RESPONSE_RECEIVED : case INTERNET_STATUS_PREFETCH : case INTERNET_STATUS_CLOSING_CONNECTION : case INTERNET_STATUS_CONNECTION_CLOSED :
default: { //handle other status here
}
} // end switch
if (hrError != INET_E_OK) { PerfDbgLog2(tagCINet, pCINet, "=== CINet::CINetCallback _hrINet:%lx, ERROR: %lx", pCINet->_hrINet, hrError); // we need to terminate here
pCINet->ReportResultAndStop(pCINet->_hrINet); } // unguard - release
//pCINet->Release();
} #ifdef INET_CALLBACK_EXCEPTION
_except(UrlMonInvokeExceptionFilter(GetExceptionCode(), GetExceptionInformation())) { dwFault = GetExceptionCode();
#if DBG == 1
//
// UrlMon catches exceptions when the client generates them. This is so we can
// cleanup properly, and allow urlmon to continue.
//
if ( dwFault == STATUS_ACCESS_VIOLATION || dwFault == 0xC0000194 /*STATUS_POSSIBLE_DEADLOCK*/ || dwFault == 0xC00000AA /*STATUS_INSTRUCTION_MISALIGNMENT*/ || dwFault == 0x80000002 /*STATUS_DATATYPE_MISALIGNMENT*/ ) { WCHAR iidName[256]; iidName[0] = 0; char achProgname[256]; achProgname[0] = 0;
GetModuleFileNameA(NULL,achProgname,sizeof(achProgname)); DbgLog2(tagCINetErr, NULL, "NotificationMgr has caught a fault 0x%08x on behalf of application %s", dwFault, achProgname); //TransAssert((!"The application has faulted processing. Check the kernel debugger for useful output.URLMon can continue but you probably want to stop and debug the application."));
} #endif
} #ifdef unix
__endexcept #endif /* unix */
#endif INET_CALLBACK_EXCEPTION
}
PerfDbgLog1(tagCINet, pCINet, "-CINet::CINetCallback (hrError:%lx)", hrError);
DEBUG_LEAVE(0); }
//+---------------------------------------------------------------------------
//
// Method: CINet::TransitState
//
// Synopsis:
//
// Arguments: [dwState] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
void CINet::TransitState(DWORD dwState, BOOL fAsync) { DEBUG_ENTER((DBG_APP, None, "CINet::TransitState", "this=%#x, %#x, %B", this, dwState, fAsync )); PerfDbgLog(tagCINet, this, "+CINet::TransitState");
if ((_dwState != INetState_DONE) && (_dwState != INetState_ERROR)) { BINDSTATUS NMsg = (BINDSTATUS) ((fAsync) ? BINDSTATUS_INTERNALASYNC : BINDSTATUS_INTERNAL); DWORD dwFlags = 0;
if ( NMsg == BINDSTATUS_INTERNALASYNC || NMsg == BINDSTATUS_ERROR || NMsg == BINDSTATUS_INTERNALASYNC) { dwFlags |= PI_FORCE_ASYNC; } if ( (dwState == INetState_AUTHENTICATE) || (dwState == INetState_DISPLAY_UI) || (_fForceSwitch)) { dwFlags |= PD_FORCE_SWITCH; }
if( _grfBindF & BINDF_FROMURLMON ) { CStateInfo CSI = CStateInfo(NMsg, dwFlags, (LPVOID)(ULongToPtr((ULONG)dwState))); if( _pCTrans ) { _pCTrans->Switch(&CSI); } } else { CStateInfo* pCSI = new CStateInfo(NMsg, dwFlags, (LPVOID)(ULongToPtr((ULONG)dwState))); if( !pCSI ) { ReportResultAndStop(E_OUTOFMEMORY); } else { if( dwFlags & PD_FORCE_SWITCH || _fForceSwitch ) { if( _pCTrans ) { _pCTrans->Switch(pCSI); } } else { Continue(pCSI); } } } }
PerfDbgLog(tagCINet, this, "-CINet::TransitState");
DEBUG_LEAVE(0); }
//+---------------------------------------------------------------------------
//
// Method: CINet::OnINetInternal
//
// Synopsis:
//
// Arguments: [dwState] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
void CINet::OnINetInternal(DWORD_PTR dwState) { DEBUG_ENTER((DBG_APP, None, "CINet::OnINetInternal", "this=%#x, %#x", this, dwState )); PerfDbgLog(tagCINet, this, "+CINet::OnINetInternal");
HRESULT hr = NOERROR;
if ((_dwState != INetState_DONE) && (_dwState != INetState_ERROR)) { switch (dwState) { case INetState_START : // is requested
hr = INetAsyncOpen(); break; case INetState_OPEN_REQUEST : hr = INetAsyncConnect(); break; case INetState_CONNECT_REQUEST : hr = INetAsyncOpenRequest(); break; case INetState_PROTOPEN_REQUEST: hr = INetAsyncSendRequest(); break; case INetState_SEND_REQUEST : if( _fSendRequestAgain ) { _fCompleted = FALSE; _fSendAgain = TRUE; _fSendRequestAgain = FALSE; hr = INetAsyncSendRequest(); } else { hr = INetQueryInfo(); } break; case INetState_DISPLAY_UI : hr = INetDisplayUI(); break; case INetState_AUTHENTICATE : hr = INetAuthenticate(); break; case INetState_READ : hr = INetRead(); break; case INetState_READ_DIRECT : hr = INetReadDirect(); break; case INetState_DATA_AVAILABLE : hr = INetReportAvailableData(); break; case INetState_INETSTATE_CHANGE: hr = INetStateChange(); break; case INetState_DONE : break; default: break; } } /*
else { PProtAssert((FALSE && "Unknown state")); } */
if ((hr != NOERROR) && (hr != E_PENDING)) { ReportResultAndStop(hr); }
PerfDbgLog(tagCINet, this, "-CINet::OnINetInternal");
DEBUG_LEAVE(0); }
//+---------------------------------------------------------------------------
//
// Method: CINet::TerminateRequest
//
// Synopsis: Close the server and request handle - wininet will make a
// callback on each handle closed
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
void CINet::TerminateRequest() { DEBUG_ENTER((DBG_APP, None, "CINet::TerminateRequest", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::TerminateRequest"); CLock lck(_mxs); // only one thread should be in here
if ((_HandleStateRequest == HandleState_Initialized)) { PProtAssert((_hRequest)); _HandleStateRequest = HandleState_Closed; InternetCloseHandle(_hRequest); //_hRequest = 0;
} else if ((_HandleStateRequest == HandleState_Pending)) { _HandleStateRequest = HandleState_Aborted; }
if (_HandleStateServer == HandleState_Initialized) { PerfDbgLog1(tagCINet, this, "=== CINet::TerminateRequest InternetCloseHandle (hServer:%lx)", _hServer); _HandleStateServer = HandleState_Closed;
if (_hServer) { // the handle can be NULL
// in case we got aborted during the
// pending open request
InternetCloseHandle(_hServer); } } else if ((_HandleStateServer == HandleState_Pending)) { _HandleStateServer = HandleState_Aborted; }
PerfDbgLog(tagCINet, this, "-CINet::TerminateRequest");
DEBUG_LEAVE(0); }
//+---------------------------------------------------------------------------
//
// Method: CINet::FindTagInHeader
//
// Synopsis:
//
// Arguments: [lpszBuffer] --
// [lpszTag] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
LPSTR CINet::FindTagInHeader(LPCSTR lpszBuffer, LPCSTR lpszTag) { DEBUG_ENTER((DBG_APP, String, "CINet::FindTagInHeader", "this=%#x, %.80q, %.80q", this, lpszBuffer, lpszTag )); PerfDbgLog(tagCINet, this, "+CINet::FindTagInHeader"); LPCSTR p; int i, cbTagLen;
cbTagLen = strlen(lpszTag); for (p = lpszBuffer; i = strlen(p); p += (i + 1)) { if (!StrCmpNI(p, lpszTag, cbTagLen)) {
DEBUG_LEAVE((LPSTR)p); return (LPSTR)p; } }
PerfDbgLog(tagCINet, this, "-CINet::FindTagInHeader");
DEBUG_LEAVE(NULL); return NULL; }
//+---------------------------------------------------------------------------
//
// Method: CINet::INetDataAvailable
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 2-23-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::INetDataAvailable() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::INetDataAvailable", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::INetDataAvailable");
HRESULT hr = NOERROR; BOOL fRet = FALSE;
PProtAssert((GetStatePending() == NOERROR)); SetINetState(INetState_DATA_AVAILABLE);
if (!_fFilenameReported) { char szFilename[MAX_PATH];
HRESULT hr1 = GetUrlCacheFilename(szFilename, MAX_PATH);
if (hr1 == NOERROR && szFilename[0] != '\0' ) { ReportNotification(BINDSTATUS_CACHEFILENAMEAVAILABLE, (LPSTR) szFilename); _fFilenameReported = TRUE; } }
// check if all data were read of the current buffer
SetStatePending(E_PENDING);
fRet = InternetQueryDataAvailable(_hRequest, &_cbReadReturn, 0, 0);
if (fRet == FALSE) { dwLstError = GetLastError(); if (dwLstError == ERROR_IO_PENDING) { hr = E_PENDING; } else { SetStatePending(NOERROR); hr = _hrError = INET_E_DATA_NOT_AVAILABLE; } } else { SetByteCountReadyToRead(_cbReadReturn); SetStatePending(NOERROR);
if (_cbReadReturn == 0) { // done
_fDone = 1; }
hr = INetReportAvailableData(); }
PerfDbgLog1(tagCINet, this, "-CINet::INetDataAvailable (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::OnINetDataAvailable
//
// Synopsis:
//
// Arguments: [dwResult] --
//
// Returns:
//
// History: 2-23-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::OnINetDataAvailable( DWORD dwResult) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::OnINetDataAvailable", "this=%#x, %#x", this, dwResult )); PerfDbgLog1(tagCINet, this, "+CINet::OnINetDataAvailable (dwAvailable:%ld)", dwResult); HRESULT hr = NOERROR;
PProtAssert((GetStatePending() == E_PENDING));
SetByteCountReadyToRead(dwResult);
if (dwResult == 0) { // done
_fDone = 1; }
// set state to normal - no pending transaction
SetStatePending(NOERROR);
// notification for next request
TransitState(INetState_DATA_AVAILABLE);
PerfDbgLog1(tagCINet, this, "-CINet::OnINetDataAvailable (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::INetReportAvailableData
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 2-23-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::INetReportAvailableData() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::INetReportAvailableData", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::INetReportAvailableData"); HRESULT hr = NOERROR; DWORD dwError; ULONG cbBytesAvailable = 0;
//BUGBUG: we hit this assertion sometimes.
//PProtAssert((GetStatePending() == NOERROR));
_hrError = INET_E_OK;
if ((GetStatePending() == E_PENDING)) { // nothing to do - data for this notfication
// already received
} else if ((cbBytesAvailable = GetByteCountReadyToRead()) != 0) { if ( _fDone || ( _cbTotalBytesRead && _cbDataSize && (_cbTotalBytesRead == _cbDataSize))) {
_hrError = INET_E_DONE; } else { if(_cbDataSize && (_cbDataSize < (cbBytesAvailable + _cbTotalBytesRead))) { _cbDataSize = cbBytesAvailable + _cbTotalBytesRead; }
if (_bscf & BSCF_DATAFULLYAVAILABLE) { _bscf |= BSCF_LASTDATANOTIFICATION; _bscf &= ~BSCF_FIRSTDATANOTIFICATION; } // BUG-WORK pCTrans migh be gone by now
_cbSizeLastReportData = cbBytesAvailable + _cbTotalBytesRead; hr = _pEmbdFilter->ReportData(_bscf, cbBytesAvailable + _cbTotalBytesRead, _cbDataSize);
if (_bscf & BSCF_FIRSTDATANOTIFICATION) { _bscf &= ~BSCF_FIRSTDATANOTIFICATION; _bscf |= BSCF_INTERMEDIATEDATANOTIFICATION; } }
} else if ( _fDone || ( _cbTotalBytesRead && _cbDataSize && (_cbTotalBytesRead == _cbDataSize))) { if (_cbDataSize == 0) { _cbDataSize = _cbTotalBytesRead; }
PerfDbgLog2(tagCINet, this, "=== CINet::INetReportAvailableData DONE! (cbTotalBytesRead:%ld, cbDataSize:%ld)", _cbTotalBytesRead, _cbDataSize); // now we should have all data
PProtAssert(( ( ( _cbDataSize == 0) || ((_cbDataSize != 0) && (_cbTotalBytesRead == _cbDataSize))) && "Did not get all data!!"));
_hrError = INET_E_DONE; }
if (_hrError != INET_E_OK) { _bscf |= BSCF_LASTDATANOTIFICATION; if (_pCTrans ) { _cbSizeLastReportData = _cbTotalBytesRead; hr = _pEmbdFilter->ReportData(_bscf, _cbTotalBytesRead, _cbDataSize);
} hr = NOERROR; }
PerfDbgLog2(tagCINet, this, "-CINet::INetReportAvailableData (_hrError:%lx, hr:%lx)", _hrError, hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::ReadDataHere
//
// Synopsis:
//
// Arguments: [pBuffer] --
// [cbBytes] --
// [pcbBytes] --
//
// Returns:
//
// History: 2-13-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::ReadDataHere(BYTE *pBuffer, DWORD cbBytes, DWORD *pcbBytes) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::ReadDataHere", "this=%#x, pBuffer, cbBytes, pcbBytes", this, pBuffer, cbBytes, pcbBytes )); PerfDbgLog(tagCINet, this, "+CINet::ReadDataHere"); HRESULT hr = NOERROR; DWORD dwError;
*pcbBytes = 0; ULONG cbReadReturn = 0; ULONG dwReturned = 0; ULONG dwReturnedTotal = 0; ULONG dwBytesLeft = cbBytes;
//BUGBUG: turn this assertion on again
//PProtAssert((GetStatePending() == NOERROR));
if (_hrError == INET_E_DONE) { // means end of file
hr = S_FALSE; } else if (GetStatePending() != NOERROR) { hr = E_PENDING; } else { _hrError = INET_E_OK; do { if ((cbReadReturn = GetByteCountReadyToRead()) == 0) { BOOL fRet;
PerfDbgLog(tagCINet, this, "CINet::ReadDataHere -> InternetQueryDataAvailable"); PProtAssert((GetStatePending() == NOERROR)); SetStatePending(E_PENDING); fRet = InternetQueryDataAvailable(_hRequest, &_cbReadReturn,0 ,0);
if (fRet == FALSE) { dwLstError = GetLastError(); if (dwLstError == ERROR_IO_PENDING) { hr = E_PENDING; } else { SetStatePending(NOERROR); hr = _hrError = INET_E_DATA_NOT_AVAILABLE; } } else { SetByteCountReadyToRead(_cbReadReturn); SetStatePending(NOERROR); if (_cbReadReturn == 0) { // download completed - no more data available
hr = _hrError = INET_E_DONE; } }
PerfDbgLog2(tagCINet, this, "CINet::ReadDataHere == InternetQueryDataAvailable (fRet:%d, _cbReadReturn:%ld)", fRet, _cbReadReturn); }
// in case of noerror read the bits
if ((hr == NOERROR) && (_hrError == INET_E_OK)) { cbReadReturn = GetByteCountReadyToRead(); PProtAssert((GetStatePending() == NOERROR));
// get the read buffer from the trans data object
PProtAssert(((pBuffer != NULL) && (cbBytes > 0))); PProtAssert((cbReadReturn > 0));
dwBytesLeft = cbBytes - dwReturnedTotal; if (dwBytesLeft > cbReadReturn) { dwBytesLeft = cbReadReturn; }
PProtAssert(( dwBytesLeft <= (cbBytes - dwReturnedTotal) ));
dwReturned = 0; PerfDbgLog1(tagCINet, this, "CINet::ReadDataHere -> InternetReadFile (dwBytesLeft:%ld)", dwBytesLeft); if (!InternetReadFile(_hRequest, pBuffer + dwReturnedTotal, dwBytesLeft, &dwReturned)) { dwError = GetLastError(); if (dwError != ERROR_IO_PENDING) { hr = _hrError = INET_E_DOWNLOAD_FAILURE; DbgLog3(tagCINetErr, this, "CINet::ReadDataHere failed: (dwError:%lx, hr:%lx, hrError:%lx)", dwError, hr, _hrError);
} else { // Note: BIG ERROR - we need to shut down now
// wininet is using the client buffer and the client is not
// aware that the buffer is used during the pending time
//
DbgLog(tagCINetErr, this, "CINet::ReadDataHere - InternetReadFile returned E_PENDING!!!"); PProtAssert((FALSE && "CINet::ReadDataHere - InternetReadFile returned E_PENDING!!!"));
hr = _hrError = INET_E_DOWNLOAD_FAILURE; }
PerfDbgLog1(tagCINet, this, "CINet::ReadDataHere == InternetReadFile (dwError:%lx)", dwError);
} else { PerfDbgLog3(tagCINet, this, "CINet::ReadDataHere == InternetReadFile ==> (cbBytes:%ld, dwReturned:%ld,_cbReadReturn:%ld)", cbBytes, dwReturned,_cbReadReturn);
PProtAssert(( (cbBytes + dwReturnedTotal) >= dwReturned ));
if (dwReturned == 0) { hr = _hrError = INET_E_DONE; } else { hr = NOERROR; }
dwReturnedTotal += dwReturned; cbReadReturn -= dwReturned; SetByteCountReadyToRead(-(LONG)dwReturned); _cbTotalBytesRead += dwReturned; } } // read case - bits available
PerfDbgLog4(tagCINet, this, "CINet::ReadDataHere ooo InternetReadFile ==>(cbBytes:%ld, dwReturned:%ld,cbReadReturn:%ld,dwReturnedTotal:%ld)", cbBytes, dwReturned,cbReadReturn,dwReturnedTotal);
} while ((hr == NOERROR) && (dwReturnedTotal < cbBytes));
PProtAssert((dwReturnedTotal <= cbBytes)); *pcbBytes = dwReturnedTotal;
if (hr == INET_E_DONE) { hr = (dwReturnedTotal) ? S_OK : S_FALSE; } }
// Note: stop the download in case of DONE or ERROR!
if (_hrError != INET_E_OK) { ReportResultAndStop((hr == S_FALSE) ? NOERROR : hr, _cbTotalBytesRead, _cbDataSize); }
PerfDbgLog4(tagCINet, this, "-CINet::ReadDataHere (_hrError:%lx, [hr:%lx,cbBytesAsked:%ld,cbBytesReturned:%ld])", _hrError, hr, cbBytes, *pcbBytes);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::OperationOnAparmentThread
//
// Synopsis:
//
// Arguments: [dwState] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL CINet::OperationOnAparmentThread(DWORD dwState) { DEBUG_ENTER((DBG_APP, Bool, "CINet::OperationOnAparmentThread", "this=%#x, %#x", this, dwState )); PerfDbgLog(tagCINet, this, "+CINet::OperationOnAparmentThread"); BOOL fRet = FALSE; switch (dwState) { case INetState_OPEN_REQUEST: break; case INetState_CONNECT_REQUEST: break; case INetState_PROTOPEN_REQUEST: break; case INetState_SEND_REQUEST: break; case INetState_READ: case INetState_READ_DIRECT: fRet = TRUE; break; default: fRet = TRUE; break; } //return fRet;
PerfDbgLog(tagCINet, this, "-CINet::OperationOnAparmentThread");
DEBUG_LEAVE(TRUE); return TRUE; }
//+---------------------------------------------------------------------------
//
// Method: CINet::OperationOnAparmentThread
//
// Synopsis:
//
// Returns:
//
// History: 10-27-98 DanpoZ (Danpo Zhang) Created
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL CINet::UTF8Enabled() { DEBUG_ENTER((DBG_APP, Bool, "CINet::UTF8Enabled", "this=%#x", this )); BOOL bRet = FALSE; // do not enable utf8 on file or ftp protocol
if( _dwIsA == DLD_PROTOCOL_FILE || _dwIsA == DLD_PROTOCOL_FTP ) { goto exit; }
// default to per-machine utf-8 setting
bRet = g_bGlobalUTF8Enabled;
// per-binding flag
if( _BndInfo.dwOptions & BINDINFO_OPTIONS_ENABLE_UTF8) { bRet = TRUE; }
if( _BndInfo.dwOptions & BINDINFO_OPTIONS_DISABLE_UTF8) { bRet = FALSE; }
if( _BndInfo.dwOptions & BINDINFO_OPTIONS_USE_IE_ENCODING) { DWORD dwIE; DWORD dwOutLen = sizeof(DWORD); HRESULT hr = UrlMkGetSessionOption( URLMON_OPTION_URL_ENCODING, &dwIE, sizeof(DWORD), &dwOutLen, NULL );
if( hr == NOERROR ) { if( dwIE == URL_ENCODING_ENABLE_UTF8 ) { bRet = TRUE; } else if( dwIE == URL_ENCODING_DISABLE_UTF8 ) { bRet = FALSE; } } }
exit:
DEBUG_LEAVE(bRet); return bRet; }
//+---------------------------------------------------------------------------
//
// Method: CINet::QueryInfoOnResponse
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::QueryInfoOnResponse() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::QueryInfoOnResponse", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::QueryInfoOnResponse"); HRESULT hr = NOERROR;
DWORD dwFlags; DWORD cbLen = sizeof(dwFlags);
// See if it is from the cache
if (InternetQueryOption(_hRequest, INTERNET_OPTION_REQUEST_FLAGS, &dwFlags, &cbLen)) { if (dwFlags & INTERNET_REQFLAG_FROM_CACHE) { _dwCacheFlags |= INTERNET_REQFLAG_FROM_CACHE; // set flag that data are from cache
_bscf |= BSCF_DATAFULLYAVAILABLE; } }
hr = QueryStatusOnResponse(); if (hr == NOERROR) { hr = QueryHeaderOnResponse(); }
if (_hrError != INET_E_OK) { SetINetState(INetState_DONE); }
PerfDbgLog1(tagCINet, this, "-CINet::QueryInfoOnResponse (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::QueryStatusOnResponse
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::QueryStatusOnResponse() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::QueryStatusOnResponse", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::QueryStatusOnResponse");
PProtAssert((FALSE));
PerfDbgLog1(tagCINet, this, "-CINet::QueryStatusOnResponse hr:%lx", E_FAIL);
DEBUG_LEAVE(E_FAIL); return E_FAIL; }
//+---------------------------------------------------------------------------
//
// Method: CINet::QueryStatusOnResponseDefault
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::QueryStatusOnResponseDefault(DWORD dwStat) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::QueryStatusOnResponseDefault", "this=%#x, %#x", this, dwStat )); PerfDbgLog(tagCINet, this, "+CINet::QueryStatusOnResponseDefault");
PProtAssert((FALSE));
PerfDbgLog1(tagCINet, this, "-CINet::QueryStatusOnResponseDefault hr:%lx", E_FAIL);
DEBUG_LEAVE(E_FAIL); return E_FAIL; }
//+---------------------------------------------------------------------------
//
// Method: CINet::QueryHeaderOnResponse
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::QueryHeaderOnResponse() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::QueryHeaderOnResponse", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::QueryHeaderOnResponse");
PProtAssert((FALSE));
PerfDbgLog1(tagCINet, this, "-CINet::QueryHeaderOnResponse hr:%lx", E_FAIL);
DEBUG_LEAVE(E_FAIL); return E_FAIL; }
//+---------------------------------------------------------------------------
//
// Method: CINet::RedirectRequest
//
// Synopsis:
//
// Arguments: [lpszBuffer] --
// [pdwBuffSize] --
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::RedirectRequest(LPSTR lpszBuffer, DWORD *pdwBuffSize, DWORD dwStatus) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::RedirectRequest", "this=%#x, %#x, %#x, %d", this, lpszBuffer, pdwBuffSize, dwStatus )); PerfDbgLog(tagCINet, this, "+CINet::RedirectRequest");
PProtAssert((FALSE));
PerfDbgLog1(tagCINet, this, "-CINet::RedirectRequest(fRet:%ld)", FALSE);
DEBUG_LEAVE(E_FAIL); return E_FAIL; }
//+---------------------------------------------------------------------------
//
// Method: CINet::AuthenticationRequest
//
// Synopsis:
//
// Arguments: [lpszBuffer] --
// [pdwBuffSize] --
//
// Returns:
//
// History: 2-06-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::AuthenticationRequest() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::AuthenticationRequest", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::AuthenticationRequest"); HRESULT hr = NOERROR; DWORD dwError;
LPWSTR pwzUsername = NULL; LPWSTR pwzPassword = NULL;
DWORD dwBindF = GetBindFlags();
PerfDbgLog2(tagCINet, this, "<1> _cbProxyAuthenticate:%d _cbAuthenticate:%d", _cbProxyAuthenticate, _cbAuthenticate); if (_fProxyAuth ? (_cbProxyAuthenticate >= AUTHENTICATE_MAX):(_cbAuthenticate >= AUTHENTICATE_MAX)) { // NOTE: set the error to noerror and
// continue reading data and show the 401 contained
_hrINet = hr = NOERROR; } else { if (_hwndAuth == NULL) { IAuthenticate *pPInfo; DbgLog(tagCINetErr, this, "+CINet::AuthenticationRequest: QS for IAuthenticate"); hr = QueryService(IID_IAuthenticate, (void **)&pPInfo); if (hr == NOERROR) { PProtAssert((pPInfo)); hr = pPInfo->Authenticate(&_hwndAuth, &pwzUsername, &pwzPassword); pPInfo->Release(); } }
if (hr == NOERROR) { _hrINet = hr = E_ACCESSDENIED;
if (pwzUsername && pwzPassword) { // set the username and password
// and retry sendrequest
LPSTR pszUsername = DupW2A(pwzUsername); LPSTR pszPassword = DupW2A(pwzPassword);
if (pszUsername) { InternetSetOption(_hRequest, INTERNET_OPTION_USERNAME, pszUsername, strlen(pszUsername)+1); delete pszUsername; } if (pszPassword) { InternetSetOption(_hRequest, INTERNET_OPTION_PASSWORD, pszPassword, strlen(pszPassword)+1); delete pszPassword; }
// if we got username & pwd, only try once
_fProxyAuth ? _cbProxyAuthenticate = AUTHENTICATE_MAX : _cbAuthenticate = AUTHENTICATE_MAX; _hrINet = hr = RPC_E_RETRY; PerfDbgLog2(tagCINet, this, "<2> _cbProxyAuthenticate:%d _cbAuthenticate:%d", _cbProxyAuthenticate, _cbAuthenticate); }
if ( (_hwndAuth || (_hwndAuth == (HWND)-1) ) && (_pCAuthData == NULL) && (hr != RPC_E_RETRY) )
{ PProtAssert((_pCAuthData == NULL)); _pCAuthData = new CAuthData(this); }
if ( (_hwndAuth || (_hwndAuth == (HWND)-1) ) && _pCAuthData && (hr != RPC_E_RETRY) ) { BOOL fRetry = FALSE; BOOL fDeleteAuthData = TRUE; DWORD dwFlags = ( FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA | FLAGS_ERROR_UI_SERIALIZE_DIALOGS);
if ((dwBindF & BINDF_NO_UI) || (dwBindF & BINDF_SILENTOPERATION)) { dwFlags |= FLAGS_ERROR_UI_FLAGS_NO_UI; }
if (_hwndAuth == (HWND)-1) { _hwndAuth = 0; }
do { _fProxyAuth ? _cbProxyAuthenticate++ : _cbAuthenticate++; PerfDbgLog2(tagCINet, this, "<3> _cbProxyAuthenticate:%d _cbAuthenticate:%d", _cbProxyAuthenticate, _cbAuthenticate);
dwError = InternetErrorDlg(_hwndAuth,_hRequest,ERROR_SUCCESS,dwFlags,(LPVOID *)&_pCAuthData);
switch (dwError) { case ERROR_CANCELLED : // wininet should never return cancelled here
PProtAssert((FALSE)); case ERROR_SUCCESS : // NOTE: succes and cancel means display the content according to ArthurBi
// continue reading data and show the 401 contained
_hrINet = hr = NOERROR; break;
case ERROR_INTERNET_FORCE_RETRY : _hrINet = hr = RPC_E_RETRY; break;
case ERROR_INTERNET_DIALOG_PENDING : // a dialog is up on another thread
// start wating on the callback
SetINetState(INetState_AUTHENTICATE); SetStatePending(E_PENDING); _fProxyAuth ? _cbProxyAuthenticate-- : _cbAuthenticate--; PerfDbgLog2(tagCINet, this, "<4> _cbProxyAuthenticate:%d _cbAuthenticate:%d", _cbProxyAuthenticate, _cbAuthenticate); fDeleteAuthData = FALSE; _hrINet = hr = E_PENDING; break;
case ERROR_INTERNET_RETRY_DIALOG: _fProxyAuth ? _cbProxyAuthenticate-- : _cbAuthenticate--; PerfDbgLog2(tagCINet, this, "<5> _cbProxyAuthenticate:%d _cbAuthenticate:%d", _cbProxyAuthenticate, _cbAuthenticate); fRetry = TRUE; break;
default: _hrINet = hr = E_ACCESSDENIED; break; }
} while (fRetry);
if (fDeleteAuthData) { delete _pCAuthData; _pCAuthData = NULL; }
} } else { _hrINet = hr = E_ACCESSDENIED; }
if (hr == RPC_E_RETRY) { _hrINet = NOERROR; _fCompleted = FALSE; _fSendAgain = TRUE; if (IsA() == DLD_PROTOCOL_FTP || IsA() == DLD_PROTOCOL_GOPHER) { // Retry InternetOpenUrl using the updated auth info.
_fDoSimpleRetry = TRUE; hr = INetAsyncOpenRequest(); } else { hr = INetAsyncSendRequest(); } } else if (hr == E_PENDING) { // do nothing and wait for async completion
} else if ( (hr != HRESULT_FROM_WIN32(ERROR_CANCELLED)) && (hr != NOERROR)) { // set the error to access denied
_hrINet = hr = E_ACCESSDENIED; } }
if (pwzUsername) { delete pwzUsername; } if (pwzPassword) { delete pwzPassword; }
PerfDbgLog1(tagCINet, this, "-CINet::AuthenticationRequest(hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::GetUrlCacheFilename
//
// Synopsis:
//
// Arguments: [szFilename] --
// [dwSize] --
//
// Returns:
//
// History: 2-28-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::GetUrlCacheFilename(LPSTR szFilename, DWORD dwSize) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::GetUrlCacheFilename", "this=%#x, %#x, %#x", this, szFilename, dwSize )); PerfDbgLog(tagCINet, this, "+CINet::GetUrlCacheFilename"); HRESULT hr = NOERROR; BOOL fRet = FALSE; DWORD dwSizeLocal = dwSize; DWORD dwError = 0;
if (dwSize) { szFilename[0] = '\0'; }
if ( !(GetBindFlags() & BINDF_NOWRITECACHE) || (GetBindFlags() & BINDF_NEEDFILE)) { fRet = InternetQueryOption(_hRequest, INTERNET_OPTION_DATAFILE_NAME, szFilename, &dwSizeLocal);
if (!fRet && (GetBindFlags() & BINDF_NEEDFILE)) { dwError = GetLastError(); hr = INET_E_DATA_NOT_AVAILABLE; SetBindResult(dwError, hr); if (dwSize) { szFilename[0] = '\0'; } } }
PerfDbgLog3(tagCINet, this, "-CINet::GetUrlCacheFilename (hr:%lx,fRet%d; szFilename:%s)", hr, fRet, szFilename);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::LockFile
//
// Synopsis:
//
// Arguments: [szFilename] --
// [dwSize] --
//
// Returns:
//
// History: 8-13-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::LockFile(BOOL fRetrieve) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::LockFile", "this=%#x, %B", this, fRetrieve )); PerfDbgLog(tagCINet, this, "+CINet::LockFile"); HRESULT hr = NOERROR; BOOL fRet = FALSE;
if (fRetrieve) { DWORD dwCacheEntryInfoBufferSize = MAX_URL_SIZE + MAX_PATH + sizeof(INTERNET_CACHE_ENTRY_INFO) + 2; INTERNET_CACHE_ENTRY_INFO *pCacheEntryInfo = (INTERNET_CACHE_ENTRY_INFO *)new CHAR [dwCacheEntryInfoBufferSize]; DWORD dwError = 0; if ( (_fLocked == FALSE) && (pCacheEntryInfo != NULL) && (RetrieveUrlCacheEntryFileA( _pszFullURL, pCacheEntryInfo, &dwCacheEntryInfoBufferSize, 0))) { _fLocked = TRUE; }
if (pCacheEntryInfo != NULL) { delete pCacheEntryInfo; } } else if ((_hLockHandle == NULL) && _hRequest) { if (InternetLockRequestFile(_hRequest, &_hLockHandle)) { PProtAssert((_hLockHandle)); } }
PerfDbgLog2(tagCINet, this, "-CINet::LockFile (hr:%lx,fRet%d)", hr, fRet);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::UnlockFile
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 8-13-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::UnlockFile() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::UnlockFile", "this=%#x", this )); PerfDbgLog(tagCINet, this, "IN CINet::UnlockFile"); HRESULT hr = NOERROR;
if (_fLocked) { UnlockUrlCacheEntryFileA(_pszFullURL, 0); _fLocked = FALSE; } else if (_hLockHandle) { if (InternetUnlockRequestFile(_hLockHandle)) { _hLockHandle = NULL; } }
PerfDbgLog1(tagCINet, this, "-CINet::UnlockFile (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::HResultFromInternetError
//
// Synopsis: maps the dwStatus ERROR_INTERNET_XXX do an hresult
//
// Arguments: [dwStatus] --
//
// Returns:
//
// History: 3-22-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::HResultFromInternetError(DWORD dwStatus) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::HResultFromInternetError", "this=%#x, %#x", this, dwStatus )); PerfDbgLog(tagCINet, this, "+CINet::HResultFromInternetError"); // dwResult is out of our know table
HRESULT hr = INET_E_DOWNLOAD_FAILURE; ULONG ulIndex = dwStatus - INTERNET_ERROR_BASE;
PProtAssert((ulIndex > 0)); BOOL fTable1 = (ulIndex > 0 && ulIndex < sizeof(INetError)/sizeof(InterErrorToHResult)); DWORD dwTable2Size = sizeof(INetErrorExtended)/sizeof(InterErrorToHResult); BOOL fTable2 = FALSE;
if (!fTable1) { fTable2 = (dwStatus <= INetErrorExtended[dwTable2Size].dwError); } if (fTable1) { // sequential table
hr = INetError[ulIndex].hresult; } else if (fTable2) { // walk the table
for (DWORD i = 0; i < dwTable2Size; i++) { if (INetErrorExtended[i].dwError == dwStatus) { hr = INetErrorExtended[i].hresult; break; } } }
PerfDbgLog1(tagCINet, this, "-CINet::HResultFromInternetError (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; } //+---------------------------------------------------------------------------
//
// Function: SetBindResult
//
// Synopsis:
//
// Arguments: [dwResult] --
//
// Returns:
//
// History: 5-10-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::SetBindResult(DWORD dwResult, HRESULT hrSuggested) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::SetBindResult", "this=%#x, %#x, %#x", this, dwResult, hrSuggested )); PerfDbgLog2(tagCINet, this, "+CINet::SetBindResult(dwResult:%ld, hrSuggested:%lx)", dwResult, hrSuggested); HRESULT hr = NOERROR;
PProtAssert((_pszResult == NULL)); _pszResult = NULL; _dwResult = dwResult;
// only find hresult in the mapping table
// if no erro was suggested
if (hrSuggested == NOERROR) { hr = _hrINet = HResultFromInternetError(_dwResult); } else { hr = _hrINet = hrSuggested; }
PerfDbgLog3(tagCINet, this, "-CINet::SetBindResult (dwResult:%ld, _hrINet:%lx, hr:%lx)", dwResult, _hrINet, hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::GetBindResult
//
// Synopsis: returns the protocol specific error
//
// Arguments: [pclsidProtocol] --
// [pdwResult] --
// [DWORD] --
// [pdwReserved] --
//
// Returns:
//
// History: 4-16-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::GetBindResult(CLSID *pclsidProtocol, DWORD *pdwResult, LPWSTR *pszResult, DWORD *pdwReserved) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::GetBindResult", "this=%#x, %#x, %#x, %#x, %#x", this, pclsidProtocol, pdwResult, pszResult, pdwReserved )); PerfDbgLog(tagCINet, this, "+CINet::GetBindResult"); HRESULT hr = NOERROR;
PProtAssert((pclsidProtocol && pdwResult && pszResult));
*pclsidProtocol = _pclsidProtocol; *pdwResult = _dwResult; if (_pszResult) { // the client is supposted to free the string
*pszResult = new WCHAR [strlen(_pszResult) + 1]; if (*pszResult) { A2W(_pszResult, *pszResult, strlen(_pszResult)); } } else { *pszResult = NULL; }
PerfDbgLog2(tagCINet, this, "-CINet::GetBindResult (dwResult:%lx, szStr:%ws)", _dwResult, pszResult);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::OnRedirected
//
// Synopsis: Called on wininet worker thread when wininet does a redirect.
// Sends notification to apartment thread.
//
// Arguments: [szNewUrl] --
//
// Returns:
//
// History: 4-17-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::OnRedirect(LPSTR szNewUrl) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::OnRedirect", "this=%#x, %.80q", this, szNewUrl )); PerfDbgLog1(tagCINet, this, "+CINet::OnRedirect (szNewUrl:%s)",szNewUrl); HRESULT hr = NOERROR;
PProtAssert((szNewUrl && "WinINet reports redirect with redirect URL"));
if (szNewUrl) { _fRedirected = TRUE; ReportNotification(BINDSTATUS_REDIRECTING, szNewUrl); }
LONG lThirdParty; if (IsThirdPartyUrl(szNewUrl)) { lThirdParty = 1; //MessageBoxA( 0, szNewUrl, "redirect: THIRDPARTY!", 0 );
InternetSetOption(_hRequest, INTERNET_OPTION_COOKIES_3RD_PARTY, &lThirdParty, sizeof(LONG)); } else { lThirdParty = 0; //MessageBoxA( 0, szNewUrl, "redirect: NOT THIRDPARTY!", 0 );
InternetSetOption(_hRequest, INTERNET_OPTION_COOKIES_3RD_PARTY, &lThirdParty, sizeof(LONG)); } PerfDbgLog1(tagCINet, this, "-CINet::OnRedirect(hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: AppendToString
//
// Synopsis: Fast append of src to dest, reallocing of dest if necessary.
//
//
// Arguments: [IN/OUT] pszDest
// [IN/OUT] pcbDest
// [IN/OUT] pcbAlloced
// [IN] szSrc
// [IN] cbSrc
//
// Returns: TRUE/FALSE
//
// History: 6-2-97 Adriaan Canter (AdriaanC) Created
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL AppendToString(LPSTR* pszDest, LPDWORD pcbDest, LPDWORD pcbAlloced, LPSTR szSrc, DWORD cbSrc) { DEBUG_ENTER((DBG_APP, Bool, "AppendToString", "%#x, %#x, %#x, %.80q, %#x", pszDest, pcbDest, pcbAlloced, szSrc, cbSrc )); DWORD cbNew = *pcbDest + cbSrc;
if (cbNew > *pcbAlloced) { DWORD cbNewAlloc = *pcbAlloced + (cbSrc < MAX_PATH ? MAX_PATH : cbSrc); LPSTR szNew = (LPSTR) new CHAR[cbNewAlloc]; if (!szNew) {
DEBUG_LEAVE(FALSE); return FALSE; } memcpy(szNew, *pszDest, *pcbDest); delete [] *pszDest; *pszDest = szNew; *pcbAlloced = cbNewAlloc; }
memcpy(*pszDest + *pcbDest, szSrc, cbSrc); *pcbDest = cbNew;
DEBUG_LEAVE(TRUE); return TRUE; }
#ifdef unix
#include <sys/utsname.h>
#endif /* unix */
//+---------------------------------------------------------------------------
//
// Function: GetUserAgentString
//
// Synopsis: Gets the user agent string from the registry. If entry is
// the default string is returned.
//
// Arguments: (none)
//
// Returns: Allocated user agent string.
//
// History: 5-13-96 JohannP (Johann Posch) Created
// 6-02-97 AdriaanC (Adriaan Canter) Mods for mult reg entries.
//
// 6-25-97 AdriaanC (Adriaan Canter) Further mods described below.
//
// 12-18-98 Adriaanc (Adriaan Canter) - Versioned base values for
// IE5 and added a versioned IE5 location for token values
// which will get read in addition to common (IE4) location.
//
// Notes: User Agent string madness: We now generate the User Agent string
// from diverse entries in the registry. We first scan HKCU for base
// keys, falling back to HKLM if not found, or finally, defaults.
// For Pre and Post platform we now pickup all entries in both HKCU
// and HKLM. Finally, for back compatibility we enumerate a list of
// tokens (such as MSN 2.0, MSN 2.1, etc) from UA Tokens in the HKLM
// registry under Internet Settings, and if any of these tokens are
// found in the *old* HKCU location User Agent String we insert them
// into the pre platform portion of the generated user agent string.
// This was specifically done for MSN which has been fixing up the old
// registry location and depends on these tokens being found in the
// User Agent string.
//
//----------------------------------------------------------------------------
LPCSTR GetUserAgentString() { DEBUG_ENTER((DBG_APP, String, "GetUserAgentString", NULL )); // Reg keys.
#define INTERNET_SETTINGS_KEY_SZ "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
#define USER_AGENT_KEY_SZ "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\User Agent"
#define USER_AGENT_KEY5_SZ "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\5.0\\User Agent"
#define USER_AGENT_SZ "User Agent"
#define PRE_PLATFORM_KEY_SZ "Pre Platform"
#define POST_PLATFORM_KEY_SZ "Post Platform"
#define UA_TOKENS_KEY_SZ "UA Tokens"
// Base UA key strings.
#define UA_KEY_SZ NULL
#define COMPATIBLE_KEY_SZ "Compatible"
#define VERSION_KEY_SZ "Version"
#define PLATFORM_KEY_SZ "Platform"
// Base UA value strings.
#define UA_VAL_SZ "Mozilla/4.0"
#define COMPATIBLE_VAL_SZ "compatible"
#define VERSION_VAL_SZ "MSIE 6.0"
// Their lengths.
#define UA_VAL_LEN (sizeof(UA_VAL_SZ) - 1)
#define COMPATIBLE_VAL_LEN (sizeof(COMPATIBLE_VAL_SZ) - 1)
#define VERSION_VAL_LEN (sizeof(VERSION_VAL_SZ) - 1)
// If we encounter a failure in constructing the string, send this.
#ifdef _WIN64
#define DEFAULT_UA_STRING UA_VAL_SZ" ("COMPATIBLE_VAL_SZ"; "VERSION_VAL_SZ"; Win64)"
#else
#define DEFAULT_UA_STRING UA_VAL_SZ" ("COMPATIBLE_VAL_SZ"; "VERSION_VAL_SZ")"
#endif
// Used for backing up user agent string.
#define IE4_UA_BACKUP_FLAG "IE5_UA_Backup_Flag"
#define BACKUP_USER_AGENT_SZ "BackupUserAgent"
#define COMPAT_MODE_TOKEN "compat"
#define NUM_UA_KEYS 4
BOOL bSuccess = TRUE; INT i, nBaseKeys; DWORD dwIndex, dwType, cbBuf, cbUA, cbTotal; LPSTR szUA, szBuf, pszWinVer; OSVERSIONINFO osVersionInfo;
// Reg handles.
HKEY hHKCU_ISKey; HKEY hHKCU_UAKey; HKEY hHKLM_UAKey; HKEY hHKCU_UA5Key; HKEY hHKLM_UA5Key; HKEY hPreKey; HKEY hPostKey; HKEY hTokensKey;
// Set all regkeys to invalid handle.
hHKCU_ISKey = hHKLM_UAKey = hHKCU_UAKey = hHKLM_UA5Key = hHKCU_UA5Key = hPreKey = hPostKey = hTokensKey = (HKEY) INVALID_HANDLE_VALUE;
// The UA keys are iterated in loops below; Keep an array
// of pointers to the HKLMUA, HKCUUA, HKLMUA5 and HKCUUA5 locations
// to use as alias in the loop. NOTE!! - Do not change the ordering.
HKEY *phUAKeyArray[NUM_UA_KEYS]; phUAKeyArray[0] = &hHKLM_UAKey; phUAKeyArray[1] = &hHKCU_UAKey; phUAKeyArray[2] = &hHKLM_UA5Key; phUAKeyArray[3] = &hHKCU_UA5Key;
// Platform strings.
LPSTR szWin32 = "Win32"; LPSTR szWin95 = "Windows 95"; LPSTR szWin98 = "Windows 98"; LPSTR szMillennium = "Windows 98; Win 9x 4.90"; LPSTR szWinNT = "Windows NT"; //for WinNT appended with version numbers
//Note: Limitation on total# of digits in Major+Minor versions=8.
//length = sizeof("Windows NT"+" "+majorverstring+"."+minorverstring
//Additional allowance is made for Win64 token.
#define WINNT_VERSION_STRING_MAX_LEN 32
char szWinNTVer[WINNT_VERSION_STRING_MAX_LEN];
#ifdef unix
CHAR szUnixPlatformName[SYS_NMLN*4+3+1]; // 4 substrings,3 spaces, 1 NULL
#endif /* unix */
// Arrays of base keys, values and lengths.
LPSTR szBaseKeys[] = {UA_KEY_SZ, COMPATIBLE_KEY_SZ, VERSION_KEY_SZ}; LPSTR szBaseValues[] = {UA_VAL_SZ, COMPATIBLE_VAL_SZ, VERSION_VAL_SZ}; DWORD cbBaseValues[] = {UA_VAL_LEN, COMPATIBLE_VAL_LEN, VERSION_VAL_LEN};
nBaseKeys = sizeof(szBaseKeys) / sizeof(LPSTR);
cbUA = 0; cbTotal = cbBuf = MAX_PATH; szBuf = szUA = 0;
// User agent string already exists.
if (g_pszUserAgentString != NULL) { szUA = g_pszUserAgentString; goto End; }
// Max size for any one field from registry is MAX_PATH.
szUA = new CHAR[MAX_PATH]; szBuf = new CHAR[MAX_PATH]; if (!szUA || !szBuf) { bSuccess = FALSE; goto End; }
// Open all 4 User Agent reg keys (HKLMUA, HKCUUA, HKLMUA5, HKCUUA5).
if (RegOpenKeyEx(HKEY_CURRENT_USER, USER_AGENT_KEY_SZ, 0, KEY_QUERY_VALUE, &hHKCU_UAKey) != ERROR_SUCCESS) hHKCU_UAKey = (HKEY)INVALID_HANDLE_VALUE;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, USER_AGENT_KEY_SZ, 0, KEY_QUERY_VALUE, &hHKLM_UAKey) != ERROR_SUCCESS) hHKLM_UAKey = (HKEY)INVALID_HANDLE_VALUE;
if (RegOpenKeyEx(HKEY_CURRENT_USER, USER_AGENT_KEY5_SZ, 0, KEY_QUERY_VALUE, &hHKCU_UA5Key) != ERROR_SUCCESS) hHKCU_UA5Key = (HKEY)INVALID_HANDLE_VALUE;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, USER_AGENT_KEY5_SZ, 0, KEY_QUERY_VALUE, &hHKLM_UA5Key) != ERROR_SUCCESS) hHKLM_UA5Key = (HKEY)INVALID_HANDLE_VALUE;
// Get user agent, compatible and version strings from IE 5.0 location.
// IE6 and on must revise this location.
for (i = 0; i < nBaseKeys; i++) { if ((hHKCU_UA5Key != INVALID_HANDLE_VALUE) && RegQueryValueEx(hHKCU_UA5Key, szBaseKeys[i], NULL, &dwType, (LPBYTE) szBuf, &(cbBuf = MAX_PATH)) == ERROR_SUCCESS && cbBuf > 1) { // Got from HKCU registry.
if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, szBuf, cbBuf - 1))) goto End; } else if ((hHKLM_UA5Key != INVALID_HANDLE_VALUE) && RegQueryValueEx(hHKLM_UA5Key, szBaseKeys[i], NULL, &dwType, (LPBYTE) szBuf, &(cbBuf = MAX_PATH)) == ERROR_SUCCESS && cbBuf > 1) { // Got from HKLM registry.
if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, szBuf, cbBuf - 1))) goto End; } else { // Got from defaults.
if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, szBaseValues[i], cbBaseValues[i]))) goto End; }
// Formating.
if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, (i == 0 ? " (" : "; "), 2))) goto End; }
// Leave the four UA keys open; Proceed to open HKLM tokens key to scan
// to scan and open Internet Settings HKCU key to read legacy UA string.
// Tokens to scan for from the old registry location to include
// in the user agent string: These are enumerated from UA Tokens,
// scanned for in the old location and added to the pre platform.
if (hHKLM_UAKey != INVALID_HANDLE_VALUE) RegOpenKeyEx(hHKLM_UAKey, UA_TOKENS_KEY_SZ, 0, KEY_QUERY_VALUE, &hTokensKey);
if (hTokensKey != INVALID_HANDLE_VALUE) { CHAR szOldUserAgentString[MAX_PATH];
// Read in the old user agent string from HKCU
RegOpenKeyEx(HKEY_CURRENT_USER, INTERNET_SETTINGS_KEY_SZ, 0, KEY_QUERY_VALUE, &hHKCU_ISKey);
if ((hHKCU_ISKey != INVALID_HANDLE_VALUE) && RegQueryValueEx(hHKCU_ISKey, USER_AGENT_SZ, NULL, &dwType, (LPBYTE) szOldUserAgentString, &(cbBuf = MAX_PATH)) == ERROR_SUCCESS && cbBuf > 1) { // Close the HKCU Internet Settings key.
RegCloseKey(hHKCU_ISKey); hHKCU_ISKey = (HKEY) INVALID_HANDLE_VALUE;
// Got old user agent string from HKCU registry. Enumerate the values in UA Tokens
// and see if any exist in the old string and if so, add them to the current string.
dwIndex = 0; #ifndef unix
while (RegEnumValue(hTokensKey, dwIndex++, szBuf, &(cbBuf = MAX_PATH - 4), /* sizeof(' ' + "; ") */ NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { // eg; find a token enumerated from UA Tokens
// Mozilla/4.0 (compatible; MSIE 4.0b2; MSN2.5; Windows NT)
// ^
// szBuf
if (cbBuf) { // Fix up token to include leading
// space and trailing semi-colon before strstr.
CHAR szToken[MAX_PATH]; szToken[0] = ' '; memcpy(szToken+1, szBuf, cbBuf); memcpy(szToken + 1 + cbBuf, "; ", sizeof("; "));
// Found a match - insert this token into user agent string.
if (strstr(szOldUserAgentString, szToken)) { if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, szBuf, cbBuf))) goto End;
if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, "; ", 2))) goto End; } } } #endif /* !unix */
}
RegCloseKey(hTokensKey); hTokensKey = (HKEY) INVALID_HANDLE_VALUE; }
// Pre platform strings - get from HKCUUA, HKLMUA,
// HKLMUA5 and HKCUUA5 locations. These are additive;
// order is not important.
for (i = 0; i < NUM_UA_KEYS; i++) { if (*(phUAKeyArray[i]) == INVALID_HANDLE_VALUE) continue;
RegOpenKeyEx(*(phUAKeyArray[i]), PRE_PLATFORM_KEY_SZ, 0, KEY_QUERY_VALUE, &hPreKey);
if (hPreKey != INVALID_HANDLE_VALUE) { dwIndex = 0; while (RegEnumValue(hPreKey, dwIndex++, szBuf, &(cbBuf = MAX_PATH), NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { if (cbBuf) { // Got from registry and non null.
if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, szBuf, cbBuf))) goto End; if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, "; ", 2))) goto End; } cbBuf = MAX_PATH; }
// Close pre platform key; User agent keys still open.
RegCloseKey(hPreKey); hPreKey = (HKEY) INVALID_HANDLE_VALUE; } }
// Platform string. This is read from the IE 5.0 location only. IE6 and later
// must revise this. If no platform value read from registry, get from OS.
if (hHKCU_UA5Key != INVALID_HANDLE_VALUE && RegQueryValueEx(hHKCU_UA5Key, PLATFORM_KEY_SZ, NULL, &dwType, (LPBYTE) szBuf, &(cbBuf = MAX_PATH)) == ERROR_SUCCESS) { // Got from HKCU.
if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, szBuf, cbBuf -1))) goto End; } else if (hHKLM_UA5Key != INVALID_HANDLE_VALUE && RegQueryValueEx(hHKLM_UA5Key, PLATFORM_KEY_SZ, NULL, &dwType, (LPBYTE) szBuf, &(cbBuf = MAX_PATH)) == ERROR_SUCCESS) { // Got from HKLM
if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, szBuf, cbBuf -1))) goto End; } else { // Couldn't get User Agent value from registry.
// Set the default value.
osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (GetVersionEx(&osVersionInfo)) { #ifndef unix
// Platform ID is either Win95 or WinNT.
if(VER_PLATFORM_WIN32_NT == osVersionInfo.dwPlatformId) { Assert(osVersionInfo.dwMajorVersion < 10000 && osVersionInfo.dwMinorVersion < 10000); /* Check for WIN64, adding another token if necessary */ LPSTR szWin64Token = "; Win64"; LPSTR szWow64Token = "; WOW64";
SYSTEM_INFO SysInfo;
GetSystemInfo(&SysInfo); bool fWin64 = ((SysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) || (SysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)); bool fWow64 = FALSE;
// There is no easy way to determine whether a 32-bit app is running on a 32-bit OS
// or Wow64. The recommended approach (Q275217) to determine this is to see if
// GetSystemWow64DirectoryA is implemented in kernel32.dll and to see if the function
// succeeds. If it succeeds, then we're running on a 64-bit processor.
if (!fWin64 && SysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) { char directoryPath[MAX_PATH]; HMODULE hModule; GetSystemWow64DirectoryPtr func;
hModule = GetModuleHandle("kernel32.dll"); func = (GetSystemWow64DirectoryPtr) GetProcAddress(hModule, "GetSystemWow64DirectoryA"); if (func && func(directoryPath, sizeof(directoryPath))) { fWow64 = TRUE; } }
LPSTR sz64Str = NULL; if( fWin64) sz64Str = szWin64Token; else if( fWow64) sz64Str = szWow64Token; else sz64Str = "";
memset(szWinNTVer, 0, WINNT_VERSION_STRING_MAX_LEN); wsprintfA(szWinNTVer, "%s %u.%u%s", szWinNT, osVersionInfo.dwMajorVersion, osVersionInfo.dwMinorVersion, sz64Str);
pszWinVer = szWinNTVer; } else { if(osVersionInfo.dwMinorVersion >= 10) { if(osVersionInfo.dwMinorVersion >= 90) { // Millennium
pszWinVer = szMillennium; } else { // Win98
pszWinVer = szWin98; } } else { // Win95
pszWinVer = szWin95; } } #else
struct utsname uName; if(uname(&uName) > -1) { strcpy(szUnixPlatformName,uName.sysname); strcat(szUnixPlatformName," "); strcat(szUnixPlatformName,uName.release); strcat(szUnixPlatformName," "); strcat(szUnixPlatformName,uName.machine); strcat(szUnixPlatformName,"; X11"); pszWinVer = &szUnixPlatformName[0]; } else pszWinVer = "Generic Unix"; #endif /* unix */
} else { // GetVersionEx failed! - set Platform to Win32.
pszWinVer = szWin32; } if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, pszWinVer, strlen(pszWinVer)))) goto End; }
// Post platform strings - get from HKCUUA, HKLMUA,
// HKLMUA5 and HKCUUA5 locations. These are additive;
// order is not important. Special case the IE4
// compat token. IE6 and later must do this also.
for (i = 0; i < NUM_UA_KEYS; i++) { if (*(phUAKeyArray[i]) == INVALID_HANDLE_VALUE) continue;
RegOpenKeyEx(*(phUAKeyArray[i]), POST_PLATFORM_KEY_SZ, 0, KEY_QUERY_VALUE, &hPostKey);
if (hPostKey != INVALID_HANDLE_VALUE) { dwIndex = 0; while (RegEnumValue(hPostKey, dwIndex++, szBuf, &(cbBuf = MAX_PATH), NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { // We need to special case the IE4 compat mode token in the
// first two keys in phUAKeyArray[];
if (cbBuf && ((i > 1) || strcmp(szBuf, COMPAT_MODE_TOKEN))) { // Got from registry and non null.
if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, "; ", 2))) goto End; if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, szBuf, cbBuf))) goto End; } cbBuf = MAX_PATH; }
// Close post platform key; User agent keys still open.
RegCloseKey(hPostKey); hPostKey = (HKEY) INVALID_HANDLE_VALUE; } } // Terminate with ")\0"
if (!(bSuccess = AppendToString(&szUA, &cbUA, &cbTotal, ")", 2))) goto End;
for (i = 0; i < NUM_UA_KEYS; i++) { if (*(phUAKeyArray[i]) != INVALID_HANDLE_VALUE) { RegCloseKey(*(phUAKeyArray[i])); *(phUAKeyArray[i]) = (HKEY) INVALID_HANDLE_VALUE; } }
// Finally, write out the generated user agent string in the old location.
if (bSuccess) { // Remember the computed user agent string for later.
g_pszUserAgentString = szUA; }
End:
// Cleanup.
delete [] szBuf;
if (!bSuccess) { delete [] szUA;
DEBUG_LEAVE(DEFAULT_UA_STRING); return DEFAULT_UA_STRING; }
DEBUG_LEAVE(szUA); return szUA; }
//+---------------------------------------------------------------------------
//
// Method: ObtainUserAgentString
//
// Synopsis:
//
// Returns:
//
// History: 08-07-1997 DanpoZ (Danpo Zhang) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI ObtainUserAgentString(DWORD dwOption, LPSTR pszUAOut, DWORD *cbSize ) { DEBUG_ENTER_API((DBG_API, Hresult, "ObtainUserAgentString", "%#x, %#x, %#x", dwOption, pszUAOut, cbSize )); // since GetUserAgentString may change some global variable,
// this API needs to add a global mutex to protect them
CLock lck(g_mxsSession);
HRESULT hr = NOERROR; if( pszUAOut && cbSize ) { LPSTR pcszUA = (LPSTR)GetUserAgentString(); DWORD cbLen = strlen(pcszUA);
if( *cbSize <= cbLen ) { hr = E_OUTOFMEMORY; } else { strcpy(pszUAOut, pcszUA); } *cbSize = cbLen + 1;
} else { hr = E_INVALIDARG; }
DEBUG_LEAVE_API(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::InternetAuthNotifyCallback
//
// Synopsis:
//
// Arguments: [dwContext] --
// [dwAction] --
// [lpReserved] --
//
// Returns:
//
// History: 10-10-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
DWORD CALLBACK CINet::InternetAuthNotifyCallback(DWORD_PTR dwContext, DWORD dwAction, LPVOID lpReserved) { DEBUG_ENTER((DBG_APP, Dword, "CINet::InternetAuthNotifyCallback", "%#x, %#x, %#x", dwContext, dwAction, lpReserved )); // If this is a request, then we know the cookie type
CINet *pCINet = (CINet *) dwContext; PerfDbgLog2(tagCINet, pCINet, "+CINet::InternetAuthNotifyCallback Action:%ld, State:%ld", dwAction, pCINet->_INState);
PProtAssert((lpReserved == NULL));
DWORD dwRes = ERROR_SUCCESS;
switch (dwAction) { case ERROR_SUCCESS : // should never be returned here
PProtAssert((FALSE));
case ERROR_CANCELLED : // NOTE: succes and cancel means display the content according to ArthurBi
// continue reading data and show the 401 contained
pCINet->_hrINet = NOERROR; // Why do we inc the count here??
pCINet->_fProxyAuth ? pCINet->_cbProxyAuthenticate++ : pCINet->_cbAuthenticate++; break;
case ERROR_INTERNET_RETRY_DIALOG: pCINet->_hrINet = INET_E_AUTHENTICATION_REQUIRED; break;
case ERROR_INTERNET_FORCE_RETRY : pCINet->_hrINet = RPC_E_RETRY; pCINet->_fProxyAuth ? pCINet->_cbProxyAuthenticate++ : pCINet->_cbAuthenticate++; break;
default: pCINet->_hrINet = E_ACCESSDENIED; break; }
pCINet->OnINetAuthenticate(dwAction);
PerfDbgLog2(tagCINet, pCINet, "-CINet::InternetAuthNotifyCallback (pCINet->_hrINet:%lx, dwResult:%lx)", pCINet->_hrINet,dwRes);
DEBUG_LEAVE(dwRes); return dwRes; }
//+---------------------------------------------------------------------------
//
// Method: CINet::OnINetAuthenticate
//
// Synopsis:
//
// Arguments: [dwResult] --
//
// Returns:
//
// History: 10-10-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::OnINetAuthenticate(DWORD dwResult) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::OnINetAuthenticate", "this=%#x, %#x", this, dwResult )); PerfDbgLog(tagCINet, this, "+CINet::OnINetAuthenticate"); HRESULT hr = NOERROR;
PProtAssert((GetStatePending() == E_PENDING)); // set state to normal - no pending transaction
SetStatePending(NOERROR); PProtAssert((_INState == INetState_AUTHENTICATE));
if (dwResult) { TransitState(INetState_AUTHENTICATE, TRUE); }
PerfDbgLog1(tagCINet, this, "-CINet::OnINetAuthenticate (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::INetAuthenticate
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 10-10-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::INetAuthenticate() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::INetAuthenticate", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::INetAuthenticate"); PProtAssert((GetStatePending() == NOERROR));
HRESULT hr = NOERROR; DWORD dwOperation;
PProtAssert((GetStatePending() == NOERROR));
if (_hrINet == INET_E_AUTHENTICATION_REQUIRED) { // bring up the internet errro dialog
hr = AuthenticationRequest();
if ((hr != NOERROR) && (hr != E_PENDING)) { _hrError = INET_E_AUTHENTICATION_REQUIRED; } else { _hrError = INET_E_OK; }
}
if (hr == NOERROR) { if (_hrINet == RPC_E_RETRY) { // retry the send/request
_hrINet = NOERROR; _fCompleted = FALSE; _fSendAgain = TRUE; hr = INetAsyncSendRequest(); } else if (_hrINet == NOERROR) { hr = QueryStatusOnResponseDefault(0); if( hr == NOERROR ) { hr = QueryHeaderOnResponse(); if (hr == NOERROR) { // read more data from wininet
hr = INetRead(); } } } else { // this will report the hresult return from the dialog
hr = _hrINet; } }
PerfDbgLog1(tagCINet, this, "-CINet::INetAuthenticate (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::INetResumeAsyncRequest
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 1-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::INetResumeAsyncRequest(DWORD dwResultCode) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::INetResumeAsyncRequest", "this=%#x, %#x", this, dwResultCode )); PerfDbgLog(tagCINet, this, "+CINet::INetResumeAsyncRequest");
HRESULT hr = NOERROR; BOOL fRestarted; BOOL fRet; PProtAssert((GetStatePending() == NOERROR));
SetINetState(INetState_SEND_REQUEST); { SetStatePending(E_PENDING);
fRet = ResumeSuspendedDownload(_hRequest, dwResultCode );
if (fRet == FALSE) { 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(tagCINet, this, "CINet::INetResumeAsyncRequest (fRet:%d, _hrError:%lx, LstError:%ld)", fRet, _hrError, dwLstError); } } else { SetStatePending(NOERROR); } }
if (_hrError != INET_E_OK) { // we need to terminate here
ReportResultAndStop(hr); }
PerfDbgLog1(tagCINet, this, "-CINet::INetResumeAsyncRequest (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::INetDisplayUI
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 10-10-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::INetDisplayUI() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::INetDisplayUI", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::INetDisplayUI"); PProtAssert((GetStatePending() == NOERROR));
HRESULT hr = NOERROR; DWORD dwOperation; DWORD dwResultCode = ERROR_SUCCESS;
PProtAssert((GetStatePending() == NOERROR)); DWORD dwBindF = GetBindFlags();
if (_hrINet == INET_E_AUTHENTICATION_REQUIRED) { HWND hwnd = 0; hr = NOERROR; // Get a window handle. QueryService on IWindowForBindingUI
// to get a window object first if necessary.
if (_pWindow == NULL) { hr = QueryService(IID_IWindowForBindingUI, (void **) &_pWindow); } // If we don't already have a window handle, get one from the interface.
if (!hwnd && _pWindow) { hr = _pWindow->GetWindow(IID_IHttpSecurity, &hwnd); PProtAssert(( (hr == S_FALSE) && (hwnd == NULL) || (hr == S_OK) && (hwnd != NULL))); }
if (hwnd && (hr == S_OK)) { DWORD dwFlags = FLAGS_ERROR_UI_SERIALIZE_DIALOGS; if ((dwBindF & BINDF_NO_UI) || (dwBindF & BINDF_SILENTOPERATION)) { dwFlags |= FLAGS_ERROR_UI_FLAGS_NO_UI; }
dwResultCode = InternetErrorDlg( hwnd, _hRequest, _dwSendRequestResult, dwFlags, &_lpvExtraSendRequestResult);
if ( dwResultCode == ERROR_CANCELLED || dwResultCode == ERROR_SUCCESS ) { // hack-hack alert, if _lpvExtraSendRequestResult non-null we change behavior
if ( !(dwResultCode == ERROR_SUCCESS && _lpvExtraSendRequestResult != NULL) ) { dwResultCode = ERROR_INTERNET_OPERATION_CANCELLED; } }
_hrINet = RPC_E_RETRY; hr = NOERROR; } else if (_dwSendRequestResult == ERROR_HTTP_COOKIE_NEEDS_CONFIRMATION || _dwSendRequestResult == ERROR_HTTP_COOKIE_NEEDS_CONFIRMATION_EX) { //fix to prevent heap trashing in wininet.b#86959
dwResultCode = ERROR_HTTP_COOKIE_DECLINED; _hrINet = RPC_E_RETRY; hr = NOERROR; }
if ((hr != NOERROR) && (hr != E_PENDING)) { _hrError = INET_E_AUTHENTICATION_REQUIRED; } else { _hrError = INET_E_OK; } }
if (hr == NOERROR) { if (_hrINet == RPC_E_RETRY) { // retry the send/request
_hrINet = NOERROR;
// hack-arama around to allow CD-ROM dialog to still work
if ( _dwSendRequestResult == ERROR_INTERNET_INSERT_CDROM ) { hr = INetAsyncSendRequest(); } else { hr = INetResumeAsyncRequest(dwResultCode); } } else { // this will report the hresult return from the dialog
hr = _hrINet; } }
PerfDbgLog1(tagCINet, this, "-CINet::INetDisplayUI (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::INetSeek
//
// Synopsis:
//
// Arguments: [DWORD] --
// [ULARGE_INTEGER] --
// [plibNewPosition] --
//
// Returns:
//
// History: 10-29-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::INetSeek(LARGE_INTEGER dlibMove,DWORD dwOrigin,ULARGE_INTEGER *plibNewPosition) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::INetSeek", "this=%#x, %#x, %#x, %#x", this, dlibMove, dwOrigin, plibNewPosition )); PerfDbgLog(tagCINet, this, "+CINet::INetSeek"); HRESULT hr = E_FAIL;
// each protocol has to overwrite this method if
// seek is supported
DWORD dwResult = InternetSetFilePointer( _hRequest ,dlibMove.LowPart ,0 ,dwOrigin ,0 );
PerfDbgLog1(tagCINet, this, "-CINet::INetSeek (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::IsUpLoad
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 4-28-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL CINet::IsUpLoad() { DEBUG_ENTER((DBG_APP, Bool, "CINet::IsUpLoad", "this=%#x", this )); BINDINFO *pBndInfo = GetBindInfo(); BOOL fRet = ( (pBndInfo->dwBindVerb != BINDVERB_GET) && (pBndInfo->stgmedData.tymed == TYMED_ISTREAM) && !_fCompleted && !_fRedirected);
DEBUG_LEAVE(fRet); return fRet; }
//+---------------------------------------------------------------------------
//
// Method: CINet::CPrivUnknown::QueryInterface
//
// Synopsis:
//
// Arguments: [riid] --
// [ppvObj] --
//
// Returns:
//
// History: 10-29-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP CINet::CPrivUnknown::QueryInterface(REFIID riid, void **ppvObj) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::CPrivUnknown::IUnknown::QueryInterface", "this=%#x, %#x, %#x", this, &riid, ppvObj )); VDATEPTROUT(ppvObj, void *); VDATETHIS(this); HRESULT hr = NOERROR;
PerfDbgLog(tagCINet, this, "+CINet::CPrivUnknown::QueryInterface"); CINet *pCINet = GETPPARENT(this, CINet, _Unknown);
*ppvObj = NULL;
if ((riid == IID_IUnknown) || (riid == IID_IOInetProtocol) || (riid == IID_IOInetProtocolRoot) ) { *ppvObj = (IOInetProtocol *) pCINet; pCINet->AddRef(); } else if ( ( IsEqualIID(riid, IID_IWinInetInfo)|| IsEqualIID(riid, IID_IWinInetHttpInfo) ) && ( !IsEqualIID(CLSID_FileProtocol, pCINet->_pclsidProtocol) ) )
{ *ppvObj = (void FAR *) (IWinInetHttpInfo *)pCINet; pCINet->AddRef(); } else if (riid == IID_IOInetThreadSwitch) { *ppvObj = (IOInetThreadSwitch *)pCINet; pCINet->AddRef(); } else { hr = E_NOINTERFACE; }
PerfDbgLog1(tagCINet, this, "-CINet::CPrivUnknown::QueryInterface (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Function: CINet::CPrivUnknown::AddRef
//
// Synopsis:
//
// Arguments: [ULONG] --
//
// Returns:
//
// History: 10-29-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CINet::CPrivUnknown::AddRef(void) { DEBUG_ENTER((DBG_APP, Dword, "CINet::CPrivUnknown::IUnknown::AddRef", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::CPrivUnknown::AddRef");
LONG lRet = ++_CRefs;
PerfDbgLog1(tagCINet, this, "-CINet::CPrivUnknown::AddRef (cRefs:%ld)", lRet);
DEBUG_LEAVE(lRet); return lRet; } //+---------------------------------------------------------------------------
//
// Function: CINet::Release
//
// Synopsis:
//
// Arguments: [ULONG] --
//
// Returns:
//
// History: 10-29-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CINet::CPrivUnknown::Release(void) { DEBUG_ENTER((DBG_APP, Dword, "CINet::CPrivUnknown::IUnknown::Release", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::CPrivUnknown::Release");
CINet *pCINet = GETPPARENT(this, CINet, _Unknown);
LONG lRet = --_CRefs;
if (lRet == 0) { delete pCINet; }
PerfDbgLog1(tagCINet, this, "-CINet::CPrivUnknown::Release (cRefs:%ld)", lRet);
DEBUG_LEAVE(lRet); return lRet; }
//+---------------------------------------------------------------------------
//
// Method: CINet::OnINetReadDirect
//
// Synopsis:
//
// Arguments: [dwResult] --
//
// Returns:
//
// History: 4-28-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::OnINetReadDirect(DWORD dwResult) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::OnINetReadDirect", "this=%#x, %#x", this, dwResult )); PerfDbgLog(tagCINet, this, "+CINet::OnINetReadDirect"); HRESULT hr = NOERROR;
PProtAssert((GetStatePending() == E_PENDING)); // set state to normal - no pending transaction
SetStatePending(NOERROR);
if (OperationOnAparmentThread(INetState_SEND_REQUEST)) { TransitState(INetState_READ_DIRECT); } else { hr = INetReadDirect(); }
PerfDbgLog1(tagCINet, this, "-CINet::OnINetReadDirect (hr:%lx)", hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::INetReadDirect
//
// Synopsis:
//
// Arguments: (none)
//
// Returns:
//
// History: 4-28-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::INetReadDirect() { DEBUG_ENTER((DBG_APP, Hresult, "CINet::INetReadDirect", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::INetReadDirect"); HRESULT hr = NOERROR; DWORD dwError; ULONG cbBytesAvailable = 1; ULONG cbBytesReport = 0; SetINetState(INetState_READ_DIRECT);
//BUGBUG: we hit this assertion sometimes.
//PProtAssert((GetStatePending() == NOERROR));
_hrError = INET_E_OK;
if (!_fFilenameReported) { char szFilename[MAX_PATH];
HRESULT hr1 = GetUrlCacheFilename(szFilename, MAX_PATH);
if (hr1 == NOERROR && szFilename[0] != '\0') { ReportNotification(BINDSTATUS_CACHEFILENAMEAVAILABLE, (LPSTR) szFilename); _fFilenameReported = TRUE; } }
if ((GetStatePending() == E_PENDING)) { // nothing to do - data for this notfication
// already received
DbgLog(tagCINetErr, this, "CINet::INetReadDirect E_PENIDNG");
} else { if ( _fDone || ( _cbTotalBytesRead && _cbDataSize && (_cbTotalBytesRead == _cbDataSize))) {
_hrError = INET_E_DONE; _pEmbdFilter->ReportData(_bscf, cbBytesAvailable, _cbDataSize); ReportResultAndStop(NOERROR, _cbTotalBytesRead, _cbDataSize); hr = NOERROR; } else {
if (_bscf & BSCF_DATAFULLYAVAILABLE) { _bscf |= BSCF_LASTDATANOTIFICATION; _bscf &= ~BSCF_FIRSTDATANOTIFICATION; cbBytesReport = cbBytesAvailable + _cbTotalBytesRead; if (IsEmbdFilterOk() ) { _pEmbdFilter->ReportData(_bscf, cbBytesReport, _cbDataSize); } ReportResultAndStop(NOERROR, cbBytesReport, _cbDataSize); } else { _bscf |= BSCF_AVAILABLEDATASIZEUNKNOWN; cbBytesReport = cbBytesAvailable + _cbTotalBytesRead; if (_pCTrans && IsEmbdFilterOk() ) { _cbSizeLastReportData = cbBytesReport; hr = _pEmbdFilter->ReportData(_bscf, cbBytesReport, _cbDataSize); } }
if (_bscf & BSCF_FIRSTDATANOTIFICATION) { _bscf &= ~BSCF_FIRSTDATANOTIFICATION; _bscf |= BSCF_INTERMEDIATEDATANOTIFICATION; } } }
PerfDbgLog2(tagCINet, this, "-CINet::INetReadDirect (_hrError:%lx, hr:%lx)", _hrError, hr);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::ReadDirect
//
// Synopsis:
//
// Arguments: [pBuffer] --
// [cbBytes] --
// [pcbBytes] --
//
// Returns:
//
// History: 4-28-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CINet::ReadDirect(BYTE *pBuffer, DWORD cbBytes, DWORD *pcbBytes) { DEBUG_ENTER((DBG_APP, Hresult, "CINet::ReadDirect", "this=%#x, %#x, %#x, %#x", this, pBuffer, cbBytes, pcbBytes )); PerfDbgLog(tagCINet, this, "+CINet::ReadDirect"); HRESULT hr = NOERROR; DWORD dwError;
*pcbBytes = 0; ULONG dwReturned = 0;
//BUGBUG: turn this assertion on again
//PProtAssert((GetStatePending() == NOERROR));
if (_hrError == INET_E_DONE) { // means end of file
hr = S_FALSE; } else if (GetStatePending() != NOERROR) { hr = E_PENDING; } else { _hrError = INET_E_OK; PProtAssert(((pBuffer != NULL) && (cbBytes > 0))); //PerfDbgLog1(tagCINet, this, "CINet::ReadDirect -> InternetReadFile (dwBytesLeft:%ld)", dwBytesLeft);
LPINTERNET_BUFFERSA pIB = &_inetBufferSend; pIB->dwStructSize = sizeof (INTERNET_BUFFERSA); pIB->Next = 0; pIB->lpcszHeader = 0; pIB->dwHeadersLength = 0; pIB->dwHeadersTotal = 0; pIB->lpvBuffer = pBuffer; pIB->dwBufferLength = cbBytes; pIB->dwBufferTotal = 0; pIB->dwOffsetLow = 0; pIB->dwOffsetHigh = 0;
dwReturned = 0; PProtAssert((GetStatePending() == NOERROR)); SetStatePending(E_PENDING);
if (!InternetReadFileExA( _hRequest //IN HINTERNET hFile,
,pIB // OUT LPINTERNET_BUFFERSA lpBuffersOut,
,IRF_NO_WAIT // IN DWORD dwFlags,
,0 // IN DWORD dwContext
)) { //
// async completion
//
dwError = GetLastError(); if (dwError != ERROR_IO_PENDING) { hr = _hrError = INET_E_DOWNLOAD_FAILURE; DbgLog3(tagCINetErr, this, "CINet::ReadDirect failed: (dwError:%lx, hr:%lx, hrError:%lx)", dwError, hr, _hrError); } else { hr = E_PENDING; } } else { //
// sync completion
//
SetStatePending(NOERROR); //
dwReturned = pIB->dwBufferLength; _cbTotalBytesRead += dwReturned; *pcbBytes = dwReturned;
PerfDbgLog3(tagCINet, this, "CINet::ReadDirect == InternetReadFileEx ==> (cbBytes:%ld, dwReturned:%ld,_cbTotalBytesRead:%ld)", cbBytes, dwReturned,_cbTotalBytesRead);
if (dwReturned == 0) { // eof
hr = _hrError = INET_E_DONE; //TransDebugOut((DEB_TRACE, "%p _IN CINetStream::INetSeek\n", this));
PProtAssert(( ( (_cbDataSize && (_cbDataSize == _cbTotalBytesRead)) || (!_cbDataSize)) && "WinInet returned incorrent amount of data!!" )); } else { hr = NOERROR; }
} // read case - bits available
*pcbBytes = dwReturned;
if (hr == INET_E_DONE) { hr = (dwReturned) ? S_OK : S_FALSE; } }
// Note: stop the download in case of DONE or ERROR!
if (_hrError != INET_E_OK) { ReportResultAndStop((hr == S_FALSE) ? NOERROR : hr); }
PerfDbgLog4(tagCINet, this, "-CINet::ReadDirect (_hrError:%lx, [hr:%lx,cbBytesAsked:%ld,cbBytesReturned:%ld])", _hrError, hr, cbBytes, *pcbBytes);
DEBUG_LEAVE(hr); return hr; }
//+---------------------------------------------------------------------------
//
// Method: CINet::GetUserAgentString
//
// Synopsis:
//
// Arguments: [pBuffer] --
// [cbBytes] --
// [pcbBytes] --
//
// Returns:
//
// History: 4-28-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
LPSTR CINet::GetUserAgentString() { DEBUG_ENTER((DBG_APP, String, "CINet::GetUserAgentString", "this=%#x", this )); PerfDbgLog(tagCINet, this, "+CINet::GetUserAgentString"); HRESULT hr = NOERROR; ULONG ulCount = 0; LPWSTR pwzStr = 0; LPSTR pszStr = 0;
hr = _pOIBindInfo->GetBindString(BINDSTRING_USER_AGENT, (LPWSTR *)&pwzStr, 1, &ulCount);
if ((hr == NOERROR) && ulCount) { PProtAssert((pwzStr)); delete _pszUserAgentStr; pszStr = _pszUserAgentStr = DupW2A(pwzStr); } else { pszStr = (LPSTR)::GetUserAgentString(); }
PerfDbgLog1(tagCINet, this, "-CINet::GetUserAgentString (pszStr:%s)", pszStr);
DEBUG_LEAVE(pszStr); return pszStr; }
BOOL GlobalUTF8Enabled() { DEBUG_ENTER((DBG_APP, Bool, "GlobalUTF8Enabled", NULL )); // read the IE5 B2 global reg key
DWORD dwErr = ERROR_SUCCESS; BOOL fRet = FALSE; HKEY hKeyClient; DWORD dwUTF8 = 0; DWORD dwSize = sizeof(DWORD); DWORD dwType;
dwErr = RegOpenKeyEx( HKEY_CURRENT_USER, INTERNET_POLICIES_KEY, 0, KEY_QUERY_VALUE, &hKeyClient ); if( dwErr == ERROR_SUCCESS ) { dwErr = RegQueryValueEx( hKeyClient, "EnableUTF8", 0, &dwType, (LPBYTE)&dwUTF8, &dwSize );
if( dwErr == ERROR_SUCCESS && dwUTF8 ) { fRet = TRUE; } RegCloseKey(hKeyClient); }
DEBUG_LEAVE(fRet); return fRet; }
// Enabled by adding a DWORD value "MBCSServername" with non=zero value under POLICY key
BOOL GlobalUTF8hackEnabled() { DEBUG_ENTER((DBG_APP, Bool, "GlobalUTF8hackEnabled", NULL )); DWORD dwErr = ERROR_SUCCESS; BOOL fRet = TRUE; HKEY hKeyClient; DWORD dwUTF8 = 0; DWORD dwSize = sizeof(DWORD); DWORD dwType;
dwErr = RegOpenKeyEx( HKEY_CURRENT_USER, INTERNET_POLICIES_KEY, 0, KEY_QUERY_VALUE, &hKeyClient ); if( dwErr == ERROR_SUCCESS ) { dwErr = RegQueryValueEx( hKeyClient, "MBCSServername", 0, &dwType, (LPBYTE)&dwUTF8, &dwSize );
if( dwErr == ERROR_SUCCESS && !dwUTF8 ) { fRet = FALSE; } RegCloseKey(hKeyClient); }
DEBUG_LEAVE(fRet); return fRet; }
|