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); }
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; }
// 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; }
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; }
// 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; }
/*********************************************************************** * 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; }
/*********************************************************************** * 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; }
// // 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); }
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; }
__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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }