void vmsBrowserSpecialInfo::RemoveUrlInfo(int nIndex)
{
	vmsCriticalSectionAutoLock csal (&m_csUrls);
	assert (nIndex >= 0 && nIndex < m_vUrls.size ());
	if (nIndex < 0 || nIndex >= m_vUrls.size ())
		return;
	m_vUrls.erase (m_vUrls.begin () + nIndex);
}
void vmsUrlMonRequestCollector::onInternetProtocolRoot_Abort(IInternetProtocolRoot *pProt, HRESULT hrReason, DWORD dwOptions)
{
	vmsCriticalSectionAutoLock csal (&m_csReq);
	int nIndex = findRequestIndexByProtocol (pProt);
	ATLASSERT (nIndex != -1);
	if (nIndex == -1)
		return;
	Request *req = getRequest (nIndex);
}
void vmsUrlMonRequestCollector::onInternetProtocolSink_ReportResult(IInternetProtocolSink *pSink, HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
{
	vmsCriticalSectionAutoLock csal (&m_csReq);
	int nIndex = findRequestIndexBySink (pSink);
	ATLASSERT (nIndex != -1);
	if (nIndex == -1)
		return;
	Request *req = getRequest (nIndex);
	CloseRequest (req);
}
bool vmsUrlMonRequestCollector::onInternetProtocolRoot_Continue(IInternetProtocolRoot* pProt, PROTOCOLDATA* pProtocolData)
{
	if (pProtocolData == &_protocolData || 
			(pProtocolData->dwState == 0 && pProtocolData->pData == _protocolData_pData && pProtocolData->cbData == 13))
	{
		vmsCriticalSectionAutoLock csal (&m_csReq);
		int nIndex = findRequestIndexByProtocol (pProt);
		assert (nIndex != -1);
		if (nIndex == -1)
		{
			LOGsnl ("WARNING: no request found for pProt in onInternetProtocolRoot_Continue");
			return true;
		}
		Request *req = getRequest (nIndex);

		if (!req->dwthridContinue)
		{
			if (req->dwTicksCompleted)
				req->spProt = NULL;

			req->dwthridContinue = GetCurrentThreadId ();

#ifdef SCL_ENABLE
			LOGsnl ("Update for request:");
			USES_CONVERSION;
			LOG (" URL: %s", W2CA (req->wstrUrl.c_str ()));
			LOG (" thridContinue: %d", req->dwthridContinue);
#endif

			HMODULE hBhoDll = GetModuleHandle (_T ("iefdm2.dll"));
			if (hBhoDll)
			{
				typedef BSTR (WINAPI *FNfdmbho_getTabUrl) (DWORD dwThreadId);
				FNfdmbho_getTabUrl pfn = (FNfdmbho_getTabUrl)GetProcAddress (hBhoDll, "fdmbho_getTabUrl");
				if (pfn)
				{
					BSTR bstrTabUrl = pfn (req->dwthridContinue);
					if (!bstrTabUrl)
						bstrTabUrl = pfn (req->dwthridStart);
					if (bstrTabUrl)
					{
						req->wstrSrcTabUrl = bstrTabUrl;
						SysFreeString (bstrTabUrl);
					}
#ifdef SCL_ENABLE
					LOG (" SRC TAB URL: %s", req->wstrSrcTabUrl.empty () ? "<NOT_FOUND>" : W2CA (req->wstrSrcTabUrl.c_str ()));
#endif
				}
			}
		}
		return true;
	}

	return false;
}
DWORD WINAPI vmsTrafficUsageModeMgr::_threadManage(LPVOID lp)
{
	LOGFN ("vmsTrafficUsageModeMgr::_threadManage");

	vmsTrafficUsageModeMgr *pthis = (vmsTrafficUsageModeMgr*)lp;

	while (WaitForSingleObject (pthis->m_hevShuttingDown, 1000) == WAIT_TIMEOUT)
	{
		pthis->CheckIfBestInterfaceChanged ();
		pthis->CheckNeedResetAllSpeedsInfo ();

		bool bDontUpdateSpeeds = pthis->m_cSecondsNoSpeedMeasure != 0;
		if (bDontUpdateSpeeds)
		{
			vmsCriticalSectionAutoLock csal (&pthis->m_csMisc);
			pthis->m_cSecondsNoSpeedMeasure--;			
		}
		if (pthis->m_bRestrainAll)
			bDontUpdateSpeeds = true;
		vmsCriticalSectionAutoLock csal (&pthis->m_csManageForSpeed);
		pthis->CheckItemsPriorityChanges ();
		UINT64 uConnectionDownloadBandwidth = pthis->refgetNetworkStat (true).uConnectionBandwidth;
		UINT64 uConnectionUploadBandwidth = pthis->refgetNetworkStat (false).uConnectionBandwidth;
		pthis->ProcessManageForSpeedItems (true, bDontUpdateSpeeds);
		

		
		for (size_t i = 0; i < pthis->m_vpManageForSpeed.size (); i++)
		{
			for (size_t j = 0; j < pthis->m_vpManageForSpeed [i]->vItems.size (); j++)
				pthis->m_vpManageForSpeed [i]->vItems [j].state &= ~ManageForSpeedItem::MSIS_PRIORITY_CHANGED;
		}

		if (uConnectionDownloadBandwidth != pthis->refgetNetworkStat (true).uConnectionBandwidth ||
				uConnectionUploadBandwidth != pthis->refgetNetworkStat (false).uConnectionBandwidth)
			pthis->BuildCurrentSettings ();
		else if (uConnectionDownloadBandwidth == UINT64_MAX )
			pthis->BuildCurrentSettings ();
	}

	return 0;
}
void vmsUrlMonRequestCollector::CloseTimedoutRequests(void)
{
	vmsCriticalSectionAutoLock csal (&m_csReq);
	DWORD dwTicks = GetTickCount ();
	for (size_t i = 0; i < m_vReq.size (); i++)
	{
		if ((m_vReq [i]->dwState & Request::GotResponse) || m_vReq [i]->dwTicksCompleted)
			continue;
		if (dwTicks - m_vReq [i]->dwTicksStarted >= 2*60*1000)
			CloseRequest (m_vReq [i]);
	}
}
void vmsUrlMonRequestCollector::onHttpNegotiate_OnResponse(IHttpNegotiate* pHN, DWORD dwResponseCode, LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR* pszAdditionalRequestHeaders)
{
	vmsCriticalSectionAutoLock csal (&m_csReq);
	int nIndex = findRequestIndexByHttpNegotiate (pHN);
	if (nIndex == -1)
		return;
	Request *req = getRequest (nIndex);
	req->dwState |= Request::GotResponse;

	IWinInetHttpInfoPtr spWinInetHttpInfo (req->spProt);
	if (spWinInetHttpInfo != NULL)
	{
		DWORD dwSize = 0, dwFlags = 0;
		spWinInetHttpInfo->QueryInfo (HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HEADERS, 0, &dwSize, &dwFlags, 0);
		if (dwSize)
		{
			std::vector <char> vBuf (dwSize);
			LPSTR psz = &vBuf.front (); *psz = 0;
			spWinInetHttpInfo->QueryInfo (HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HEADERS, psz, &dwSize, &dwFlags, 0);
			req->strRequestHeaders = psz;
		}
		dwSize = 0; dwFlags = 0;
		spWinInetHttpInfo->QueryInfo (HTTP_QUERY_RAW_HEADERS_CRLF, 0, &dwSize, &dwFlags, 0);
		if (dwSize)
		{
			std::vector <char> vBuf (dwSize);
			LPSTR psz = &vBuf.front (); *psz = 0;
			spWinInetHttpInfo->QueryInfo (HTTP_QUERY_RAW_HEADERS_CRLF, psz, &dwSize, &dwFlags, 0);
			req->strResponseHeaders = psz;
		}
	}

	IWinInetInfoPtr spWinInetInfo (req->spProt);
	if (spWinInetInfo != NULL)
	{
		vector <char> vch; vch.resize (1000); vch [0] = 0;
		DWORD dwSize = vch.size ();
		HRESULT hr = spWinInetInfo->QueryOption (INTERNET_OPTION_URL, &vch[0], &dwSize);
		if (dwSize > vch.size ())
		{
			vch.resize (dwSize); vch [0] = 0;
			hr = spWinInetInfo->QueryOption (INTERNET_OPTION_URL, &vch[0], &dwSize);
		}
		if (SUCCEEDED (hr))
		{
			USES_CONVERSION;
			wstring wstr = A2CW (&vch[0]);
			if (wcscmp (wstr.c_str (), req->wstrUrl.c_str ()))
				req->wstrRedirectedUrl = wstr;
		}
	}
}
void vmsUrlMonRequestCollector::onNewRequest(Request *request)
{
	_BrowsersSharedData.ModifyActiveDownloadsCount (1);

	RemoveTooOldRequests ();

	request->dwTicksStarted = GetTickCount ();

	IServiceProviderPtr spSP (request->spSink);
	assert (spSP != NULL);
	if (spSP != NULL)
		spSP->QueryService (IID_IHttpNegotiate, IID_IHttpNegotiate, (void**)&request->spHttpNegotiate);

	request->dwthridStart = GetCurrentThreadId ();

	if (_IEVersion.m_appVersion.empty () || _IEVersion.m_appVersion [0] < 10)
	{
		BINDINFO bi; DWORD dwBindF;
		ZeroMemory (&bi, sizeof (bi));
		bi.cbSize = sizeof (bi);
		request->spBindInfo->GetBindInfo (&dwBindF, &bi);

		if (bi.dwBindVerb == BINDVERB_POST && bi.cbstgmedData)
		{
			
			if (bi.stgmedData.tymed == TYMED_HGLOBAL)
			{
				LPVOID pData = GlobalLock (bi.stgmedData.hGlobal);
				if (pData)
				{
					request->vbPostData.resize (bi.cbstgmedData);
					CopyMemory (&request->vbPostData [0], pData, bi.cbstgmedData);
					GlobalUnlock (bi.stgmedData.hGlobal);
				}
			}
		}
	}

	vmsCriticalSectionAutoLock csal (&m_csReq);
	m_vReq.push_back (request);

#ifdef SCL_ENABLE
	LOGsnl ("New request:");
	USES_CONVERSION;
	LOG (" URL: %s", W2CA (request->wstrUrl.c_str ()));
	LOG (" thridStart: %d", request->dwthridStart);
	LOG (" post data size: %d", request->vbPostData.size ());
#endif

	request->spSink->Switch (&_protocolData);
}
void vmsUrlMonRequestCollector::onInternetProtocolSink_ReportProgress(IInternetProtocolSink* pSink, ULONG ulStatusCode, LPCWSTR szStatusText)
{
#ifdef SCL_ENABLE
	{USES_CONVERSION;
	vmsCriticalSectionAutoLock csal (&m_csReq);
	int nIndex = findRequestIndexBySink (pSink);
	if (nIndex == -1)
		return;
	Request *req = getRequest (nIndex);
	LOGsnl ("Progress for request:");
	LOG (" URL: %s", W2CA (req->wstrUrl.c_str ()));
	LOG (" ulStatusCode: %d", ulStatusCode);
	LOG (" szStatusText: %s", W2CA (szStatusText));}
#endif

	if (ulStatusCode != BINDSTATUS_REDIRECTING)
		return;

	assert (szStatusText != NULL);
	if (!szStatusText)
		return;

	vmsCriticalSectionAutoLock csal (&m_csReq);
	int nIndex = findRequestIndexBySink (pSink);
	if (nIndex == -1)
		return;
	Request *req = getRequest (nIndex);

	req->wstrRedirectedUrl = szStatusText;

#ifdef SCL_ENABLE
	LOGsnl ("Update for request:");
	USES_CONVERSION;
	LOG (" URL: %s", W2CA (req->wstrUrl.c_str ()));
	LOG (" Redirecting to URL: %s", W2CA (szStatusText));
	LOG (" TICKCOUNT: %d", GetTickCount ());
#endif
}
void vmsUrlMonRequestCollector::onInternetProtocolSink_ReportData(IInternetProtocolSink* pSink, DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
{
	vmsCriticalSectionAutoLock csal (&m_csReq);
	int nIndex = findRequestIndexBySink (pSink);
	if (nIndex == -1)
		return;
	Request *req = getRequest (nIndex);
	req->dwState |= Request::GotResponse;

#ifdef SCL_ENABLE
	USES_CONVERSION;
	LOGsnl ("Report data for request:");
	LOG (" URL: %s", W2CA (req->wstrUrl.c_str ()));
	LOG (" grfBSCF: %d", grfBSCF);
	LOG (" progress: %d", ulProgress);
	LOG (" progress max: %d", ulProgressMax);
#endif
}
void vmsUrlMonRequestCollector::RemoveTooOldRequests(void)
{
	vmsCriticalSectionAutoLock csal (&m_csReq);
	size_t cOld = 0;

	DWORD dwTicks = GetTickCount ();

	for (size_t i = 0; i < m_vReq.size (); i++, cOld++)
	{
		if (m_vReq [i]->dwTicksCompleted && 
				dwTicks - m_vReq [i]->dwTicksCompleted < 5*60*1000)
			break;
		if (dwTicks - m_vReq [i]->dwTicksStarted < 15*60*1000)
			break;
		if (!m_vReq [i]->dwTicksCompleted) 
			CloseRequest (m_vReq [i]);
	}

	if (cOld)
		m_vReq.erase (m_vReq.begin (), m_vReq.begin () + cOld);
}
void vmsTrafficUsageModeMgr::_IECatchMgrEvents(fsIECatchMgrEvent ev, LPVOID lp)
{
	vmsTrafficUsageModeMgr *pThis = (vmsTrafficUsageModeMgr*) lp;

	vmsCriticalSectionAutoLock csal (&pThis->m_csTUMManage);

	switch (ev)
	{
	case ICME_DLSTARTED:
		switch (pThis->m_enTUMManage)
		{
		case TM_OFF:
			return;

		case TM_DECREASEBYONELEVEL:
			switch (pThis->GetTUM ())
			{
			case TUM_HEAVY:
				pThis->setTUM (TUM_MEDIUM, false);
				break;

			case TUM_MEDIUM:
				pThis->setTUM (TUM_LIGHT, false);
				break;
			}
			break;

		case TM_SETTOLIGHT:
			pThis->setTUM (TUM_LIGHT, false);
			break;
		}
		break;

	case ICME_DLCOMPLETED:
		if (pThis->GetTUM () != pThis->m_enUserTUM)
			pThis->setTUM (pThis->m_enUserTUM, false);
		break;
	}
}
bool vmsInterfaceHook::HookMethod (LPVOID pvObject, LPVOID pfnHook, int nMethod)
{
	vmsCriticalSectionAutoLock csal (&m_csHooks);

	int nIndex = findHookIndex (pvObject, nMethod);
	if (nIndex != -1)
		return true;

	Entry hook;
	hook.ppvVat = *(LPVOID**)pvObject;
	hook.nMethod = nMethod;
	hook.pvOriginalFn = hook.ppvVat [nMethod];

	DWORD dw = 0;
	if (FALSE == VirtualProtect (hook.ppvVat, sizeof (LONG_PTR) * (hook.nMethod+1), PAGE_EXECUTE_READWRITE, &dw))
		return false;

	m_vHooks.push_back (hook);

	assert (hook.ppvVat [hook.nMethod] != pfnHook);
	hook.ppvVat [hook.nMethod] = pfnHook;

	return true;
}
void vmsBrowserSpecialInfo::AddUrl(const UrlInfo &url)
{
	vmsCriticalSectionAutoLock csal (&m_csUrls);
	m_vUrls.push_back (url);
}