Exemple #1
1
// POST request to URL
void WinHttpIO::post(HttpReq* req, const char* data, unsigned len)
{
    LOG_debug << "POST target URL: " << req->posturl << " chunked: " << req->chunked;

    if (req->binary)
    {
        LOG_debug << "[sending " << (data ? len : req->out->size()) << " bytes of raw data]";
    }
    else
    {
        LOG_debug << "Sending: " << *req->out;
    }

    WinHttpContext* httpctx;

    WCHAR szURL[8192];
    WCHAR szHost[256];
    URL_COMPONENTS urlComp = { sizeof urlComp };

    urlComp.lpszHostName = szHost;
    urlComp.dwHostNameLength = sizeof szHost / sizeof *szHost;
    urlComp.dwUrlPathLength = (DWORD)-1;
    urlComp.dwSchemeLength = (DWORD)-1;

    httpctx = new WinHttpContext;

    httpctx->httpio = this;
    httpctx->req = req;
    httpctx->gzip = false;

    req->httpiohandle = (void*)httpctx;

    if (MultiByteToWideChar(CP_UTF8, 0, req->posturl.c_str(), -1, szURL,
                            sizeof szURL / sizeof *szURL)
     && WinHttpCrackUrl(szURL, 0, 0, &urlComp))
    {
        if ((httpctx->hConnect = WinHttpConnect(hSession, szHost, urlComp.nPort, 0)))
        {
            httpctx->hRequest = WinHttpOpenRequest(httpctx->hConnect, L"POST",
                                                   urlComp.lpszUrlPath, NULL,
                                                   WINHTTP_NO_REFERER,
                                                   WINHTTP_DEFAULT_ACCEPT_TYPES,
                                                   (urlComp.nScheme == INTERNET_SCHEME_HTTPS)
                                                   ? WINHTTP_FLAG_SECURE
                                                   : 0);

            if (httpctx->hRequest)
            {
                if (proxyUsername.size())
                {
                    LOG_verbose << "Setting proxy credentials";

                    WinHttpSetCredentials(httpctx->hRequest, WINHTTP_AUTH_TARGET_PROXY,
                                          WINHTTP_AUTH_SCHEME_BASIC,
                                          (LPWSTR)proxyUsername.data(), (LPWSTR)proxyPassword.data(), NULL);
                }

                WinHttpSetTimeouts(httpctx->hRequest, 58000, 58000, 0, 0);

                WinHttpSetStatusCallback(httpctx->hRequest, asynccallback,
                                         WINHTTP_CALLBACK_FLAG_DATA_AVAILABLE
                                       | WINHTTP_CALLBACK_FLAG_READ_COMPLETE
                                       | WINHTTP_CALLBACK_FLAG_HEADERS_AVAILABLE
                                       | WINHTTP_CALLBACK_FLAG_REQUEST_ERROR
                                       | WINHTTP_CALLBACK_FLAG_SECURE_FAILURE
                                       | WINHTTP_CALLBACK_FLAG_SENDREQUEST_COMPLETE
                                       | WINHTTP_CALLBACK_FLAG_SEND_REQUEST
                                       | WINHTTP_CALLBACK_FLAG_WRITE_COMPLETE
                                       | WINHTTP_CALLBACK_FLAG_HANDLES,
                                         0);

                LPCWSTR pwszHeaders = req->type == REQ_JSON || !req->buf
                                    ? L"Content-Type: application/json\r\nAccept-Encoding: gzip"
                                    : L"Content-Type: application/octet-stream";

                // data is sent in HTTP_POST_CHUNK_SIZE instalments to ensure
                // semi-smooth UI progress info
                if (req->chunkedout.size())
                {
                    req->outbuf.append(req->chunkedout);
                    req->chunkedout.clear();
                }

                req->chunked = 0;

                httpctx->postlen = data ? len : req->out->size();
                httpctx->postdata = data ? data : req->out->data();

                if (urlComp.nPort == 80)
                {
                    LOG_verbose << "HTTP connection";

                    // HTTP connection: send a chunk of data immediately
                    httpctx->postpos = (httpctx->postlen < HTTP_POST_CHUNK_SIZE)
                                      ? httpctx->postlen
                                      : HTTP_POST_CHUNK_SIZE;
                }
                else
                {
                    LOG_verbose << "HTTPS connection";

                    // HTTPS connection: ignore certificate errors, send no data yet
                    DWORD flags = SECURITY_FLAG_IGNORE_CERT_CN_INVALID
                                | SECURITY_FLAG_IGNORE_CERT_DATE_INVALID
                                | SECURITY_FLAG_IGNORE_UNKNOWN_CA;

                    WinHttpSetOption(httpctx->hRequest, WINHTTP_OPTION_SECURITY_FLAGS, &flags, sizeof flags);

                    httpctx->postpos = 0;
                }

                if (WinHttpSendRequest(httpctx->hRequest, pwszHeaders,
                                       wcslen(pwszHeaders),
                                       (LPVOID)httpctx->postdata,
                                       httpctx->postpos,
                                       httpctx->postlen,
                                       (DWORD_PTR)httpctx))
                {
                    LOG_verbose << "Request sent";
                    req->status = REQ_INFLIGHT;
                    return;
                }

                LOG_err << "Error sending request: " << req->posturl << "  Code: " << GetLastError();
            }
            else
            {
                LOG_err << "Error opening request: " << req->posturl << "  Code: " << GetLastError();
            }
        }
        else
        {
            LOG_err << "Error connecting to " << req->posturl << "  Code: " << GetLastError();
            httpctx->hRequest = NULL;
        }
    }
    else
    {
        LOG_err << "Error parsing POST URL: " << req->posturl << "  Code: " << GetLastError();
        httpctx->hRequest = NULL;
        httpctx->hConnect = NULL;
    }

    LOG_err << "Request failed";
    req->status = REQ_FAILURE;
}
DWORD
InitializeGlobals(
    PCWSTR pwszServer
    )
{
    DWORD dwError = ERROR_SUCCESS;
    HINTERNET hSession = NULL;
    HINTERNET hConnect = NULL;

    hSession = WinHttpOpen(L"winhttp async sample/0.1",
                           WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
                           WINHTTP_NO_PROXY_NAME,
                           WINHTTP_NO_PROXY_BYPASS,
                           WINHTTP_FLAG_ASYNC);
    if (hSession == NULL) 
    {
        dwError = GetLastError();
        goto Exit;
    }

    if (WinHttpSetStatusCallback(hSession,
                                 (WINHTTP_STATUS_CALLBACK)AsyncCallback,
                                 WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS,
                                 0) == WINHTTP_INVALID_STATUS_CALLBACK) 
    {
        dwError = GetLastError();
        goto Exit;
    }

    hConnect = WinHttpConnect(hSession, 
                              pwszServer,
                              INTERNET_DEFAULT_HTTP_PORT,
                              0);
    if (hConnect == NULL) 
    {
        dwError = GetLastError();
        goto Exit;
    }

    g_hSession = hSession;
    hSession = NULL;
    g_hConnect = hConnect;
    hConnect = NULL;

Exit:

    if (hConnect != NULL)
    {
        WinHttpCloseHandle(hConnect);
        hConnect = NULL;
    }

    if (hSession != NULL)
    {
        WinHttpCloseHandle(hSession);
        hSession = NULL;
    }

    return dwError;
}
Exemple #3
0
//セッションを閉じる
//コネクションとリクエストも閉じる
//戻り値:エラーコード
DWORD CWinHTTPUtil::CloseSession()
{
	if( this->upThread != NULL ){
		::SetEvent(this->upStopEvent);
		// スレッド終了待ち
		if ( ::WaitForSingleObject(this->upThread, 15000) == WAIT_TIMEOUT ){
			::TerminateThread(this->upThread, 0xffffffff);
		}
		CloseHandle(this->upThread);
		this->upThread = NULL;
	}

	//コネクション系のクローズ
	if( this->request != NULL ){
		WinHttpSetStatusCallback( this->request, NULL, NULL, NULL );
		WinHttpCloseHandle(this->request);
		this->request = NULL;
	}
	if( this->connect != NULL ){
		WinHttpCloseHandle(this->connect);
		this->connect = NULL;
	}
	if( this->session != NULL ){
		WinHttpCloseHandle(this->session);
		this->session = NULL;
	}
	return NO_ERR;
}
HINTERNET WinHTTPSession::setup(const Request & request, LPCWSTR method) {
	
	platform::WideString wurl(request.url());
	
	URL_COMPONENTS url;
	ZeroMemory(&url, sizeof(url));
	url.dwStructSize = sizeof(url);
	url.dwSchemeLength = url.dwHostNameLength = url.dwUrlPathLength = DWORD(-1);
	if(WinHttpCrackUrl(wurl, 0, 0, &url) != TRUE) {
		throw new Response("Invalid URL: \"" + request.url() + "\"");
	}
	
	DWORD flags = 0;
	if(url.nScheme == INTERNET_SCHEME_HTTPS) {
		flags |= WINHTTP_FLAG_SECURE;
	} else if(url.nScheme != INTERNET_SCHEME_HTTP) {
		throw new Response("Unsupported protocol");
	}
	
	if(m_scheme != url.nScheme || m_port != url.nPort
	   || m_host.compare(0, m_host.length(), url.lpszHostName, url.dwHostNameLength) != 0) {
		if(m_connection) {
			WinHttpCloseHandle(m_connection);
		}
		m_scheme = url.nScheme;
		m_host.assign(url.lpszHostName, url.dwHostNameLength);
		m_port = url.nPort;
		m_connection = WinHttpConnect(m_session, m_host.c_str(), m_port, 0);
	}
	if(!m_connection) {
		throw new Response("Could not create connection object: " + errorString());
	}
	
	LPCWSTR resource = url.dwUrlPathLength ? url.lpszUrlPath : L"/";
	
	LPCWSTR accept[] = { L"*/*", NULL };
	
	HINTERNET wrequest = WinHttpOpenRequest(m_connection, method, resource, NULL,
	                                        WINHTTP_NO_REFERER, accept, flags);
	if(!wrequest) {
		throw new Response("Could not create request object: " + errorString());
	}
	
	if(request.followRedirects()) {
		WinHttpSetStatusCallback(wrequest, statusCallback, WINHTTP_CALLBACK_FLAG_REDIRECT, 0);
	} else {
		ULONG disable = WINHTTP_DISABLE_REDIRECTS;
		WinHttpSetOption(wrequest, WINHTTP_OPTION_DISABLE_FEATURE, &disable, sizeof(disable));
	}
	
	return wrequest;
}
Exemple #5
0
static void test_redirect( void )
{
    static const WCHAR codeweavers[] = {'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0};

    HANDLE ses, con, req;
    DWORD size, status;
    BOOL ret;
    struct info info, *context = &info;

    info.test  = redirect_test;
    info.count = sizeof(redirect_test) / sizeof(redirect_test[0]);
    info.index = 0;
    info.wait = NULL;

    ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 );
    ok(ses != NULL, "failed to open session %u\n", GetLastError());

    WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );

    ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
    ok(ret, "failed to set context value %u\n", GetLastError());

    setup_test( &info, winhttp_connect, __LINE__ );
    con = WinHttpConnect( ses, codeweavers, 0, 0 );
    ok(con != NULL, "failed to open a connection %u\n", GetLastError());

    setup_test( &info, winhttp_open_request, __LINE__ );
    req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
    ok(req != NULL, "failed to open a request %u\n", GetLastError());

    setup_test( &info, winhttp_send_request, __LINE__ );
    ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
    ok(ret, "failed to send request %u\n", GetLastError());

    setup_test( &info, winhttp_receive_response, __LINE__ );
    ret = WinHttpReceiveResponse( req, NULL );
    ok(ret, "failed to receive response %u\n", GetLastError());

    size = sizeof(status);
    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
    ok(ret, "failed unexpectedly %u\n", GetLastError());
    ok(status == 200, "request failed unexpectedly %u\n", status);

    setup_test( &info, winhttp_close_handle, __LINE__ );
    WinHttpCloseHandle( req );
    WinHttpCloseHandle( con );
    WinHttpCloseHandle( ses );
}
Exemple #6
0
void CALLBACK CWinHTTPUtil::StatusCallback (
		HINTERNET hInternet,
		DWORD_PTR dwContext,
		DWORD dwInternetStatus,
		LPVOID lpvStatusInformation,
		DWORD dwStatusInformationLength
		)
{
	CWinHTTPUtil* sys = (CWinHTTPUtil*)dwContext;

	switch(dwInternetStatus){
		case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE:
			//WinHttpSendRequest
			sys->StatusSendRequestComplete();
			break;
		case WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE:
			//WinHttpWriteData
			sys->StatusWriteComplete(*((DWORD *)lpvStatusInformation));
			break;
		case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE:
			//WinHttpReceiveResponse
			sys->StatusHeadersAvailable();
			break;
		case WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE:
			//WinHttpQueryDataAvailable
			sys->StatusDataAvailable(*((DWORD*)lpvStatusInformation));
			break;
		case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR:
			//エラー発生
			{
				WinHttpSetStatusCallback( sys->request, NULL, NULL, NULL );
				sys->errEndCode = ERR_NW_FALSE;
				SetEvent(sys->responseCompEvent);
			}
			break;
		default:
			break;
	}
	
}
Exemple #7
0
	void HTTPClient::sendMsg(HTTPMsg* pMsg){
		lwassert(pMsg);
		if ( !_isConnected ){
			connect();
		}
		if ( !_isConnected ){
			return;
		}
		
		HINTERNET hRequest = WinHttpOpenRequest( _hConnect, L"POST", pMsg->getObjName(),
			NULL, WINHTTP_NO_REFERER,
			WINHTTP_DEFAULT_ACCEPT_TYPES, 
			0 );
		pMsg->setHRequest(hRequest);

		//WinHttpSetOption(hRequest,
		//	WINHTTP_OPTION_CONTEXT_VALUE,
		//	pMsg,
		//	sizeof(pMsg));

		WinHttpSetStatusCallback(hRequest,
			requestCallback,
			WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS |
			WINHTTP_CALLBACK_FLAG_HANDLES,   // to listen to the HANDLE_CLOSING event
			0);

		DWORD size = pMsg->getBuff()->getSize();
		bool bResults = WinHttpSendRequest( hRequest,
			WINHTTP_NO_ADDITIONAL_HEADERS, 0,
			pMsg->getBuff()->getBuff(), size, 
			size, (DWORD_PTR)pMsg ) != 0;
		if ( bResults ){
			_msgs.push_back(pMsg);
		}else{
			delete pMsg;
		}
	}
Exemple #8
0
//リクエストを送る
//内部メモリバッファにDLする場合はファイル容量に要注意
//戻り値:エラーコード
DWORD CWinHTTPUtil::SendRequest( 
	LPCWSTR url,					//[IN] アクセスするURL
	NW_VERB_MODE verbMode,			//[IN] VERBの種類
	LPCWSTR addHttpHeader,			//[IN] Httpヘッダに追加するものあるなら指定
	LPCWSTR saveFilePath,			//[IN] DLファイル名、NULL時は内部メモリバッファにDL
	UPLOAD_DATA_LIST* upList		//[IN] サーバーに送信するデータ(PUT or POST)
	)
{
	if( url == NULL ){
		return ERR_INVALID_ARG;
	}
	if( this->session == NULL ){
		return ERR_NW_NO_SESSION;
	}
	//リクエストクローズ
	if( this->request != NULL ){
		WinHttpSetStatusCallback( this->request, NULL, NULL, NULL );
		WinHttpCloseHandle(this->request);
		this->request = NULL;
	}
	ClearUpList();
	for( size_t i=0; i<this->dlBuffList.size(); i++ ){
		SAFE_DELETE(this->dlBuffList[i]);
	}
	this->dlBuffList.clear();

	//URLの分解
	URL_COMPONENTS stURL;
	ZeroMemory(&stURL, sizeof(URL_COMPONENTS));
	stURL.dwStructSize = sizeof(URL_COMPONENTS);

	stURL.dwSchemeLength    = -1;
	stURL.dwHostNameLength  = -1;
	stURL.dwUrlPathLength   = -1;
	stURL.dwExtraInfoLength = -1;

	if( WinHttpCrackUrl( url, (DWORD)wcslen(url), 0, &stURL) == NULL ){
		return ERR_FALSE;
	}
	if( stURL.dwHostNameLength <= 0 ){
		return ERR_FALSE;
	}

	wstring host = L"";
	host.insert(0,stURL.lpszHostName, stURL.dwHostNameLength );
	host += L"\0";

	if( CompareNoCase(host, stURL.lpszHostName) != 0 || this->lastPort != stURL.nPort){
		//前回と違うコネクションなのでやりなおし
		if( this->connect != NULL ){
			WinHttpCloseHandle(this->connect);
			this->connect = NULL;
		}
	}

	//コネクションオープン
	if( this->connect == NULL ){
		this->connect = WinHttpConnect( this->session, host.c_str(), stURL.nPort, 0 );
		if( this->connect == NULL ){
			return ERR_NW_OPEN_CONNECT;
		}
	}

	//Verbの設定
	wstring verb = L"GET";
	if( verbMode == NW_VERB_GET ){
		verb = L"GET";
	}else if( verbMode == NW_VERB_POST ){
		verb = L"POST";
	}else if( verbMode == NW_VERB_PUT ){
		verb = L"PUT";
	}

	wstring sendUrl = L"";
	sendUrl.insert(0, stURL.lpszUrlPath, stURL.dwUrlPathLength+stURL.dwExtraInfoLength);
	sendUrl += L"\0";

	//リクエストオープン
	if( stURL.nPort == INTERNET_DEFAULT_HTTPS_PORT ){
		this->request = WinHttpOpenRequest( this->connect, verb.c_str(), sendUrl.c_str(),
			NULL, WINHTTP_NO_REFERER, 
			WINHTTP_DEFAULT_ACCEPT_TYPES, 
			WINHTTP_FLAG_SECURE);
	}else{
		this->request = WinHttpOpenRequest( this->connect, verb.c_str(), sendUrl.c_str(),
			NULL, WINHTTP_NO_REFERER, 
			WINHTTP_DEFAULT_ACCEPT_TYPES, 
			0 );
	}
	if( this->request == NULL ){
		return ERR_NW_OPEN_REQUEST;
	}

	if( this->useProxy == TRUE ){
		//ProxyのIDとパスワードがあったらセット
		if( this->proxyID.size() > 0 || this->proxyPWD.size() > 0 ){
			if( WinHttpSetCredentials( this->request,
				WINHTTP_AUTH_TARGET_PROXY,
				WINHTTP_AUTH_SCHEME_BASIC,
				this->proxyID.c_str(),
				this->proxyPWD.c_str(),
				NULL )  == FALSE ){
				return ERR_NW_PROXY_LOGIN;
			}
		}
	}

	//HTTPヘッダを設定
	if( addHttpHeader != NULL ){
		WinHttpAddRequestHeaders( this->request, addHttpHeader, -1, WINHTTP_ADDREQ_FLAG_ADD );
	}

	//コールバック設定
	WinHttpSetStatusCallback(this->request, StatusCallback, WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS, NULL );

	//アップロードデータのコピー
	this->totalUpSize = 0;
	if( upList != NULL ){
		for( DWORD i=0; i<upList->listCount; i++ ){
			UPLOAD_DATA* item = new UPLOAD_DATA;
			item->filePathFlag = upList->list[i].filePathFlag;
			item->buffSize = upList->list[i].buffSize;
			if( item->buffSize > 0 ){
				item->buff = new BYTE[item->buffSize];
				memcpy(item->buff, upList->list[i].buff, item->buffSize);
			}
			upDataList.push_back(item);

			if( item->filePathFlag == TRUE ){
				HANDLE file = CreateFileW( (WCHAR*)item->buff, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
				if( file == INVALID_HANDLE_VALUE ){
					//ファイルにアクセスできないのでエラー
					return ERR_NW_OPEN_FILE;
				}
				DWORD HSize=0;
				DWORD LSize=0;
				LSize = GetFileSize(file, &HSize);
				CloseHandle(file);
				if( HSize > 0 ){
					//DWORD以上は未サポート
					return ERR_SIZE;
				}
				this->totalUpSize += LSize;
			}else{
				this->totalUpSize  += item->buffSize;
			}
		}
	}

	this->lastHost = host;
	this->lastPort = stURL.nPort;
	if( saveFilePath != NULL ){
		this->saveFilePath = saveFilePath;
	}else{
		this->saveFilePath = L"";
	}

	ResetEvent(this->upStopEvent);
	ResetEvent(this->responseCompEvent);
	this->errEndCode = NO_ERR;
	if( WinHttpSendRequest( this->request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, totalUpSize, (DWORD_PTR)this) == FALSE ){
		return ERR_NW_SEND_REQUEST;
	}
	if( this->asyncMode == FALSE ){
		//同期なので完了するまで待つ
		WaitForSingleObject(this->responseCompEvent, INFINITE);
		return this->errEndCode;
	}
	return NO_ERR;
}
DWORD
ProxyResolver::GetProxyForUrlEx(
    _In_ HINTERNET hSession,
    _In_z_ PCWSTR pwszUrl,
    _In_ WINHTTP_AUTOPROXY_OPTIONS *pAutoProxyOptions
)
/*++

Routine Description:

    Retrieves the proxy data with the specified option using WinhttpGetProxyForUrlEx.

Arguments:

    hSession - The WinHttp session to use for the proxy resolution.

    pwszUrl - The URL to get the proxy for.

    pAutoProxyOptions - Specifies the auto-proxy options to use.

Return Value:

    WIN32 Error codes.

--*/
{
    DWORD dwError = ERROR_SUCCESS;
    HINTERNET hResolver = NULL;
    WINHTTP_STATUS_CALLBACK wscCallback = NULL;

    //
    // Create proxy resolver handle. It's best to close the handle during call back.
    //

    dwError = s_pfnWinhttpCreateProxyResolver(hSession,
                                              &hResolver);
    if (dwError != ERROR_SUCCESS)
    {
        goto quit;
    }

    //
    // Sets up a callback function that WinHTTP can call as proxy results are resolved.
    //

    wscCallback = WinHttpSetStatusCallback(hResolver,
                                           GetProxyCallBack,
                                           WINHTTP_CALLBACK_FLAG_REQUEST_ERROR | WINHTTP_CALLBACK_FLAG_GETPROXYFORURL_COMPLETE,
                                           0);
    if(wscCallback == WINHTTP_INVALID_STATUS_CALLBACK)
    {
        dwError = GetLastError();
        goto quit;
    }

    //
    // The extended API works in asynchronous mode, therefore wait until the
    // results are set in the call back function.
    //

    dwError = s_pfnWinhttpGetProxyForUrlEx(hResolver,
                                           pwszUrl,
                                           pAutoProxyOptions,
                                           (DWORD_PTR)this);
    if (dwError != ERROR_IO_PENDING)
    {
        goto quit;
    }

    //
    // The resolver handle will get closed in the callback and cannot be used any longer.
    //

    hResolver = NULL;

    dwError = WaitForSingleObjectEx(m_hEvent,
                                    INFINITE,
                                    FALSE);
    if (dwError != WAIT_OBJECT_0)
    {
        dwError = GetLastError();
        goto quit;
    }

    dwError = m_dwError;

quit:

    if (hResolver != NULL)
    {
        WinHttpCloseHandle(hResolver);
        hResolver = NULL;
    }

    return dwError;
}
Exemple #10
0
static int winhttp_connect(
	winhttp_subtransport *t)
{
	wchar_t *wide_host;
	int32_t port;
	wchar_t *wide_ua;
	git_buf ua = GIT_BUF_INIT;
	int error = -1;
	int default_timeout = TIMEOUT_INFINITE;
	int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT;

	t->session = NULL;
	t->connection = NULL;

	/* Prepare port */
	if (git__strtol32(&port, t->connection_data.port, NULL, 10) < 0)
		return -1;

	/* Prepare host */
	if (git__utf8_to_16_alloc(&wide_host, t->connection_data.host) < 0) {
		giterr_set(GITERR_OS, "unable to convert host to wide characters");
		return -1;
	}

	if ((error = user_agent(&ua)) < 0) {
		git__free(wide_host);
		return error;
	}

	if (git__utf8_to_16_alloc(&wide_ua, git_buf_cstr(&ua)) < 0) {
		giterr_set(GITERR_OS, "unable to convert host to wide characters");
		git__free(wide_host);
		git_buf_free(&ua);
		return -1;
	}

	git_buf_free(&ua);

	/* Establish session */
	t->session = WinHttpOpen(
		wide_ua,
		WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
		WINHTTP_NO_PROXY_NAME,
		WINHTTP_NO_PROXY_BYPASS,
		0);

	if (!t->session) {
		giterr_set(GITERR_OS, "failed to init WinHTTP");
		goto on_error;
	}

	if (!WinHttpSetTimeouts(t->session, default_timeout, default_connect_timeout, default_timeout, default_timeout)) {
		giterr_set(GITERR_OS, "failed to set timeouts for WinHTTP");
		goto on_error;
	}

	
	/* Establish connection */
	t->connection = WinHttpConnect(
		t->session,
		wide_host,
		(INTERNET_PORT) port,
		0);

	if (!t->connection) {
		giterr_set(GITERR_OS, "failed to connect to host");
		goto on_error;
	}

	if (WinHttpSetStatusCallback(t->connection, winhttp_status, WINHTTP_CALLBACK_FLAG_SECURE_FAILURE, 0) == WINHTTP_INVALID_STATUS_CALLBACK) {
		giterr_set(GITERR_OS, "failed to set status callback");
		goto on_error;
	}

	error = 0;

on_error:
	if (error < 0)
		winhttp_close_connection(t);

	git__free(wide_host);
	git__free(wide_ua);

	return error;
}
Exemple #11
0
static void test_async( void )
{
    HANDLE ses, con, req;
    DWORD size, status;
    BOOL ret;
    struct info info, *context = &info;
    char buffer[1024];

    info.test  = async_test;
    info.count = sizeof(async_test) / sizeof(async_test[0]);
    info.index = 0;
    info.wait = CreateEventW( NULL, FALSE, FALSE, NULL );

    ses = WinHttpOpen( user_agent, 0, NULL, NULL, WINHTTP_FLAG_ASYNC );
    ok(ses != NULL, "failed to open session %u\n", GetLastError());

    WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );

    ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
    ok(ret, "failed to set context value %u\n", GetLastError());

    setup_test( &info, winhttp_connect, __LINE__ );
    con = WinHttpConnect( ses, test_winehq, 0, 0 );
    ok(con != NULL, "failed to open a connection %u\n", GetLastError());

    setup_test( &info, winhttp_open_request, __LINE__ );
    req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
    ok(req != NULL, "failed to open a request %u\n", GetLastError());

    setup_test( &info, winhttp_send_request, __LINE__ );
    ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
    ok(ret, "failed to send request %u\n", GetLastError());

    WaitForSingleObject( info.wait, INFINITE );

    setup_test( &info, winhttp_receive_response, __LINE__ );
    ret = WinHttpReceiveResponse( req, NULL );
    ok(ret, "failed to receive response %u\n", GetLastError());

    WaitForSingleObject( info.wait, INFINITE );

    size = sizeof(status);
    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
    ok(ret, "failed unexpectedly %u\n", GetLastError());
    ok(status == 200, "request failed unexpectedly %u\n", status);

    setup_test( &info, winhttp_query_data, __LINE__ );
    ret = WinHttpQueryDataAvailable( req, NULL );
    ok(ret, "failed to query data available %u\n", GetLastError());

    WaitForSingleObject( info.wait, INFINITE );

    setup_test( &info, winhttp_read_data, __LINE__ );
    ret = WinHttpReadData( req, buffer, sizeof(buffer), NULL );
    ok(ret, "failed to query data available %u\n", GetLastError());

    WaitForSingleObject( info.wait, INFINITE );

    setup_test( &info, winhttp_close_handle, __LINE__ );
    WinHttpCloseHandle( req );
    WinHttpCloseHandle( con );
    WinHttpCloseHandle( ses );

    WaitForSingleObject( info.wait, INFINITE );
    CloseHandle( info.wait );
}
Exemple #12
0
static void test_connection_cache( void )
{
    HANDLE ses, con, req;
    DWORD size, status;
    BOOL ret;
    struct info info, *context = &info;

    info.test  = cache_test;
    info.count = sizeof(cache_test) / sizeof(cache_test[0]);
    info.index = 0;
    info.wait = NULL;

    ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 );
    ok(ses != NULL, "failed to open session %u\n", GetLastError());

    WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );

    ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
    ok(ret, "failed to set context value %u\n", GetLastError());

    setup_test( &info, winhttp_connect, __LINE__ );
    con = WinHttpConnect( ses, test_winehq, 0, 0 );
    ok(con != NULL, "failed to open a connection %u\n", GetLastError());

    setup_test( &info, winhttp_open_request, __LINE__ );
    req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
    ok(req != NULL, "failed to open a request %u\n", GetLastError());

    setup_test( &info, winhttp_send_request, __LINE__ );
    ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
    ok(ret, "failed to send request %u\n", GetLastError());

    setup_test( &info, winhttp_receive_response, __LINE__ );
    ret = WinHttpReceiveResponse( req, NULL );
    ok(ret, "failed to receive response %u\n", GetLastError());

    size = sizeof(status);
    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
    ok(ret, "failed unexpectedly %u\n", GetLastError());
    ok(status == 200, "request failed unexpectedly %u\n", status);

    setup_test( &info, winhttp_close_handle, __LINE__ );
    WinHttpCloseHandle( req );

    setup_test( &info, winhttp_open_request, __LINE__ );
    req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
    ok(req != NULL, "failed to open a request %u\n", GetLastError());

    ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
    ok(ret, "failed to set context value %u\n", GetLastError());

    setup_test( &info, winhttp_send_request, __LINE__ );
    ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
    ok(ret, "failed to send request %u\n", GetLastError());

    setup_test( &info, winhttp_receive_response, __LINE__ );
    ret = WinHttpReceiveResponse( req, NULL );
    ok(ret, "failed to receive response %u\n", GetLastError());

    size = sizeof(status);
    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
    ok(ret, "failed unexpectedly %u\n", GetLastError());
    ok(status == 200, "request failed unexpectedly %u\n", status);

    setup_test( &info, winhttp_close_handle, __LINE__ );
    WinHttpCloseHandle( req );

    setup_test( &info, winhttp_close_handle, __LINE__ );
    WinHttpCloseHandle( req );
    WinHttpCloseHandle( con );
    WinHttpCloseHandle( ses );

    Sleep(2000); /* make sure connection is evicted from cache */

    info.index = 0;

    ses = WinHttpOpen( user_agent, 0, NULL, NULL, 0 );
    ok(ses != NULL, "failed to open session %u\n", GetLastError());

    WinHttpSetStatusCallback( ses, check_notification, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0 );

    ret = WinHttpSetOption( ses, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
    ok(ret, "failed to set context value %u\n", GetLastError());

    setup_test( &info, winhttp_connect, __LINE__ );
    con = WinHttpConnect( ses, test_winehq, 0, 0 );
    ok(con != NULL, "failed to open a connection %u\n", GetLastError());

    setup_test( &info, winhttp_open_request, __LINE__ );
    req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
    ok(req != NULL, "failed to open a request %u\n", GetLastError());

    ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
    ok(ret, "failed to set context value %u\n", GetLastError());

    setup_test( &info, winhttp_send_request, __LINE__ );
    ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
    ok(ret, "failed to send request %u\n", GetLastError());

    setup_test( &info, winhttp_receive_response, __LINE__ );
    ret = WinHttpReceiveResponse( req, NULL );
    ok(ret, "failed to receive response %u\n", GetLastError());

    size = sizeof(status);
    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
    ok(ret, "failed unexpectedly %u\n", GetLastError());
    ok(status == 200, "request failed unexpectedly %u\n", status);

    setup_test( &info, winhttp_close_handle, __LINE__ );
    WinHttpCloseHandle( req );

    setup_test( &info, winhttp_open_request, __LINE__ );
    req = WinHttpOpenRequest( con, NULL, NULL, NULL, NULL, NULL, 0 );
    ok(req != NULL, "failed to open a request %u\n", GetLastError());

    ret = WinHttpSetOption( req, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(struct info *) );
    ok(ret, "failed to set context value %u\n", GetLastError());

    setup_test( &info, winhttp_send_request, __LINE__ );
    ret = WinHttpSendRequest( req, NULL, 0, NULL, 0, 0, 0 );
    ok(ret, "failed to send request %u\n", GetLastError());

    setup_test( &info, winhttp_receive_response, __LINE__ );
    ret = WinHttpReceiveResponse( req, NULL );
    ok(ret, "failed to receive response %u\n", GetLastError());

    size = sizeof(status);
    ret = WinHttpQueryHeaders( req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL );
    ok(ret, "failed unexpectedly %u\n", GetLastError());
    ok(status == 200, "request failed unexpectedly %u\n", status);

    setup_test( &info, winhttp_close_handle, __LINE__ );
    WinHttpCloseHandle( req );
    WinHttpCloseHandle( con );
    WinHttpCloseHandle( ses );

    Sleep(2000); /* make sure connection is evicted from cache */
}
Exemple #13
0
UINT CWinHTTPUtil::UploadThread(LPVOID pParam)
{
	if( pParam == NULL ){
		return 0;
	}
	CWinHTTPUtil* sys = (CWinHTTPUtil*)pParam;

	HANDLE eventArray[2];
	eventArray[0] = sys->upStopEvent;
	eventArray[1] = sys->writeCompEvent;

	SetEvent(sys->writeCompEvent);
	for( size_t i=0; i<sys->upDataList.size(); i++ ){
		UPLOAD_DATA* data = sys->upDataList[i];
		if( data->filePathFlag == FALSE ){
			DWORD res = WaitForMultipleObjects(2, eventArray, FALSE, INFINITE);
			if( res == WAIT_OBJECT_0 ){
				//STOP
				break;
			}else if( res == WAIT_OBJECT_0+1 ){
				WinHttpWriteData( sys->request, data->buff, data->buffSize, NULL );
			}
		}else{
			HANDLE file;
			file = CreateFile( (WCHAR*)data->buff, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
			if( file == INVALID_HANDLE_VALUE ){
				sys->errEndCode = ERR_NW_FILE_OPEN;
				WinHttpSetStatusCallback( sys->request, NULL, NULL, NULL );
				SetEvent(sys->responseCompEvent);
				return 0;
			}
			DWORD readSize = 0;
			DWORD readBuffSize = 0;
			BYTE buff[SEND_BUFF_SIZE];
			DWORD fileSize = GetFileSize(file, NULL);
			while( readSize < fileSize ){
				DWORD res = WaitForMultipleObjects(2, eventArray, FALSE, INFINITE);
				if( res == WAIT_OBJECT_0 ){
					//STOP
					break;
				}else if( res == WAIT_OBJECT_0+1 ){
					DWORD buffSize = 0;
					if( SEND_BUFF_SIZE+readSize < fileSize ){
						buffSize = SEND_BUFF_SIZE;
					}else{
						buffSize = fileSize - readSize;
					}
					if( ReadFile(file, buff, SEND_BUFF_SIZE, &readBuffSize, NULL ) == FALSE ){
						sys->errEndCode = ERR_NW_FILE_OPEN;
						WinHttpSetStatusCallback( sys->request, NULL, NULL, NULL );
						SetEvent(sys->responseCompEvent);
						return 0;
					}else{
						DWORD retryCount = 0;
						while( WinHttpWriteData( sys->request, buff, readBuffSize, NULL ) == FALSE ){
							Sleep(200);
							if( retryCount > 100 ){
								sys->errEndCode = ERR_NW_FALSE;
								WinHttpSetStatusCallback( sys->request, NULL, NULL, NULL );
								SetEvent(sys->responseCompEvent);
								return 0;
							}
							retryCount++;
						}
					}

					readSize+=buffSize;
				}
			}
			CloseHandle(file);
		}
	}
	WinHttpReceiveResponse(sys->request, NULL);

	sys->ClearUpList();
	return 0;
}
Exemple #14
0
static int winhttp_connect(
	winhttp_subtransport *t)
{
	wchar_t *wide_host;
	int32_t port;
	wchar_t *wide_ua;
	git_buf ua = GIT_BUF_INIT;
	int error = -1;
	int default_timeout = TIMEOUT_INFINITE;
	int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT;
	DWORD protocols =
		WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 |
		WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 |
		WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;

	t->session = NULL;
	t->connection = NULL;

	/* Prepare port */
	if (git__strtol32(&port, t->connection_data.port, NULL, 10) < 0)
		return -1;

	/* Prepare host */
	if (git__utf8_to_16_alloc(&wide_host, t->connection_data.host) < 0) {
		giterr_set(GITERR_OS, "unable to convert host to wide characters");
		return -1;
	}


	if ((error = git_http__user_agent(&ua)) < 0) {
		git__free(wide_host);
		return error;
	}

	if (git__utf8_to_16_alloc(&wide_ua, git_buf_cstr(&ua)) < 0) {
		giterr_set(GITERR_OS, "unable to convert host to wide characters");
		git__free(wide_host);
		git_buf_free(&ua);
		return -1;
	}

	git_buf_free(&ua);

	/* Establish session */
	t->session = WinHttpOpen(
		wide_ua,
		WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
		WINHTTP_NO_PROXY_NAME,
		WINHTTP_NO_PROXY_BYPASS,
		0);

	if (!t->session) {
		giterr_set(GITERR_OS, "failed to init WinHTTP");
		goto on_error;
	}

	/*
	 * Do a best-effort attempt to enable TLS 1.2 but allow this to
	 * fail; if TLS 1.2 support is not available for some reason,
	 * ignore the failure (it will keep the default protocols).
	 */
	WinHttpSetOption(t->session,
		WINHTTP_OPTION_SECURE_PROTOCOLS,
		&protocols,
		sizeof(protocols));

	if (!WinHttpSetTimeouts(t->session, default_timeout, default_connect_timeout, default_timeout, default_timeout)) {
		giterr_set(GITERR_OS, "failed to set timeouts for WinHTTP");
		goto on_error;
	}


	/* Establish connection */
	t->connection = WinHttpConnect(
		t->session,
		wide_host,
		(INTERNET_PORT) port,
		0);

	if (!t->connection) {
		giterr_set(GITERR_OS, "failed to connect to host");
		goto on_error;
	}

	if (WinHttpSetStatusCallback(t->connection, winhttp_status, WINHTTP_CALLBACK_FLAG_SECURE_FAILURE, 0) == WINHTTP_INVALID_STATUS_CALLBACK) {
		giterr_set(GITERR_OS, "failed to set status callback");
		goto on_error;
	}

	error = 0;

on_error:
	if (error < 0)
		winhttp_close_connection(t);

	git__free(wide_host);
	git__free(wide_ua);

	return error;
}
Exemple #15
0
// Set URL
bool SoffidEssoManager::SaveURLServer (const char* url)
{
	URL_COMPONENTS urlComp;		// Initialize the URL_COMPONENTS structure.

	// Set required component lengths to non-zero so that they are cracked.
	ZeroMemory(&urlComp, sizeof(urlComp));
	urlComp.dwStructSize = sizeof(urlComp);
	WCHAR szScheme[15];
	urlComp.lpszScheme = szScheme;
	urlComp.dwSchemeLength = 14;
	WCHAR szHostName[256];
	urlComp.lpszHostName = szHostName;
	urlComp.dwHostNameLength = 255;
	WCHAR szPath[5096];
	urlComp.lpszUrlPath = szPath;
	urlComp.dwUrlPathLength = 4095;

	int strLen = mbstowcs(NULL, url, strlen(url) + 1);
	wchar_t* wUrl = (wchar_t*) malloc(strLen * sizeof(wchar_t));
	mbstowcs(wUrl, url, strlen(url) + 1);

	// Use WinHttpOpen to obtain a session handle.
	HINTERNET hSession = WinHttpOpen(SoffidEssoManager::DEF_CON_AGENT.c_str(),
			WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME,
			WINHTTP_NO_PROXY_BYPASS, 0);

	// Specify an HTTP server.
	if (hSession)
	{
		if (!WinHttpCrackUrl(wUrl, wcslen(wUrl), 0, &urlComp))
		{
			MessageBox(NULL, Utils::LoadResourcesString(8).c_str(),
					Utils::LoadResourcesString(1001).c_str(),
					MB_OK | MB_ICONEXCLAMATION);
			return false;
		}
		WinHttpSetStatusCallback(hSession, asyncCallback,
				WINHTTP_CALLBACK_FLAG_SECURE_FAILURE, 0);
	}
	else
		return false;

	// Obtener la lista de host
	size_t size;
	if (debug)
		log("Connecting to https://%ls:%d/cert\n", szHostName, urlComp.nPort);

	LPCSTR cert = readURL(hSession, szHostName, urlComp.nPort, L"/cert", true, &size);

	// Check error obtain certificate
	if (cert == NULL)
	{
		log("Error getting certificate");
		return FALSE;
	}

	std::string fileName = getMazingerDir();
	fileName += SoffidEssoManager::DEF_CERTIFICATE_NAME;

	FILE *f = fopen(fileName.c_str(), "wb");

	if (f == NULL)
	{
		log("Error generating file %s", fileName.c_str());
		return FALSE;
	}

	else
	{
		fwrite(cert, size, 1, f);
		fclose(f);
	}

	// Write certificate
	SeyconCommon::writeProperty("CertificateFile", fileName.c_str());

	// Write ESSO Server
	SeyconCommon::writeProperty("SSOServer", MZNC_wstrtostr(szHostName).c_str());

	char szPort[100];
	sprintf(szPort, "%d", urlComp.nPort);

	// Write server prot
	SeyconCommon::writeProperty("seycon.https.port", szPort);

	return true;
}
Exemple #16
0
static INT_PTR CALLBACK Window_UpdateCheckDlg(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
	const wchar_t* kValueNextVersion[2] = {UPDATE_RELEASE, UPDATE_BETA};
	const char* kVersionType[2] = {"Release", "Beta"};
	UpdateData* data;
	int child_id;
//	int child_notify;
	
	switch(uMsg) {
	case WM_INITDIALOG:{
		wchar_t szHost[256];
		URL_COMPONENTS urlComp = {sizeof(urlComp)};
		urlComp.lpszHostName = szHost;
		urlComp.dwHostNameLength = sizeof(szHost)/sizeof(szHost[0]);
		urlComp.dwUrlPathLength = 1;
		urlComp.dwSchemeLength = 1;
		
		if(lParam != UPDATE_SHOW) // code in WM_WINDOWPOSCHANGING isn't enough...
			SetWindowLongPtr(hDlg, GWL_EXSTYLE, WS_EX_NOACTIVATE);
		
		data = calloc(1, sizeof(UpdateData));
		if(!data)
			goto error;
		data->ref_count = 2;
		data->type = lParam;
		data->update_window = hDlg;
		data->status_text = GetDlgItem(hDlg, IDC_STATUS);
		data->icon_update = LoadImage(g_instance, MAKEINTRESOURCE(IDI_UPDATE), IMAGE_ICON, 0,0, LR_DEFAULTSIZE);
		SendMessage(hDlg, WM_SETICON, ICON_BIG, (LPARAM)data->icon_update);
		SendMessage(hDlg, WM_SETICON, ICON_SMALL, (LPARAM)data->icon_update);
		data->icon_update_small = LoadImage(g_instance, MAKEINTRESOURCE(IDI_UPDATE_S), IMAGE_ICON, 0,0, LR_DEFAULTSIZE);
		data->next_version[0] = api.GetInt(NULL, kValueNextVersion[0], 1);
		#if VER_IsReleaseOrHigher() // release build, opt-in beta check
		data->next_version[1] = api.GetInt(NULL, kValueNextVersion[1], 0);
		#else // non-release build, force beta check
		data->next_version[1] = 1;
		#endif
		SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)data);
		
		data->session = WinHttpOpen(L"T-Clock/" L(VER_SHORT_DOTS), WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, WINHTTP_FLAG_ASYNC);
		if(!data->session)
			goto error;
		WinHttpSetTimeouts(data->session, 30000, 10000, 30000, 30000);
		WinHttpSetStatusCallback(data->session, HttpProgress, WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS, 0);
		WinHttpCrackUrl(kUpdateURL, 0, 0, &urlComp);
		data->connection = WinHttpConnect(data->session, urlComp.lpszHostName, urlComp.nPort, 0);
		if(!data->connection)
			goto error;
		data->request = WinHttpOpenRequest(data->connection, L"GET", urlComp.lpszUrlPath, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, (urlComp.nScheme==INTERNET_SCHEME_HTTPS?WINHTTP_FLAG_SECURE:0));
		if(!data->request)
			goto error;
		WinHttpSendRequest(data->request, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, (DWORD_PTR)data);
		return 1;
		error:
		SendMessage(hDlg, WM_DOWNLOAD_RESULT, 1, 0);
		UpdateCheck_Free(data); // frees 2nd reference (callback)
		if(lParam != UPDATE_SHOW)
			EndDialog(hDlg, IDCANCEL);
		return 1;}
	case WM_WINDOWPOSCHANGING:{
		WINDOWPOS* wndpos = (WINDOWPOS*)lParam;
		data = (UpdateData*)GetWindowLongPtr(hDlg,DWLP_USER);
		if(data && data->type != UPDATE_SHOW) {
			wndpos->flags &= ~SWP_SHOWWINDOW;
			wndpos->flags |= SWP_NOACTIVATE|SWP_NOZORDER;
		}
		return 1;}
	case WM_WINDOWPOSCHANGED:
		return 1;
	case WM_DESTROY:
		data = (UpdateData*)GetWindowLongPtr(hDlg,DWLP_USER);
		DestroyIcon(data->icon_update_small);
		DestroyIcon(data->icon_update);
		UpdateCheck_Free(data);
		return 1;
	case WMBC_INITDIALOG:
		data = (UpdateData*)GetWindowLongPtr(hDlg,DWLP_USER);
		update_notify_data_.button[0].icon = data->icon_update_small;
		// update check
		update_notify_data_.check[0].state = 0;
		if(data->next_version[0])
			update_notify_data_.check[0].state |= BST_CHECKED;
		// beta check
		update_notify_data_.check[1].state = BST_MBC_AUTODISABLE;
		if(data->next_version[1])
			update_notify_data_.check[1].state |= BST_CHECKED;
		#if !VER_IsReleaseOrHigher() // non-release build, forced beta check
		update_notify_data_.check[1].state &= ~BST_MBC_AUTODISABLE;
		update_notify_data_.check[1].style = WS_DISABLED;
		#endif
		SetWindowLongPtr(hDlg, DWLP_MSGRESULT, (LONG_PTR)&update_notify_data_);
		return 1;
	case WMBC_CHECKS:
		data = (UpdateData*)GetWindowLongPtr(hDlg,DWLP_USER);
		if(!data->next_version[0] != !(wParam&1)) {
			data->next_version[0] = (wParam&1);
			api.SetInt(NULL, kValueNextVersion[0], data->next_version[0]);
		}
		if(!data->next_version[1] != !(wParam&2)) {
			data->next_version[1] = (wParam&2 ? 1 : 0);
			api.SetInt(NULL, kValueNextVersion[1], data->next_version[1]);
		}
		return 1;
	case WM_DOWNLOAD_RESULT:
		data = (UpdateData*)GetWindowLongPtr(hDlg,DWLP_USER);
		if(wParam == 0) {
			int idx = 0;
			char* pos;
			unsigned version[2];
			unsigned version_next[2];
			const char* version_str[2] = {0};
			char* version_text[2];
			
			// parse version data
			pos = data->buffer;
			for(;;) {
				if(!version_str[1]) {
					version_text[0] = pos;
					pos = strchr(version_text[0], '\n');
					if(!pos || pos-version_text[0] > 21)
						break;
					*pos++ = '\0';
					version_text[1] = strchr(version_text[0], '|');
					if(!version_text[1])
						break;
					*version_text[1]++ = '\0';
					for(idx=0; idx<2; ++idx) {
						if(!version_str[0]) {
							// revision
							version_next[idx] = data->next_version[idx];
							if(version_next[idx] && version_next[idx] < VER_REVISION)
								version_next[idx] = VER_REVISION;
							version[idx] = atoi(version_text[idx]);
							if(version[idx] <= version_next[idx])
								version_next[idx] = 0;
						} else {
							// version string
							version_str[idx] = version_text[idx];
						}
					}
					if(!version_str[0]) {
						version_str[0] = (char*)1;
						continue;
					}
				}
				// version description
				version_text[0] = strchr(pos, '|');
				if(!version_text[0])
					break;
				++version_text[0];
				version_text[1] = strchr(version_text[0], '|');
				if(!version_text[1])
					break;
				*version_text[1]++ = '\0';
				idx = -1;
				break;
			}
			if(idx != -1) {
				SendMessage(hDlg, WM_DOWNLOAD_RESULT, 2, 0);
				return 1;
			}
			// show version
			if(data->type == UPDATE_SHOW) {
				version_next[0] = version[0];
				version_next[1] = version[1];
			}
			if(version_next[0] || version_next[1]) {
				if(data->type != UPDATE_SILENT) {
					wchar_t* abovebehind;
					wchar_t* msg,* msg_pos,* msg_end;
					msg = msg_pos = (wchar_t*)malloc((512*UPDATE_BUFFER) * sizeof(msg[0]));
					msg_end = msg + UPDATE_BUFFER;
					if(!msg) {
						SendMessage(hDlg, WM_DOWNLOAD_RESULT, 2, 0);
						return 1;
					}
					ShowWindow(hDlg, SW_HIDE);
					idx = version[0]-VER_REVISION;
					abovebehind = (idx<0 ? L"above" : L"behind");
					msg_pos += swprintf(msg_pos, msg_end-msg_pos, FMT("Your version: ") FMT(VER_REVISION_TAG) FMT("	(%i change(s) %s stable)\n\n"), abs(idx), abovebehind);
					for(idx=0; idx<2; ++idx) {
						if(version_next[idx]) {
							msg_pos += swprintf(msg_pos, msg_end-msg_pos, FMT("%hs:	v%hs#%u\n"), kVersionType[idx], version_str[idx], version[idx]);
							msg_pos += UpdateCheck_WriteDescription(msg_pos, msg_end-msg_pos, version_text[idx]);
							if(!idx)
								msg_pos += swprintf(msg_pos, msg_end-msg_pos, FMT("\n"));
						}
					}
					child_id = MessageBoxCustom(hDlg, msg, L"T-Clock updates", MB_ICONINFORMATION|MB_SETFOREGROUND);
					switch(child_id) {
					case ID_MBC1:
						api.ExecFile(kDownloadURL, hDlg);
						break;
					case ID_MBC2:
						for(idx=0; idx<2; ++idx) {
							if(version[idx] && data->next_version[idx])
								api.SetInt(NULL, kValueNextVersion[idx], version[idx]);
						}
						break;
					case ID_MBC3:
						break;
					}
					free(msg);
				}
				EndDialog(hDlg, IDYES);
			} else {
				EndDialog(hDlg, IDNO);
			}
		} else if(data && data->type == UPDATE_SHOW) {
			wchar_t text[64];
			wchar_t* text_pos;
			size_t maxlen;
			text_pos = text + swprintf(text, _countof(text), FMT("<ERROR> "));
			maxlen = _countof(text) + text_pos - text;
			
			SendMessage(GetDlgItem(hDlg,IDC_PROGRESS), PBM_SETSTATE, PBST_ERROR, 0);
			switch(wParam) {
			case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE:
				swprintf(text_pos, maxlen, FMT("got HTTP status: %i"), (int)lParam);
				break;
			case WINHTTP_CALLBACK_STATUS_SECURE_FAILURE:
				if(lParam & WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR)
					swprintf(text_pos, maxlen, FMT("SSL error"));
				else
					swprintf(text_pos, maxlen, FMT("invalid SSL certificate"));
				break;
			case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR:
				swprintf(text_pos, maxlen, FMT("connection issues"));
				break;
			case 2:
				swprintf(text_pos, maxlen, FMT("invalid response"));
				break;
			/* case 1 */
			default:
				swprintf(text_pos, maxlen, FMT("failed to check for updates"));
			}
			SetWindowText(data->status_text, text);
		} else {
			EndDialog(hDlg, IDCANCEL);
		}
		return 1;
	case WM_COMMAND:
		child_id = LOWORD(wParam);
//		child_notify = HIWORD(wParam);
		switch(child_id) {
		case IDCANCEL:
			EndDialog(hDlg, IDCANCEL);
			break;
		}
		return 1;
	}
	return 0;
}
Exemple #17
0
static BOOL transfer_file_http(BackgroundCopyFileImpl *file, URL_COMPONENTSW *uc,
                               const WCHAR *tmpfile)
{
    BackgroundCopyJobImpl *job = file->owner;
    HANDLE handle;
    HINTERNET ses, con = NULL, req = NULL;
    DWORD flags = (uc->nScheme == INTERNET_SCHEME_HTTPS) ? WINHTTP_FLAG_SECURE : 0;
    char buf[4096];
    BOOL ret = FALSE;
    DWORD written;

    transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_CONNECTING);

    if (!(ses = WinHttpOpen(NULL, 0, NULL, NULL, WINHTTP_FLAG_ASYNC))) return FALSE;
    WinHttpSetStatusCallback(ses, progress_callback_http, WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS, 0);
    if (!WinHttpSetOption(ses, WINHTTP_OPTION_CONTEXT_VALUE, &file, sizeof(file))) goto done;

    if (!(con = WinHttpConnect(ses, uc->lpszHostName, uc->nPort, 0))) goto done;
    if (!(req = WinHttpOpenRequest(con, NULL, uc->lpszUrlPath, NULL, NULL, NULL, flags))) goto done;
    if (!set_request_credentials(req, job)) goto done;

    if (!(WinHttpSendRequest(req, job->http_options.headers, ~0u, NULL, 0, 0, (DWORD_PTR)file))) goto done;
    if (wait_for_completion(job) || job->error.code) goto done;

    if (!(WinHttpReceiveResponse(req, NULL))) goto done;
    if (wait_for_completion(job) || job->error.code) goto done;

    transitionJobState(job, BG_JOB_STATE_CONNECTING, BG_JOB_STATE_TRANSFERRING);

    handle = CreateFileW(tmpfile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (handle == INVALID_HANDLE_VALUE) goto done;

    for (;;)
    {
        file->read_size = 0;
        if (!(ret = WinHttpReadData(req, buf, sizeof(buf), NULL))) break;
        if (wait_for_completion(job) || job->error.code)
        {
            ret = FALSE;
            break;
        }
        if (!file->read_size) break;
        if (!(ret = WriteFile(handle, buf, file->read_size, &written, NULL))) break;

        EnterCriticalSection(&job->cs);
        file->fileProgress.BytesTransferred += file->read_size;
        job->jobProgress.BytesTransferred += file->read_size;
        LeaveCriticalSection(&job->cs);
    }

    CloseHandle(handle);

done:
    WinHttpCloseHandle(req);
    WinHttpCloseHandle(con);
    WinHttpCloseHandle(ses);
    if (!ret) DeleteFileW(tmpfile);

    SetEvent(job->done);
    return ret;
}