Example #1
0
static String queryHTTPHeader(HINTERNET requestHandle, DWORD infoLevel)
{
    DWORD bufferSize = 0;
    HttpQueryInfoW(requestHandle, infoLevel, 0, &bufferSize, 0);

    Vector<UChar> characters(bufferSize / sizeof(UChar));

    if (!HttpQueryInfoW(requestHandle, infoLevel, characters.data(), &bufferSize, 0))
        return String();

    characters.removeLast(); // Remove NullTermination.
    return String::adopt(characters);
}
Example #2
0
File: http.c Project: bilboed/wine
static LPWSTR query_http_info(HttpProtocol *This, DWORD option)
{
    LPWSTR ret = NULL;
    DWORD len = 0;
    BOOL res;

    res = HttpQueryInfoW(This->base.request, option, NULL, &len, NULL);
    if (!res && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
        ret = heap_alloc(len);
        res = HttpQueryInfoW(This->base.request, option, ret, &len, NULL);
    }
    if(!res) {
        TRACE("HttpQueryInfoW(%d) failed: %08x\n", option, GetLastError());
        heap_free(ret);
        return NULL;
    }

    return ret;
}
Example #3
0
// Download content of a url to a file
bool HttpGetToFile(const WCHAR *url, const WCHAR *destFilePath)
{
    bool ok = false;
    HINTERNET  hReq = nullptr, hInet = nullptr;
    DWORD dwRead = 0;
    DWORD headerBuffSize = sizeof(DWORD);
    DWORD statusCode = 0;
    char buf[1024];

    HANDLE hf = CreateFile(destFilePath, GENERIC_WRITE, FILE_SHARE_READ, nullptr,
            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,  nullptr);
    if (INVALID_HANDLE_VALUE == hf)
        goto Exit;

    hInet = InternetOpen(USER_AGENT, INTERNET_OPEN_TYPE_PRECONFIG, nullptr, nullptr, 0);
    if (!hInet)
        goto Exit;

    hReq = InternetOpenUrl(hInet, url, nullptr, 0, 0, 0);
    if (!hReq)
        goto Exit;

    if (!HttpQueryInfoW(hReq, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &statusCode, &headerBuffSize, nullptr)) {
        goto Exit;
    }
    if (statusCode != 200) {
        goto Exit;
    }

    for (;;) {
        if (!InternetReadFile(hReq, buf, sizeof(buf), &dwRead))
            goto Exit;
        if (dwRead == 0)
            break;
        DWORD size;
        BOOL wroteOk = WriteFile(hf, buf, (DWORD)dwRead, &size, nullptr);
        if (!wroteOk)
            goto Exit;

        if (size != dwRead)
            goto Exit;
    }

    ok = true;
Exit:
    CloseHandle(hf);
    if (hReq)
        InternetCloseHandle(hReq);
    if (hInet)
        InternetCloseHandle(hInet);
    if (!ok)
        file::Delete(destFilePath);
    return ok;
}
Example #4
0
File: ftp.c Project: AlexSteel/wine
static HRESULT WINAPI HttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption,
        void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved)
{
    FtpProtocol *This = impl_from_IWinInetHttpInfo(iface);
    TRACE("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);

    if(!This->base.request)
        return E_FAIL;

    if(!HttpQueryInfoW(This->base.request, dwOption, pBuffer, pcbBuffer, pdwFlags))
        return S_FALSE;
    return S_OK;
}
Example #5
0
// returns false if failed to download or status code is not 200
// for other scenarios, check HttpRsp
bool  HttpGet(const WCHAR *url, HttpRsp *rspOut)
{
    HINTERNET hReq = nullptr;
    DWORD headerBuffSize = sizeof(DWORD);
    DWORD flags = INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RELOAD;

    rspOut->error = ERROR_SUCCESS;
    HINTERNET hInet = InternetOpen(USER_AGENT, INTERNET_OPEN_TYPE_PRECONFIG, nullptr, nullptr, 0);
    if (!hInet)
        goto Error;

    hReq = InternetOpenUrl(hInet, url, nullptr, 0, flags, 0);
    if (!hReq)
        goto Error;

    if (!HttpQueryInfoW(hReq, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &rspOut->httpStatusCode, &headerBuffSize, nullptr)) {
        goto Error;
    }

    for (;;) {
        char buf[1024];
        DWORD dwRead = 0;
        if (!InternetReadFile(hReq, buf, sizeof(buf), &dwRead)) {
            goto Error;
        }
        if (0 == dwRead) {
            break;
        }
        bool ok = rspOut->data.AppendChecked(buf, dwRead);
        if (!ok)
            goto Error;
    }

Exit:
    if (hReq)
        InternetCloseHandle(hReq);
    if (hInet)
        InternetCloseHandle(hInet);
    return HttpRspOk(rspOut);

Error:
    rspOut->error = GetLastError();
    if (0 == rspOut->error)
        rspOut->error = ERROR_GEN_FAILURE;
    goto Exit;
}
Example #6
0
/***********************************************************************
 *         WININET_GetConnectionStatus
 */
static INT WININET_GetConnectionStatus( HINTERNET hRequest )
{
    WCHAR szStatus[0x20];
    DWORD sz, index, dwStatus;

    TRACE("%p\n", hRequest );

    sz = sizeof szStatus;
    index = 0;
    if( !HttpQueryInfoW( hRequest, HTTP_QUERY_STATUS_CODE,
                    szStatus, &sz, &index))
        return -1;
    dwStatus = atoiW( szStatus );

    TRACE("request %p status = %d\n", hRequest, dwStatus );

    return dwStatus;
}
/*!
 * @brief Wrapper around WinINET-specific request response validation.
 * @param hReq HTTP request handle.
 * @param ctx The HTTP transport context.
 * @return An indication of the result of getting a response.
 */
static DWORD validate_response_wininet(HANDLE hReq, HttpTransportContext* ctx)
{
	DWORD statusCode;
	DWORD statusCodeSize = sizeof(statusCode);
	vdprintf("[PACKET RECEIVE WININET] Getting the result code...");
	if (HttpQueryInfoW(hReq, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &statusCode, &statusCodeSize, 0))
	{
		vdprintf("[PACKET RECEIVE WININET] Returned status code is %d", statusCode);

		// did the request succeed?
		if (statusCode != 200)
		{
			// bomb out
			return ERROR_BAD_CONFIGURATION;
		}
	}

	return ERROR_SUCCESS;
}
Example #8
0
/***********************************************************************
 *         WININET_GetAuthRealm
 *
 *  Determine the name of the (basic) Authentication realm
 */
static BOOL WININET_GetAuthRealm( HINTERNET hRequest, LPWSTR szBuf, DWORD sz, BOOL proxy )
{
    LPWSTR p, q;
    DWORD index, query;
    static const WCHAR szRealm[] = { 'r','e','a','l','m','=',0 };

    if (proxy)
        query = HTTP_QUERY_PROXY_AUTHENTICATE;
    else
        query = HTTP_QUERY_WWW_AUTHENTICATE;

    /* extract the Realm from the response and show it */
    index = 0;
    if( !HttpQueryInfoW( hRequest, query, szBuf, &sz, &index) )
        return FALSE;

    /*
     * FIXME: maybe we should check that we're
     * dealing with 'Basic' Authentication
     */
    p = strchrW( szBuf, ' ' );
    if( !p || strncmpW( p+1, szRealm, strlenW(szRealm) ) )
    {
        ERR("response wrong? (%s)\n", debugstr_w(szBuf));
        return FALSE;
    }

    /* remove quotes */
    p += 7;
    if( *p == '"' )
    {
        p++;
        q = strrchrW( p, '"' );
        if( q )
            *q = 0;
    }
    strcpyW( szBuf, p );

    return TRUE;
}
Example #9
0
//
//	This function used for full page replace. The idea is to redirect querying any infromation from the source page 
//	 HTTTP headers to the result page HTTP headers.
//
static BOOL HttpQueryInfoCommon(
	HINTERNET	hRequest, 
	DWORD		dwInfoLevel, 
	LPVOID		lpvBuffer, 
	LPDWORD		lpdwBufferLength, 
	LPDWORD		lpdwIndex,
	BOOL		bUnicode
	)
{
	BOOL Ret = FALSE;
	PHANDLE_CONTEXT Ctx;

	if (Ctx = FindHandle(hRequest))
	{
		// Checking if the page will be replaced
		if (Ctx->Flags & CF_REPLACE)
		{
			PTRANSFER_CONTEXT	tCtx = (PTRANSFER_CONTEXT)Ctx->tCtx;

			DbgPrint("ISFB_%04x: HttpQueryInfo replace, dwInfoLevel = %u\n", g_CurrentProcessId, dwInfoLevel);

			// Copmlete loading of the page to replace with
			if ((tCtx) && ((tCtx->Headers) || (TransferCompleteReceive(tCtx, TRUE) == NO_ERROR)))
				// Replacing request handle
				hRequest = tCtx->hRequest;
		}	// if (Ctx->Flags & CF_REPLACE)
		ReleaseHandle(Ctx);
	}	// if (Ctx = FindHandle(hRequest))

	if (bUnicode)
		Ret = HttpQueryInfoW(hRequest, dwInfoLevel, lpvBuffer, lpdwBufferLength, lpdwIndex);
	else
		Ret = HttpQueryInfoA(hRequest, dwInfoLevel, lpvBuffer, lpdwBufferLength, lpdwIndex);

	return(Ret);
}
Example #10
0
		bool				inet_get_resource_range(const wstring& url,__int64 start,__int64 length,inet_reader& reader)
		{
			wstring url2=inet_canonicalize_url(url);

			bool succ=false;

			HINTERNET handle_internet=NULL;
			HINTERNET handle_url=NULL;
			HINTERNET handle_connect=NULL;
			HINTERNET handle_file=NULL;

			inet_url_parts parts=inet_crack_url(url2);
			do
			{
				if(parts.scheme==INTERNET_SCHEME_HTTP)
				{
					handle_internet=InternetOpenW(INET_USER_AGENT.c_str(),INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
					if(!handle_internet)
						break;
					wstring header;
					if(length<0)
						header=FORMATW(L"Range: bytes=%I64d-",start);
					else
						header=FORMATW(L"Range: bytes=%I64d-%I64d",start,start+length-1);
					handle_url=InternetOpenUrlW(handle_internet,url2.c_str(),header.c_str(),0,0,NULL);
					if(!handle_url)
						break;

					wchar_t buffer[4096];
					DWORD buffer_len=sizeof(buffer);
					DWORD index=0;

					__int64 len=-1;

					if(HttpQueryInfoW(handle_url,HTTP_QUERY_CONTENT_LENGTH,buffer,&buffer_len,&index))
						len=_wtoi64(buffer);

					reader.run(handle_url);
				}
				else if(parts.scheme==INTERNET_SCHEME_FTP)
				{
					handle_internet=InternetOpenW(INET_USER_AGENT.c_str(),INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
					if(!handle_internet)
						break;
					handle_connect=InternetConnectW(handle_internet,parts.hostname.c_str(),parts.port,parts.username.c_str(),parts.password.c_str(),INTERNET_SERVICE_FTP,INTERNET_FLAG_PASSIVE,NULL);
					if(!handle_connect)
						break;
					wstring command=FORMATW(L"REST %I64d",start);
					FtpCommandW(handle_connect,FALSE,FTP_TRANSFER_TYPE_BINARY,command.c_str(),NULL,NULL);

					handle_file=FtpOpenFileW(handle_connect,parts.url_path.c_str(),GENERIC_READ,FTP_TRANSFER_TYPE_BINARY,NULL);
					if(!handle_file)
						break;

					reader.run(handle_file);
				}
				else
					break;
			}while(false);

			if(handle_file)
				InternetCloseHandle(handle_file);
			if(handle_connect)
				InternetCloseHandle(handle_connect);
			if(handle_url)
				InternetCloseHandle(handle_url);
			if(handle_internet)
				InternetCloseHandle(handle_internet);

			return true;
		}
Example #11
0
		__int64				inet_get_resource_size(const wstring& url)
		{
			wstring url2=inet_canonicalize_url(url);

			__int64 res_size=-1;
			bool succ=false;

			HINTERNET handle_internet=NULL;
			HINTERNET handle_url=NULL;
			HINTERNET handle_connect=NULL;
			HINTERNET handle_file=NULL;

			inet_url_parts parts=inet_crack_url(url2);
			do
			{
				if(parts.scheme==INTERNET_SCHEME_HTTP)
				{
					handle_internet=InternetOpenW(INET_USER_AGENT.c_str(),INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
					if(!handle_internet)
						break;
					handle_url=InternetOpenUrlW(handle_internet,url2.c_str(),NULL,0,0,NULL);
					if(!handle_url)
						break;

					wchar_t buffer[4096];
					DWORD buffer_len=sizeof(buffer);
					DWORD index=0;
					if(!HttpQueryInfoW(handle_url,HTTP_QUERY_CONTENT_LENGTH,buffer,&buffer_len,&index))
						break;
					res_size=_wtoi64(buffer);

					succ=true;
				}
				else if(parts.scheme==INTERNET_SCHEME_FTP)
				{
					handle_internet=InternetOpenW(INET_USER_AGENT.c_str(),INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0);
					if(!handle_internet)
						break;
					handle_connect=InternetConnectW(handle_internet,parts.hostname.c_str(),parts.port,parts.username.c_str(),parts.password.c_str(),INTERNET_SERVICE_FTP,INTERNET_FLAG_PASSIVE,NULL);
					if(!handle_connect)
						break;
					handle_file=FtpOpenFile(handle_connect,parts.url_path.c_str(),GENERIC_READ,FTP_TRANSFER_TYPE_BINARY,NULL);
					if(!handle_file)
						break;
					DWORD low,high;
					low=FtpGetFileSize(handle_file,&high);
					if(low==(~0))
						break;
					res_size=low|(((__int64)high)<<32);

					succ=true;
				}
				else
					break;
			}while(false);

			if(handle_file)
				InternetCloseHandle(handle_file);
			if(handle_connect)
				InternetCloseHandle(handle_connect);
			if(handle_url)
				InternetCloseHandle(handle_url);
			if(handle_internet)
				InternetCloseHandle(handle_internet);

			return res_size;
		}
Example #12
0
    void InetProcessCookies(HTTP_REQUEST_HANDLE *lpReq)
    {
        if ((lpReq) && (lpReq->dwType == HTTP_REQUEST))
        {
            EnterSafeCriticalSection(&lpReq->lpUrl->lpSession->csSession);
            {
                WCHAR *lpUrl=NULL,
                      *lpPath=NULL,
                      *lpHost=NULL;
                do
                {
                    DWORD dwLen=INTERNET_MAX_URL_LENGTH*sizeof(WCHAR);
                    lpUrl=(WCHAR*)MemQuickAlloc(dwLen);
                    if (!lpUrl)
                        break;

                    if (!InternetQueryOptionW(lpReq->hReq,INTERNET_OPTION_URL,lpUrl,&dwLen))
                        break;

                    lpPath=WCHAR_QuickAlloc(INTERNET_MAX_PATH_LENGTH);
                    if (!lpPath)
                        break;

                    lpHost=WCHAR_QuickAlloc(INTERNET_MAX_HOST_NAME_LENGTH);
                    if (!lpHost)
                        break;

                    URL_COMPONENTSW url={0};
                    url.dwStructSize=sizeof(url);
                    url.lpszHostName=lpHost;
                    url.dwHostNameLength=INTERNET_MAX_HOST_NAME_LENGTH;
                    url.lpszUrlPath=lpPath;
                    url.dwUrlPathLength=INTERNET_MAX_PATH_LENGTH;
                    if (!InternetCrackUrlW(lpUrl,NULL,0,&url))
                        break;

                    DWORD i=0;
                    while (true)
                    {
                        WCHAR *lpCookie=NULL,szTmp[1];
                        DWORD dwSize=0;
                        if ((HttpQueryInfoW(lpReq->hReq,HTTP_QUERY_SET_COOKIE,szTmp,&dwSize,&i)) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
                            break;

                        dwSize+=2;
                        lpCookie=(WCHAR*)MemQuickAlloc(dwSize);
                        if (!lpCookie)
                            break;

                        if (HttpQueryInfoW(lpReq->hReq,HTTP_QUERY_SET_COOKIE,lpCookie,&dwSize,&i))
                        {
                            WCHAR *lpData=StrChrW(lpCookie,L'=');
                            if (lpData)
                            {
                                *lpData++=0;
                                Cookie_Parse(lpReq->lpUrl->lpSession,lpHost,lpPath,lpCookie,lpData);
                            }
                        }
                        MemFree(lpCookie);
                    }
                }
                while (false);

                MemFree(lpUrl);
                MemFree(lpPath);
                MemFree(lpHost);
            }
            LeaveSafeCriticalSection(&lpReq->lpUrl->lpSession->csSession);
        }
        return;
    }
Example #13
0
int64_t Downloader::downloadWin(Job* job, const Request& request,
        Downloader::Response* response)
{
    QUrl url = request.url;
    QString verb = request.httpMethod;
    QFile* file = request.file;
    QString* mime = &response->mimeType;
    QString* contentDisposition = &response->contentDisposition;
    HWND parentWindow = defaultPasswordWindow;
    QString* sha1 = &response->hashSum;
    bool useCache = request.useCache;
    QCryptographicHash::Algorithm alg = request.alg;
    bool keepConnection = request.keepConnection;
    int timeout = request.timeout;
    bool interactive = request.interactive;

    QString initialTitle = job->getTitle();

    job->setTitle(initialTitle + " / " + QObject::tr("Connecting"));

    if (sha1)
        sha1->clear();

    QString server = url.host();
    QString resource = url.path();
    QString encQuery = url.query(QUrl::FullyEncoded);
    if (!encQuery.isEmpty())
        resource.append('?').append(encQuery);

    QString agent("Npackd/");
    agent.append(NPACKD_VERSION);

    agent += " (compatible; MSIE 9.0)";

    HINTERNET internet = InternetOpenW((WCHAR*) agent.utf16(),
            INTERNET_OPEN_TYPE_PRECONFIG,
            0, 0, 0);

    if (internet == 0) {
        QString errMsg;
        WPMUtils::formatMessage(GetLastError(), &errMsg);
        job->setErrorMessage(errMsg);
    }

    if (job->shouldProceed()) {
        // change the timeout to 5 minutes
        DWORD rec_timeout = timeout * 1000;
        InternetSetOption(internet, INTERNET_OPTION_RECEIVE_TIMEOUT,
                &rec_timeout, sizeof(rec_timeout));

        // enable automatic gzip decoding
        const DWORD INTERNET_OPTION_HTTP_DECODING = 65;
        BOOL b = TRUE;
        InternetSetOption(internet, INTERNET_OPTION_HTTP_DECODING,
                &b, sizeof(b));

        job->setProgress(0.01);
    }

    HINTERNET hConnectHandle = 0;
    if (job->shouldProceed()) {
        INTERNET_PORT port = url.port(url.scheme() == "https" ?
                INTERNET_DEFAULT_HTTPS_PORT: INTERNET_DEFAULT_HTTP_PORT);
        hConnectHandle = InternetConnectW(internet,
                (WCHAR*) server.utf16(), port, 0, 0, INTERNET_SERVICE_HTTP, 0, 0);

        if (hConnectHandle == 0) {
            QString errMsg;
            WPMUtils::formatMessage(GetLastError(), &errMsg);
            job->setErrorMessage(errMsg);
        }
    }


    // flags: http://msdn.microsoft.com/en-us/library/aa383661(v=vs.85).aspx
    // We support accepting any mime file type since this is a simple download
    // of a file
    HINTERNET hResourceHandle = 0;
    if (job->shouldProceed()) {
        LPCTSTR ppszAcceptTypes[2];
        ppszAcceptTypes[0] = L"*/*";
        ppszAcceptTypes[1] = NULL;
        DWORD flags = (url.scheme() == "https" ? INTERNET_FLAG_SECURE : 0);
        if (keepConnection)
            flags |= INTERNET_FLAG_KEEP_CONNECTION;
        flags |= INTERNET_FLAG_RESYNCHRONIZE;
        if (!useCache)
            flags |= INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_PRAGMA_NOCACHE |
                    INTERNET_FLAG_RELOAD;
        hResourceHandle = HttpOpenRequestW(hConnectHandle,
                reinterpret_cast<LPCWSTR>(verb.utf16()),
                (WCHAR*) resource.utf16(),
                0, 0, ppszAcceptTypes,
                flags, 0);
        if (hResourceHandle == 0) {
            QString errMsg;
            WPMUtils::formatMessage(GetLastError(), &errMsg);
            job->setErrorMessage(errMsg);
        }
    }

    if (job->shouldProceed()) {
        job->checkOSCall(HttpAddRequestHeadersW(hResourceHandle,
                L"Accept-Encoding: gzip, deflate", -1,
                HTTP_ADDREQ_FLAG_ADD));
    }

    DWORD dwStatus, dwStatusSize = sizeof(dwStatus);

    // qDebug() << "download.5";
    int callNumber = 0;
    while (job->shouldProceed()) {
        // qDebug() << "download.5.1";

        DWORD sendRequestError = 0;
        if (!HttpSendRequestW(hResourceHandle,
                reinterpret_cast<LPCWSTR>(request.headers.utf16()), -1,
                const_cast<char*>(request.postData.data()),
                request.postData.length())) {
            sendRequestError = GetLastError();
        }

        // http://msdn.microsoft.com/en-us/library/aa384220(v=vs.85).aspx
        if (!HttpQueryInfo(hResourceHandle, HTTP_QUERY_FLAG_NUMBER |
                HTTP_QUERY_STATUS_CODE, &dwStatus, &dwStatusSize, NULL)) {
            QString errMsg;
            WPMUtils::formatMessage(GetLastError(), &errMsg);
            job->setErrorMessage(errMsg);
            break;
        }

        /*
        qDebug() << callNumber <<
                sendRequestError << dwStatus << request.httpMethod <<
                request.url.toString();
        */

        // 2XX
        if (sendRequestError == 0) {
            DWORD hundreds = dwStatus / 100;
            if (hundreds == 2 || hundreds == 5)
                break;
        }

        // the InternetErrorDlg calls below can either handle
        // sendRequestError <> 0 or HTTP error code <> 2xx

        void* p = 0;

        // both calls to InternetErrorDlg should be enclosed by one
        // mutex, so that only one dialog will be shown
        loginDialogMutex.lock();

        DWORD r;

        if (callNumber == 0) {
            r = InternetErrorDlg(0,
                   hResourceHandle, sendRequestError,
                    FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
                    FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS |
                    FLAGS_ERROR_UI_FLAGS_GENERATE_DATA |
                    FLAGS_ERROR_UI_FLAGS_NO_UI, &p);
            if (r == ERROR_SUCCESS && interactive)
                r = ERROR_INTERNET_FORCE_RETRY;
        } else if (interactive) {
            if (parentWindow) {
                r = InternetErrorDlg(parentWindow,
                        hResourceHandle, sendRequestError,
                        FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
                        FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS |
                        FLAGS_ERROR_UI_FLAGS_GENERATE_DATA, &p);
            } else {
                QString e = inputPassword(hConnectHandle, dwStatus);

                //qDebug() << "inputPassword: "******"HTTP status code %1")).arg(dwStatus));
            }
        } else if (r == ERROR_INTERNET_FORCE_RETRY) {
            // nothing
        } else if (r == ERROR_CANCELLED) {
            job->setErrorMessage(QObject::tr("Cancelled by the user"));
        } else if (r == ERROR_INVALID_HANDLE) {
            job->setErrorMessage(QObject::tr("Invalid handle"));
        } else {
            job->setErrorMessage(QString(
                    QObject::tr("Unknown error %1 from InternetErrorDlg")).arg(r));
        }

        loginDialogMutex.unlock();

        if (!job->shouldProceed())
            break;

        // read all the data before re-sending the request
        char smallBuffer[4 * 1024];
        while (true) {
            DWORD read;
            if (!InternetReadFile(hResourceHandle, &smallBuffer,
                    sizeof(smallBuffer), &read)) {
                QString errMsg;
                WPMUtils::formatMessage(GetLastError(), &errMsg);
                job->setErrorMessage(errMsg);
                goto out;
            }

            // qDebug() << "read some bytes " << read;
            if (read == 0)
                break;
        }

        callNumber++;
    }; // while (job->shouldProceed())

out:
    if (job->shouldProceed()) {
        // http://msdn.microsoft.com/en-us/library/aa384220(v=vs.85).aspx
        if (!HttpQueryInfo(hResourceHandle, HTTP_QUERY_FLAG_NUMBER |
                HTTP_QUERY_STATUS_CODE, &dwStatus, &dwStatusSize, NULL)) {
            QString errMsg;
            WPMUtils::formatMessage(GetLastError(), &errMsg);
            job->setErrorMessage(errMsg);
        } else {
            // 2XX
            if (dwStatus / 100 != 2) {
                job->setErrorMessage(QString(
                        QObject::tr("HTTP status code %1")).arg(dwStatus));
            }
        }
    }

    if (job->shouldProceed()) {
        job->setProgress(0.03);
        job->setTitle(initialTitle + " / " + QObject::tr("Downloading"));
    }

    // MIME type
    if (job->shouldProceed()) {
        if (mime) {
            WCHAR mimeBuffer[1024];
            DWORD bufferLength = sizeof(mimeBuffer);
            DWORD index = 0;
            if (!HttpQueryInfoW(hResourceHandle, HTTP_QUERY_CONTENT_TYPE,
                    &mimeBuffer, &bufferLength, &index)) {
                QString errMsg;
                WPMUtils::formatMessage(GetLastError(), &errMsg);
                job->setErrorMessage(errMsg);
            } else {
                mime->setUtf16((ushort*) mimeBuffer, bufferLength / 2);
            }
        }
    }

    bool gzip = false;

    // Content-Encoding
    if (job->shouldProceed()) {
        WCHAR contentEncodingBuffer[1024];
        DWORD bufferLength = sizeof(contentEncodingBuffer);
        DWORD index = 0;
        if (HttpQueryInfoW(hResourceHandle, HTTP_QUERY_CONTENT_ENCODING,
                &contentEncodingBuffer, &bufferLength, &index)) {
            QString contentEncoding;
            contentEncoding.setUtf16((ushort*) contentEncodingBuffer,
                    bufferLength / 2);
            gzip = contentEncoding == "gzip" || contentEncoding == "deflate";
        }

        job->setProgress(0.04);
    }

    // Content-Disposition
    if (job->shouldProceed()) {
        if (contentDisposition) {
            WCHAR cdBuffer[1024];
            wcscpy(cdBuffer, L"Content-Disposition");
            DWORD bufferLength = sizeof(cdBuffer);
            DWORD index = 0;
            if (HttpQueryInfoW(hResourceHandle, HTTP_QUERY_CUSTOM,
                    &cdBuffer, &bufferLength, &index)) {
                contentDisposition->setUtf16((ushort*) cdBuffer,
                        bufferLength / 2);
            }
        }
    }

    int64_t contentLength = -1;

    // content length
    if (job->shouldProceed()) {
        WCHAR contentLengthBuffer[100];
        DWORD bufferLength = sizeof(contentLengthBuffer);
        DWORD index = 0;
        if (HttpQueryInfoW(hResourceHandle, HTTP_QUERY_CONTENT_LENGTH,
                contentLengthBuffer, &bufferLength, &index)) {
            QString s;
            s.setUtf16((ushort*) contentLengthBuffer, bufferLength / 2);
            bool ok;
            contentLength = s.toLongLong(&ok, 10);
            if (!ok)
                contentLength = 0;
        }

        job->setProgress(0.05);
    }

    if (job->shouldProceed()) {
        Job* sub = job->newSubJob(0.95, QObject::tr("Reading the data"));
        readData(sub, hResourceHandle, file, sha1, gzip, contentLength, alg);
        if (!sub->getErrorMessage().isEmpty())
            job->setErrorMessage(sub->getErrorMessage());
    }

    if (hResourceHandle)
        InternetCloseHandle(hResourceHandle);
    if (hConnectHandle)
        InternetCloseHandle(hConnectHandle);
    if (internet)
        InternetCloseHandle(internet);

    if (job->shouldProceed())
        job->setProgress(1);

    job->setTitle(initialTitle);

    job->complete();

    return contentLength;
}
Example #14
0
File: http.c Project: ccpgames/wine
static HRESULT HttpProtocol_start_downloading(Protocol *prot)
{
    HttpProtocol *This = impl_from_Protocol(prot);
    LPWSTR content_type, content_length, ranges;
    DWORD len = sizeof(DWORD);
    DWORD status_code;
    BOOL res;
    HRESULT hres;

    static const WCHAR wszDefaultContentType[] =
        {'t','e','x','t','/','h','t','m','l',0};

    if(!This->http_negotiate) {
        WARN("Expected IHttpNegotiate pointer to be non-NULL\n");
        return S_OK;
    }

    res = HttpQueryInfoW(This->base.request, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
            &status_code, &len, NULL);
    if(res) {
        WCHAR *response_headers;

        if((This->base.bind_info.dwOptions & BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS) && is_redirect_response(status_code)) {
            WCHAR *location;

            TRACE("Got redirect with disabled auto redirects\n");

            location = query_http_info(This, HTTP_QUERY_LOCATION);
            This->base.flags |= FLAG_RESULT_REPORTED | FLAG_LAST_DATA_REPORTED;
            IInternetProtocolSink_ReportResult(This->base.protocol_sink, INET_E_REDIRECT_FAILED, 0, location);
            heap_free(location);
            return INET_E_REDIRECT_FAILED;
        }

        response_headers = query_http_info(This, HTTP_QUERY_RAW_HEADERS_CRLF);
        if(response_headers) {
            hres = IHttpNegotiate_OnResponse(This->http_negotiate, status_code, response_headers,
                    NULL, NULL);
            heap_free(response_headers);
            if (hres != S_OK) {
                WARN("IHttpNegotiate_OnResponse failed: %08x\n", hres);
                return S_OK;
            }
        }
    }else {
        WARN("HttpQueryInfo failed: %d\n", GetLastError());
    }

    ranges = query_http_info(This, HTTP_QUERY_ACCEPT_RANGES);
    if(ranges) {
        IInternetProtocolSink_ReportProgress(This->base.protocol_sink, BINDSTATUS_ACCEPTRANGES, NULL);
        heap_free(ranges);
    }

    content_type = query_http_info(This, HTTP_QUERY_CONTENT_TYPE);
    if(content_type) {
        /* remove the charset, if present */
        LPWSTR p = strchrW(content_type, ';');
        if (p) *p = '\0';

        IInternetProtocolSink_ReportProgress(This->base.protocol_sink,
                (This->base.bindf & BINDF_FROMURLMON)
                 ? BINDSTATUS_MIMETYPEAVAILABLE : BINDSTATUS_RAWMIMETYPE,
                 content_type);
        heap_free(content_type);
    }else {
        WARN("HttpQueryInfo failed: %d\n", GetLastError());
        IInternetProtocolSink_ReportProgress(This->base.protocol_sink,
                 (This->base.bindf & BINDF_FROMURLMON)
                  ? BINDSTATUS_MIMETYPEAVAILABLE : BINDSTATUS_RAWMIMETYPE,
                  wszDefaultContentType);
    }

    content_length = query_http_info(This, HTTP_QUERY_CONTENT_LENGTH);
    if(content_length) {
        This->base.content_length = atoiW(content_length);
        heap_free(content_length);
    }

    return S_OK;
}
Example #15
0
static
DWORD WINAPI
ThreadFunc(LPVOID Context)
{
    CComPtr<IBindStatusCallback> dl;
    WCHAR path[MAX_PATH];
    PWSTR p, q;
    HWND Dlg = (HWND) Context;
    ULONG dwContentLen, dwBytesWritten, dwBytesRead, dwStatus;
    ULONG dwCurrentBytesRead = 0;
    ULONG dwStatusLen = sizeof(dwStatus);
    BOOL bCancelled = FALSE;
    BOOL bTempfile = FALSE;
    BOOL bCab = FALSE;
    HINTERNET hOpen = NULL;
    HINTERNET hFile = NULL;
    HANDLE hOut = INVALID_HANDLE_VALUE;
    unsigned char lpBuffer[4096];
    PCWSTR lpszAgent = L"RApps/1.0";
    URL_COMPONENTS urlComponents;
    size_t urlLength, filenameLength;

    /* build the path for the download */
    p = wcsrchr(AppInfo->szUrlDownload, L'/');
    q = wcsrchr(AppInfo->szUrlDownload, L'?');
 
    /* do we have a final slash separator? */
    if (!p)
        goto end;

    /* prepare the tentative length of the filename, maybe we've to remove part of it later on */
    filenameLength = wcslen(p) * sizeof(WCHAR);

    /* do we have query arguments in the target URL after the filename? account for them
      (e.g. https://example.org/myfile.exe?no_adware_plz) */
    if (q && q > p && (q - p) > 0)
        filenameLength -= wcslen(q - 1) * sizeof(WCHAR);

    /* is this URL an update package for RAPPS? if so store it in a different place */
    if (wcscmp(AppInfo->szUrlDownload, APPLICATION_DATABASE_URL) == 0)
    {
        bCab = TRUE;
        if (!GetStorageDirectory(path, _countof(path)))
            goto end;
    }
    else
    {
        if (FAILED(StringCbCopyW(path, sizeof(path),  SettingsInfo.szDownloadDir)))
            goto end;
    }

    /* is the path valid? can we access it? */
    if (GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES)
    {
        if (!CreateDirectoryW(path, NULL))
            goto end;
    }

    /* append a \ to the provided file system path, and the filename portion from the URL after that */
    if (FAILED(StringCbCatW(path, sizeof(path), L"\\")))
        goto end;
    if (FAILED(StringCbCatNW(path, sizeof(path), p + 1, filenameLength)))
        goto end;

    if (!bCab && AppInfo->szSHA1[0] != 0 && GetFileAttributesW(path) != INVALID_FILE_ATTRIBUTES)
    {
        /* only open it in case of total correctness */
        if (VerifyInteg(AppInfo->szSHA1, path))
            goto run;
    }

    /* download it */
    bTempfile = TRUE;
    CDownloadDialog_Constructor(Dlg, &bCancelled, IID_PPV_ARG(IBindStatusCallback, &dl));

    if (dl == NULL)
        goto end;

    /* FIXME: this should just be using the system-wide proxy settings */
    switch(SettingsInfo.Proxy)
    {
        case 0: /* preconfig */
            hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
            break;
        case 1: /* direct (no proxy) */
            hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
            break;
        case 2: /* use proxy */
            hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_PROXY, SettingsInfo.szProxyServer, SettingsInfo.szNoProxyFor, 0);
            break;
        default: /* preconfig */
            hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
            break;
    }

    if (!hOpen)
        goto end;

    hFile = InternetOpenUrlW(hOpen, AppInfo->szUrlDownload, NULL, 0, INTERNET_FLAG_PRAGMA_NOCACHE|INTERNET_FLAG_KEEP_CONNECTION, 0);
    if (!hFile)
        goto end;

    if (!HttpQueryInfoW(hFile, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwStatus, &dwStatusLen, NULL))
        goto end;

    if(dwStatus != HTTP_STATUS_OK)
    {
        WCHAR szMsgText[MAX_STR_LEN];

        if (!LoadStringW(hInst, IDS_UNABLE_TO_DOWNLOAD, szMsgText, sizeof(szMsgText) / sizeof(WCHAR)))
            goto end;

        MessageBoxW(hMainWnd, szMsgText, NULL, MB_OK | MB_ICONERROR);
        goto end;
    }

    dwStatusLen = sizeof(dwStatus);

    memset(&urlComponents, 0, sizeof(urlComponents));
    urlComponents.dwStructSize = sizeof(urlComponents);

    if(FAILED(StringCbLengthW(AppInfo->szUrlDownload, sizeof(AppInfo->szUrlDownload), &urlLength)))
        goto end;

    urlLength /= sizeof(WCHAR);
    urlComponents.dwSchemeLength = urlLength + 1;
    urlComponents.lpszScheme = (LPWSTR)malloc(urlComponents.dwSchemeLength * sizeof(WCHAR));
    urlComponents.dwHostNameLength = urlLength + 1;
    urlComponents.lpszHostName = (LPWSTR)malloc(urlComponents.dwHostNameLength * sizeof(WCHAR));

    if(!InternetCrackUrlW(AppInfo->szUrlDownload, urlLength+1, ICU_DECODE | ICU_ESCAPE, &urlComponents))
        goto end;
    
    if(urlComponents.nScheme == INTERNET_SCHEME_HTTP || urlComponents.nScheme == INTERNET_SCHEME_HTTPS)
        HttpQueryInfo(hFile, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &dwContentLen, &dwStatus, 0);

    if(urlComponents.nScheme == INTERNET_SCHEME_FTP)
        dwContentLen = FtpGetFileSize(hFile, &dwStatus);

#ifdef USE_CERT_PINNING
    /* are we using HTTPS to download the RAPPS update package? check if the certificate is original */
    if ((urlComponents.nScheme == INTERNET_SCHEME_HTTPS) &&
        (wcscmp(AppInfo->szUrlDownload, APPLICATION_DATABASE_URL) == 0) &&
        (!CertIsValid(hOpen, urlComponents.lpszHostName)))
    {
        WCHAR szMsgText[MAX_STR_LEN];

        if (!LoadStringW(hInst, IDS_CERT_DOES_NOT_MATCH, szMsgText, sizeof(szMsgText) / sizeof(WCHAR)))
            goto end;

        MessageBoxW(Dlg, szMsgText, NULL, MB_OK | MB_ICONERROR);
        goto end;
    }
#endif

    free(urlComponents.lpszScheme);
    free(urlComponents.lpszHostName);

    hOut = CreateFileW(path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);

    if (hOut == INVALID_HANDLE_VALUE)
        goto end;

    do
    {
        if (!InternetReadFile(hFile, lpBuffer, _countof(lpBuffer), &dwBytesRead))
        {
            WCHAR szMsgText[MAX_STR_LEN];

            if (!LoadStringW(hInst, IDS_INTERRUPTED_DOWNLOAD, szMsgText, _countof(szMsgText)))
                goto end;

            MessageBoxW(hMainWnd, szMsgText, NULL, MB_OK | MB_ICONERROR);
            goto end;
        }
        if (!WriteFile(hOut, &lpBuffer[0], dwBytesRead, &dwBytesWritten, NULL))
        {
            WCHAR szMsgText[MAX_STR_LEN];

            if (!LoadStringW(hInst, IDS_UNABLE_TO_WRITE, szMsgText, _countof(szMsgText)))
                goto end;

            MessageBoxW(hMainWnd, szMsgText, NULL, MB_OK | MB_ICONERROR);
            goto end;
        }
        dwCurrentBytesRead += dwBytesRead;
        dl->OnProgress(dwCurrentBytesRead, dwContentLen, 0, AppInfo->szUrlDownload);
    }
    while (dwBytesRead && !bCancelled);

    CloseHandle(hOut);
    hOut = INVALID_HANDLE_VALUE;

    if (bCancelled)
        goto end;

    /* if this thing isn't a RAPPS update and it has a SHA-1 checksum
       verify its integrity by using the native advapi32.A_SHA1 functions */
    if (!bCab && AppInfo->szSHA1[0] != 0)
    {
        WCHAR szMsgText[MAX_STR_LEN];

        /* change a few strings in the download dialog to reflect the verification process */
        LoadStringW(hInst, IDS_INTEG_CHECK_TITLE, szMsgText, _countof(szMsgText));

        SetWindowText(Dlg, szMsgText);
        SendMessageW(GetDlgItem(Dlg, IDC_DOWNLOAD_STATUS), WM_SETTEXT, 0, (LPARAM)path);

        /* this may take a while, depending on the file size */
        if (!VerifyInteg(AppInfo->szSHA1, path))
        {
            if (!LoadStringW(hInst, IDS_INTEG_CHECK_FAIL, szMsgText, _countof(szMsgText)))
                goto end;

            MessageBoxW(Dlg, szMsgText, NULL, MB_OK | MB_ICONERROR);
            goto end;
        }
    }

    ShowWindow(Dlg, SW_HIDE);

run:
    /* run it */
    if (!bCab)
        ShellExecuteW( NULL, L"open", path, NULL, NULL, SW_SHOWNORMAL );

end:
    if (hOut != INVALID_HANDLE_VALUE)
        CloseHandle(hOut);

    InternetCloseHandle(hFile);
    InternetCloseHandle(hOpen);

    if (bTempfile)
    {
        if (bCancelled || (SettingsInfo.bDelInstaller && !bCab))
            DeleteFileW(path);
    }

    EndDialog(Dlg, 0);

    return 0;
}
Example #16
0
static NTSTATUS DownloadUpdateThreadStart(
    __in PVOID Parameter
    )
{
    PPH_STRING downloadUrlPath = NULL;
    HANDLE tempFileHandle = NULL;
    HINTERNET hInitialize = NULL, hConnection = NULL, hRequest = NULL;
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    HWND hwndDlg = (HWND)Parameter;

    Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), FALSE);
    SetDlgItemText(hwndDlg, IDC_STATUS, L"Initializing");

    // Reset the progress state on Vista and above.
    if (WindowsVersion > WINDOWS_XP)
        SendDlgItemMessage(hwndDlg, IDC_PROGRESS, PBM_SETSTATE, PBST_NORMAL, 0L);

    if (!ConnectionAvailable())
        return status;

    __try
    {
        // Get temp dir.
        WCHAR tempPathString[MAX_PATH];
        DWORD tempPathLength = GetTempPath(MAX_PATH, tempPathString);

        if (tempPathLength == 0 || tempPathLength > MAX_PATH)
        {
            LogEvent(hwndDlg, PhFormatString(L"CreateFile failed (%d)", GetLastError()));
            __leave;
        }

        // create the download path string.
        downloadUrlPath = PhFormatString(
            L"/projects/processhacker/files/processhacker2/processhacker-%u.%u-setup.exe/download?use_mirror=autoselect", /* ?use_mirror=waix" */
            UpdateData.MajorVersion,
            UpdateData.MinorVersion
            );

        // Append the tempath to our string: %TEMP%processhacker-%u.%u-setup.exe
        // Example: C:\\Users\\dmex\\AppData\\Temp\\processhacker-2.10-setup.exe
        SetupFilePath = PhFormatString(
            L"%sprocesshacker-%u.%u-setup.exe",
            tempPathString,
            UpdateData.MajorVersion,
            UpdateData.MinorVersion
            );

        // Create output file
        status = PhCreateFileWin32(
            &tempFileHandle,
            SetupFilePath->Buffer,
            FILE_GENERIC_READ | FILE_GENERIC_WRITE,
            FILE_ATTRIBUTE_NOT_CONTENT_INDEXED | FILE_ATTRIBUTE_TEMPORARY,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
            FILE_OVERWRITE_IF,
            FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
            );

        if (!NT_SUCCESS(status))
        {
            LogEvent(hwndDlg, PhFormatString(L"PhCreateFileWin32 failed (%s)", ((PPH_STRING)PHA_DEREFERENCE(PhGetNtMessage(status)))->Buffer));
            __leave;
        }

        {
            // Create a user agent string.
            PPH_STRING phVersion = PhGetPhVersion();
            PPH_STRING userAgent = PhConcatStrings2(L"PH Updater v", phVersion->Buffer);

            // Initialize the wininet library.
            if (!(hInitialize = InternetOpen(
                userAgent->Buffer,
                INTERNET_OPEN_TYPE_PRECONFIG,
                NULL,
                NULL,
                0
                )))
            {
                LogEvent(hwndDlg, PhFormatString(L"Updater: (InitializeConnection) InternetOpen failed (%d)", GetLastError()));

                PhDereferenceObject(userAgent);
                PhDereferenceObject(phVersion);

                __leave;
            }

            PhDereferenceObject(userAgent);
            PhDereferenceObject(phVersion);
        }

        // Connect to the server.
        if (!(hConnection = InternetConnect(
            hInitialize,
            L"sourceforge.net",
            INTERNET_DEFAULT_HTTP_PORT,
            NULL,
            NULL,
            INTERNET_SERVICE_HTTP,
            0,
            0)))
        {
            LogEvent(hwndDlg, PhFormatString(L"InternetConnect failed (%d)", GetLastError()));
            __leave;
        }

        // Open the HTTP request.
        if (!(hRequest = HttpOpenRequest(
            hConnection,
            NULL,
            downloadUrlPath->Buffer,
            NULL,
            NULL,
            NULL,
            INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_RESYNCHRONIZE,
            0
            )))
        {
            LogEvent(hwndDlg, PhFormatString(L"HttpOpenRequest failed (%d)", GetLastError()));
            __leave;
        }

        SetDlgItemText(hwndDlg, IDC_STATUS, L"Connecting");

        // Send the HTTP request.
        if (!HttpSendRequest(hRequest, NULL, 0, NULL, 0))
        {
            LogEvent(hwndDlg, PhFormatString(L"HttpSendRequest failed (%d)", GetLastError()));

            // Enable the 'Retry' button.
            Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), TRUE);
            SetDlgItemText(hwndDlg, IDC_DOWNLOAD, L"Retry");

            // Reset the state and let user retry the download.
            PhUpdaterState = Download;
        }
        else
        {
            BYTE hashBuffer[20]; 
            DWORD contentLengthSize = sizeof(DWORD);
            PH_HASH_CONTEXT hashContext;

            // Initialize hash algorithm.
            PhInitializeHash(&hashContext, Sha1HashAlgorithm);

            if (!HttpQueryInfoW(hRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &contentLength, &contentLengthSize, 0))
            {
                // No content length...impossible to calculate % complete...
                // we can read the data, BUT in this instance Sourceforge always returns the content length
                // so instead we'll exit here instead of downloading the file.
                LogEvent(hwndDlg, PhFormatString(L"HttpQueryInfo failed (%d)", GetLastError()));
                __leave;
            }
            else
            {
                BYTE buffer[PAGE_SIZE];
                DWORD bytesRead = 0, startTick = 0;
                IO_STATUS_BLOCK isb;

                // Zero the buffer.
                ZeroMemory(buffer, PAGE_SIZE);

                // Reset the counters.
                bytesDownloaded = 0, timeTransferred = 0, LastUpdateTime = 0;
                IsUpdating = FALSE;

                // Start the clock.
                startTick = GetTickCount();
                timeTransferred = startTick;

                // Download the data.
                while (InternetReadFile(hRequest, buffer, PAGE_SIZE, &bytesRead))
                {
                    // If we get zero bytes, the file was uploaded or there was an error.
                    if (bytesRead == 0)
                        break;

                    // If window closed and thread handle was closed, just dispose and exit.
                    // (This also skips error checking/prompts and updating the disposed UI)
                    if (!DownloadThreadHandle)
                        __leave;

                    // Update the hash of bytes we downloaded.
                    PhUpdateHash(&hashContext, buffer, bytesRead);

                    // Write the downloaded bytes to disk.
                    status = NtWriteFile(
                        tempFileHandle,
                        NULL,
                        NULL,
                        NULL,
                        &isb,
                        buffer,
                        bytesRead,
                        NULL,
                        NULL
                        );

                    if (!NT_SUCCESS(status))
                    {
                        PPH_STRING message = PhGetNtMessage(status);

                        LogEvent(hwndDlg, PhFormatString(L"NtWriteFile failed (%s)", message->Buffer));

                        PhDereferenceObject(message);
                        break;
                    }

                    // Check dwBytesRead are the same dwBytesWritten length returned by WriteFile.
                    if (bytesRead != isb.Information)
                    {
                        PPH_STRING message = PhGetNtMessage(status);

                        LogEvent(hwndDlg, PhFormatString(L"NtWriteFile failed (%s)", message->Buffer));

                        PhDereferenceObject(message);
                        break;
                    }
                                        
                    // Update our total bytes downloaded
                    PhAcquireQueuedLockExclusive(&Lock);
                    bytesDownloaded += (DWORD)isb.Information;
                    PhReleaseQueuedLockExclusive(&Lock);

                    AsyncUpdate();
                }

                // Check if we downloaded the entire file.
                assert(bytesDownloaded == contentLength);

                // Compute our hash result.
                if (PhFinalHash(&hashContext, &hashBuffer, 20, NULL))
                {
                    // Allocate our hash string, hex the final hash result in our hashBuffer.
                    PPH_STRING hexString = PhBufferToHexString(hashBuffer, 20);

                    if (PhEqualString(hexString, UpdateData.Hash, TRUE))
                    {
                        // If PH is not elevated, set the UAC shield for the install button as the setup requires elevation.
                        if (!PhElevated)
                            SendMessage(GetDlgItem(hwndDlg, IDC_DOWNLOAD), BCM_SETSHIELD, 0, TRUE);

                        // Set the download result, don't include hash status since it succeeded.
                        //SetDlgItemText(hwndDlg, IDC_STATUS, L"Download Complete");
                        // Set button text for next action
                        Button_SetText(GetDlgItem(hwndDlg, IDC_DOWNLOAD), L"Install");
                        // Enable the Install button
                        Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), TRUE);
                        // Hash succeeded, set state as ready to install.
                        PhUpdaterState = Install;
                    }
                    else
                    {
                        if (WindowsVersion > WINDOWS_XP)
                            SendDlgItemMessage(hwndDlg, IDC_PROGRESS, PBM_SETSTATE, PBST_ERROR, 0L);

                        SetDlgItemText(hwndDlg, IDC_STATUS, L"Download complete, SHA1 Hash failed.");

                        // Set button text for next action
                        Button_SetText(GetDlgItem(hwndDlg, IDC_DOWNLOAD), L"Retry");
                        // Enable the Install button
                        Button_Enable(GetDlgItem(hwndDlg, IDC_DOWNLOAD), TRUE);
                        // Hash failed, reset state to downloading so user can redownload the file.
                        PhUpdaterState = Download;
                    }

                    PhDereferenceObject(hexString);
                }
                else
                {
                    //SetDlgItemText(hwndDlg, IDC_STATUS, L"PhFinalHash failed");

                    // Show fancy Red progressbar if hash failed on Vista and above.
                    if (WindowsVersion > WINDOWS_XP)
                        SendDlgItemMessage(hwndDlg, IDC_PROGRESS, PBM_SETSTATE, PBST_ERROR, 0L);
                }
            }
        }

        status = STATUS_SUCCESS;
    }
    __finally
    {
        if (hInitialize)
        {
            InternetCloseHandle(hInitialize);
            hInitialize = NULL;
        }

        if (hConnection)
        {
            InternetCloseHandle(hConnection);
            hConnection = NULL;
        }

        if (hRequest)
        {
            InternetCloseHandle(hRequest);
            hRequest = NULL;
        }

        if (tempFileHandle)
        {
            NtClose(tempFileHandle);
            tempFileHandle = NULL;
        }

        if (downloadUrlPath)
        {
            PhDereferenceObject(downloadUrlPath);
            downloadUrlPath = NULL;
        }
    }

    return status;
}
Example #17
0
static
DWORD WINAPI
ThreadFunc(LPVOID Context)
{
    CComPtr<IBindStatusCallback> dl;
    WCHAR path[MAX_PATH];
    LPWSTR p;
    HWND Dlg = (HWND) Context;
    ULONG dwContentLen, dwBytesWritten, dwBytesRead, dwStatus;
    ULONG dwCurrentBytesRead = 0;
    ULONG dwStatusLen = sizeof(dwStatus);
    BOOL bCancelled = FALSE;
    BOOL bTempfile = FALSE;
    BOOL bCab = FALSE;
    HINTERNET hOpen = NULL;
    HINTERNET hFile = NULL;
    HANDLE hOut = INVALID_HANDLE_VALUE;
    unsigned char lpBuffer[4096];
    PCWSTR lpszAgent = L"RApps/1.0";
    URL_COMPONENTS urlComponents;
    size_t urlLength;

    /* built the path for the download */
    p = wcsrchr(AppInfo->szUrlDownload, L'/');

    if (!p)
        goto end;

        if (wcscmp(AppInfo->szUrlDownload, APPLICATION_DATABASE_URL) == 0)
        {
            bCab = TRUE;
            if (!GetStorageDirectory(path, sizeof(path) / sizeof(path[0])))
                goto end;
        }
        else
        {
            if (FAILED(StringCbCopyW(path, sizeof(path),  SettingsInfo.szDownloadDir)))
                goto end;
        }


    if (GetFileAttributesW(path) == INVALID_FILE_ATTRIBUTES)
    {
        if (!CreateDirectoryW(path, NULL))
            goto end;
    }

    if (FAILED(StringCbCatW(path, sizeof(path), L"\\")))
        goto end;
    if (FAILED(StringCbCatW(path, sizeof(path), p + 1)))
        goto end;

    /* download it */
    bTempfile = TRUE;
    CDownloadDialog_Constructor(Dlg, &bCancelled, IID_PPV_ARG(IBindStatusCallback, &dl));

    if (dl == NULL)
        goto end;

    switch(SettingsInfo.Proxy)
    {
        case 0: /* preconfig */
            hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
            break;
        case 1: /* direct (no proxy) */
            hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
            break;
        case 2: /* use proxy */
            hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_PROXY, SettingsInfo.szProxyServer, SettingsInfo.szNoProxyFor, 0);
            break;
        default: /* preconfig */
            hOpen = InternetOpenW(lpszAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
            break;
    }

    if (!hOpen)
        goto end;

    hFile = InternetOpenUrlW(hOpen, AppInfo->szUrlDownload, NULL, 0, INTERNET_FLAG_PRAGMA_NOCACHE|INTERNET_FLAG_KEEP_CONNECTION, 0);
    if (!hFile)
        goto end;

    if (!HttpQueryInfoW(hFile, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwStatus, &dwStatusLen, NULL))
        goto end;

    if(dwStatus != HTTP_STATUS_OK)
    {
        WCHAR szMsgText[MAX_STR_LEN];

        if (!LoadStringW(hInst, IDS_UNABLE_TO_DOWNLOAD, szMsgText, sizeof(szMsgText) / sizeof(WCHAR)))
            goto end;

        MessageBoxW(hMainWnd, szMsgText, NULL, MB_OK | MB_ICONERROR);
        goto end;
    }

    dwStatusLen = sizeof(dwStatus);

    memset(&urlComponents, 0, sizeof(urlComponents));
    urlComponents.dwStructSize = sizeof(urlComponents);

    if(FAILED(StringCbLengthW(AppInfo->szUrlDownload, sizeof(AppInfo->szUrlDownload), &urlLength)))
        goto end;
    
    urlComponents.dwSchemeLength = urlLength*sizeof(WCHAR);
    urlComponents.lpszScheme = (PWSTR)malloc(urlComponents.dwSchemeLength);
    
    if(!InternetCrackUrlW(AppInfo->szUrlDownload, urlLength+1, ICU_DECODE | ICU_ESCAPE, &urlComponents))
        goto end;
    
    if(urlComponents.nScheme == INTERNET_SCHEME_HTTP || urlComponents.nScheme == INTERNET_SCHEME_HTTPS)
        HttpQueryInfo(hFile, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &dwContentLen, &dwStatus, 0);

    if(urlComponents.nScheme == INTERNET_SCHEME_FTP)
        dwContentLen = FtpGetFileSize(hFile, &dwStatus);

    free(urlComponents.lpszScheme);

    hOut = CreateFileW(path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);

    if (hOut == INVALID_HANDLE_VALUE)
        goto end;

    do
    {
        if (!InternetReadFile(hFile, lpBuffer, _countof(lpBuffer), &dwBytesRead)) goto end;
        if (!WriteFile(hOut, &lpBuffer[0], dwBytesRead, &dwBytesWritten, NULL)) goto end;
        dwCurrentBytesRead += dwBytesRead;
        dl->OnProgress(dwCurrentBytesRead, dwContentLen, 0, AppInfo->szUrlDownload);
    }
    while (dwBytesRead);

    CloseHandle(hOut);
    hOut = INVALID_HANDLE_VALUE;

    if (bCancelled)
        goto end;

    ShowWindow(Dlg, SW_HIDE);

    /* run it */
    if (!bCab)
        ShellExecuteW( NULL, L"open", path, NULL, NULL, SW_SHOWNORMAL );

end:
    if (hOut != INVALID_HANDLE_VALUE)
        CloseHandle(hOut);

    InternetCloseHandle(hFile);
    InternetCloseHandle(hOpen);

    if (bTempfile)
    {
        if (bCancelled || (SettingsInfo.bDelInstaller && !bCab))
            DeleteFileW(path);
    }

    EndDialog(Dlg, 0);

    return 0;
}
Example #18
0
File: http.c Project: bilboed/wine
static HRESULT HttpProtocol_start_downloading(Protocol *prot)
{
    HttpProtocol *This = ASYNCPROTOCOL_THIS(prot);
    LPWSTR content_type, content_length, ranges;
    DWORD len = sizeof(DWORD);
    DWORD status_code;
    BOOL res;
    HRESULT hres;

    static const WCHAR wszDefaultContentType[] =
        {'t','e','x','t','/','h','t','m','l',0};

    if(!This->http_negotiate) {
        WARN("Expected IHttpNegotiate pointer to be non-NULL\n");
        return S_OK;
    }

    res = HttpQueryInfoW(This->base.request, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
            &status_code, &len, NULL);
    if(res) {
        LPWSTR response_headers = query_http_info(This, HTTP_QUERY_RAW_HEADERS_CRLF);
        if(response_headers) {
            hres = IHttpNegotiate_OnResponse(This->http_negotiate, status_code, response_headers,
                    NULL, NULL);
            heap_free(response_headers);
            if (hres != S_OK) {
                WARN("IHttpNegotiate_OnResponse failed: %08x\n", hres);
                return S_OK;
            }
        }
    }else {
        WARN("HttpQueryInfo failed: %d\n", GetLastError());
    }

    ranges = query_http_info(This, HTTP_QUERY_ACCEPT_RANGES);
    if(ranges) {
        IInternetProtocolSink_ReportProgress(This->base.protocol_sink, BINDSTATUS_ACCEPTRANGES, NULL);
        heap_free(ranges);
    }

    content_type = query_http_info(This, HTTP_QUERY_CONTENT_TYPE);
    if(content_type) {
        /* remove the charset, if present */
        LPWSTR p = strchrW(content_type, ';');
        if (p) *p = '\0';

        IInternetProtocolSink_ReportProgress(This->base.protocol_sink,
                (This->base.bindf & BINDF_FROMURLMON)
                 ? BINDSTATUS_MIMETYPEAVAILABLE : BINDSTATUS_RAWMIMETYPE,
                 content_type);
        heap_free(content_type);
    }else {
        WARN("HttpQueryInfo failed: %d\n", GetLastError());
        IInternetProtocolSink_ReportProgress(This->base.protocol_sink,
                 (This->base.bindf & BINDF_FROMURLMON)
                  ? BINDSTATUS_MIMETYPEAVAILABLE : BINDSTATUS_RAWMIMETYPE,
                  wszDefaultContentType);
    }

    content_length = query_http_info(This, HTTP_QUERY_CONTENT_LENGTH);
    if(content_length) {
        This->base.content_length = atoiW(content_length);
        heap_free(content_length);
    }

    return S_OK;
}