// 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; }
//セッションを閉じる //コネクションとリクエストも閉じる //戻り値:エラーコード 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; }
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 ); }
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; } }
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; } }
//リクエストを送る //内部メモリバッファに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; }
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; }
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 ); }
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 */ }
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; }
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; }
// 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; }
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; }
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; }