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;
		}
	}
}
STDMETHODIMP vmsBindStatusCallback::OnStartBinding (DWORD dwReserved, IBinding *pib)
{
	if (!pib)
		return E_INVALIDARG;
	
	m_spBinding = pib;

	char sz [10000] = "";
	DWORD dw = sizeof (sz);
	
	IWinInetHttpInfoPtr spHttpInfo (pib);

	if (spHttpInfo != NULL)
	{
		DWORD dwFlags = 0;
	
		HRESULT hr = spHttpInfo->QueryInfo (
			HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HEADERS, sz, &dw, &dwFlags, NULL);
	
		LPDWORD pdw = (LPDWORD)sz;
		dw = *pdw;
	
		if (S_OK == hr)
		{
			m_strCookies = "";
			m_strReferer = "";
		
			LPCSTR pszReferer = strstr (sz, "Referer: ");		
			if (pszReferer)
			{
				pszReferer += strlen ("Referer: ");
				while (*pszReferer != 0 && *pszReferer != '\r' && *pszReferer != '\n')
					m_strReferer += *pszReferer++;
			}
		
			LPCSTR pszCookie = strstr (sz, "Cookie: ");		
			if (pszCookie)
			{
				pszCookie += strlen ("Cookie: ");
				while (*pszCookie != 0 && *pszCookie != '\r' && *pszCookie != '\n')
					m_strCookies += *pszCookie++;
			}
		}

		*sz = 0; dw = sizeof (sz); dwFlags = 0;
		spHttpInfo->QueryInfo (HTTP_QUERY_CONTENT_LENGTH, sz, &dw, &dwFlags, NULL);
		if (*sz)
			m_uFileSize = _atoi64 (sz);

		*sz = 0; dw = sizeof (sz); dwFlags = 0;
		spHttpInfo->QueryInfo (HTTP_QUERY_CONTENT_DISPOSITION, sz, &dw, &dwFlags, NULL);
		if (*sz)
			ExtractFileNameFromContentDisposition (sz);
	}
	
	IWinInetInfoPtr spWinInetInfo (pib);
	ATLASSERT (spWinInetInfo != NULL);
	if (spWinInetInfo != NULL)
	{
		

		*sz = 0; dw = sizeof (sz);
		spWinInetInfo->QueryOption (INTERNET_OPTION_URL, sz, &dw);
		if (*sz)
			m_strUrl = sz;
	}

	ATLASSERT (!m_strUrl.empty ());

	if (!m_bHttp && !m_strUrl.empty ())
	{
		m_bHttp = strnicmp (m_strUrl.c_str (), "http:", 5) == 0 || 
			strnicmp (m_strUrl.c_str (), "https:", 6) == 0;
	}

	if (m_tstrFileName.empty () && !m_strUrl.empty ())
	{
		string str = vmsHttpHelper::ExtractFileName (m_strUrl.c_str ());
		string str2;

		if (m_bHttp)
		{
			vmsHttpHelper::DecodeUrl (str.c_str (), str2);
			if (vmsStringsHelper::isUtf8String (str2.c_str ()))
			{
				int iLen = MultiByteToWideChar (CP_UTF8, 0, str2.c_str (), -1, NULL, 0);
				if (iLen > 0)
				{
					USES_CONVERSION;
					LPWSTR pwsz = new wchar_t [++iLen];
					MultiByteToWideChar (CP_UTF8, 0, str2.c_str (), -1, pwsz, iLen);
					m_tstrFileName = W2CT (pwsz);
					delete [] pwsz;
				}
			}
		}
		else
		{
			str2 = str;
		}

		if (m_tstrFileName.empty ())
		{
			USES_CONVERSION;
			m_tstrFileName = A2CT (str2.c_str ());
		}
	}

	if (!m_strUrl.empty ())
		vmsHttpHelper::ExtractHostName (m_strUrl.c_str (), m_strHostName);

	if (m_bDoFailInStartBinding)
		return E_FAIL;

	if (m_uFileSize != _UI64_MAX && m_uFileSize > 2*1024*1024*1024i64)
		return E_FAIL;

	m_htDownload = CreateThread (NULL, 0, _threadDownload, this, 0, &dw);
	return S_OK;
}