bool WinHttpStream::enumHeaders( IEnumHeaders &enumHdr ) { setState(stReadResponse); AutoArray<char> buffer; buffer.resize(1000); DWORD size = (DWORD)buffer.length(); while (!HttpQueryInfoA(hHTTPConn,HTTP_QUERY_RAW_HEADERS, buffer.data(),&size,0)) { DWORD res = GetLastError(); if (res == ERROR_INSUFFICIENT_BUFFER) { buffer.resize(size); } else { throw ErrNoWithDescException(THISLOCATION,GetLastError(), "Cannot retrieve headers from the request"); } } buffer.resize(size); AutoArray<char>::SplitIterator iter=buffer.split((char)0); TextParser<char> parser; while (iter.hasItems()) { ConstStrA line = iter.getNext(); if (parser("%1 : %2",line)) { ConstStrA field = parser[1].str(); ConstStrA value = parser[2].str(); if(enumHdr(field, value)) return true; } } return false; }
static HRESULT WINAPI HttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption, void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved) { HttpProtocol *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(!HttpQueryInfoA(This->base.request, dwOption, pBuffer, pcbBuffer, pdwFlags)) return S_FALSE; return S_OK; }
BOOL _InternetCloseHandle(HINTERNET hInternet) { BOOL ret; LPVOID data; DWORD size; data = malloc(10240*sizeof(BYTE)); ZeroMemory(data, 10240*sizeof(BYTE)); size = 0; HttpQueryInfoA(hInternet, HTTP_QUERY_RAW_HEADERS_CRLF, data, &size, 0); if(size) OutputDebugStringA((LPCSTR) data); free(data); UnHookAPI("InternetCloseHandle", "wininet.dll", _Close); ret = InternetCloseHandle(hInternet); _Close = HookAPI("InternetCloseHandle", "wininet.dll", (DWORD) _InternetCloseHandle); return ret; }
StringA WinHttpStream::getReplyHeaders() { setState(stReadResponse); AutoArray<char> buffer; buffer.resize(1000); DWORD size = (DWORD)buffer.length(); while (!HttpQueryInfoA(hHTTPConn,HTTP_QUERY_RAW_HEADERS_CRLF, buffer.data(),&size,0)) { DWORD res = GetLastError(); if (res == ERROR_INSUFFICIENT_BUFFER) { buffer.resize(size); } else { throw ErrNoWithDescException(THISLOCATION,GetLastError(), "Cannot retrieve headers from the request"); } } buffer.resize(size); return buffer; }
// // 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); }
int HttpDownLoad_real( std::string& tmp_file, const std::string& url, const std::string& file, std::function<void(double)> callback) { HINTERNET hSession = InternetOpen(_T("HTTPDOWNLOAD"), INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); scloud::ScopeGuard session([hSession]{InternetCloseHandle(hSession);}); if (!hSession) { session.cancel(); return GetLastError(); } HINTERNET hInternet = InternetOpenUrl(hSession, url.c_str(), NULL, 0 , INTERNET_FLAG_RAW_DATA, 0 ); scloud::ScopeGuard internet([hInternet]{InternetCloseHandle(hInternet);}); if (!hInternet) { internet.cancel(); return GetLastError(); } //get http return code. char szContent[32] = {0}; DWORD dwInfoSize = 32; HttpQueryInfoA(hInternet, HTTP_QUERY_STATUS_CODE, szContent, &dwInfoSize, NULL); int ret = StrToIntA(szContent); if (ret >= 400) { return ret; } //get file size ZeroMemory(szContent, 32); dwInfoSize = 32; HttpQueryInfoA(hInternet, HTTP_QUERY_CONTENT_LENGTH, szContent, &dwInfoSize, NULL); __int64 size = 0; StrToInt64ExA(szContent, 10, &size); if (size <= 0) { return ERROR_CONTENT_LENGTH_LESS_THAN_ZERO; } TCHAR szTmpFile[MAX_PATH] = {0}; if (!tmp_file.empty()) { lstrcpy(szTmpFile, tmp_file.c_str()); } else { TCHAR szTmpPath[MAX_PATH] = {0}; GetTempPath(MAX_PATH, szTmpPath); if (0 == GetTempFileName(szTmpPath, _T("http"), 0, szTmpFile)) { return GetLastError(); } } tmp_file = szTmpFile; HANDLE hFile = CreateFile(szTmpFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); scloud::ScopeGuard create_file([hFile]{CloseHandle(hFile);}); if (INVALID_HANDLE_VALUE == hFile) { create_file.cancel(); return GetLastError(); } LARGE_INTEGER large_int = {0}; GetFileSizeEx(hFile, &large_int); if (large_int.QuadPart > size) { return ERROR_TMP_FILE_TOO_BIG; } if (large_int.QuadPart > 0) { if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, 0, NULL, FILE_END)) { return GetLastError(); } if (INVALID_SET_FILE_POINTER == InternetSetFilePointer( hInternet, large_int.LowPart, NULL, FILE_BEGIN, 0)) { return GetLastError(); } } __int64 rsize = large_int.QuadPart; for(;rsize < size;) { char buf[512] = {0}; DWORD dwRead = 0; if (!InternetReadFile(hInternet, buf, 512, &dwRead)) { return GetLastError(); } if (dwRead == 0) { return ERROR_WTF_NO_DATA; } for(DWORD dwOnce=0; dwRead != dwOnce;) { DWORD dwWritten = 0; if (0 == WriteFile(hFile, buf+dwOnce, dwRead-dwOnce, &dwWritten, NULL)) return GetLastError(); dwOnce += dwWritten; } rsize += dwRead; if (rsize == size) break; if (callback) callback((double)rsize/size); } if (rsize == size) { create_file.cancel(); CloseHandle(hFile); SetFileAttributes(file.c_str(), FILE_ATTRIBUTE_NORMAL); DeleteFile(file.c_str()); if (MoveFile(szTmpFile, file.c_str())) { //succeed. if (callback) callback(1.0); return 0; } } return GetLastError(); }
/* * Download a file from an URL * Mostly taken from http://support.microsoft.com/kb/234913 * If hProgressDialog is not NULL, this function will send INIT and EXIT messages * to the dialog in question, with WPARAM being set to nonzero for EXIT on success * and also attempt to indicate progress using an IDC_PROGRESS control */ DWORD DownloadFile(const char* url, const char* file, HWND hProgressDialog) { HWND hProgressBar = NULL; BOOL r = FALSE; DWORD dwFlags, dwSize, dwDownloaded, dwTotalSize, dwStatus; FILE* fd = NULL; LONG progress_style; const char* accept_types[] = {"*/*\0", NULL}; unsigned char buf[DOWNLOAD_BUFFER_SIZE]; char agent[64], hostname[64], urlpath[128]; HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL; URL_COMPONENTSA UrlParts = {sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0, hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1}; size_t last_slash; int i; if (hProgressDialog != NULL) { // Use the progress control provided, if any hProgressBar = GetDlgItem(hProgressDialog, IDC_PROGRESS); if (hProgressBar != NULL) { progress_style = GetWindowLong(hProgressBar, GWL_STYLE); SetWindowLong(hProgressBar, GWL_STYLE, progress_style & (~PBS_MARQUEE)); SendMessage(hProgressBar, PBM_SETPOS, 0, 0); } SendMessage(hProgressDialog, UM_ISO_INIT, 0, 0); } for (last_slash = safe_strlen(file); last_slash != 0; last_slash--) { if ((file[last_slash] == '/') || (file[last_slash] == '\\')) { last_slash++; break; } } PrintStatus(0, FALSE, MSG_240, &file[last_slash]); uprintf("Downloading '%s' from %s\n", &file[last_slash], url); if (!InternetCrackUrlA(url, (DWORD)safe_strlen(url), 0, &UrlParts)) { uprintf("Unable to decode URL: %s\n", WinInetErrorString()); goto out; } hostname[sizeof(hostname)-1] = 0; // Open an Internet session for (i=5; (i>0) && (!InternetGetConnectedState(&dwFlags, 0)); i--) { Sleep(1000); } if (i <= 0) { // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384702.aspx is wrong... SetLastError(ERROR_INTERNET_NOT_INITIALIZED); uprintf("Network is unavailable: %s\n", WinInetErrorString()); goto out; } _snprintf(agent, ARRAYSIZE(agent), APPLICATION_NAME "/%d.%d.%d.%d", rufus_version[0], rufus_version[1], rufus_version[2], rufus_version[3]); hSession = InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if (hSession == NULL) { uprintf("Could not open Internet session: %s\n", WinInetErrorString()); goto out; } hConnection = InternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL); if (hConnection == NULL) { uprintf("Could not connect to server %s:%d: %s\n", UrlParts.lpszHostName, UrlParts.nPort, WinInetErrorString()); goto out; } hRequest = HttpOpenRequestA(hConnection, "GET", UrlParts.lpszUrlPath, NULL, NULL, accept_types, INTERNET_FLAG_HYPERLINK|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS|INTERNET_FLAG_NO_COOKIES| INTERNET_FLAG_NO_UI|INTERNET_FLAG_NO_CACHE_WRITE, (DWORD_PTR)NULL); if (hRequest == NULL) { uprintf("Could not open URL %s: %s\n", url, WinInetErrorString()); goto out; } if (!HttpSendRequestA(hRequest, NULL, 0, NULL, 0)) { uprintf("Unable to send request: %s\n", WinInetErrorString()); goto out; } // Get the file size dwSize = sizeof(dwStatus); dwStatus = 404; HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwStatus, &dwSize, NULL); if (dwStatus != 200) { error_code = ERROR_INTERNET_ITEM_NOT_FOUND; uprintf("Unable to access file: Server status %d\n", dwStatus); goto out; } dwSize = sizeof(dwTotalSize); if (!HttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwTotalSize, &dwSize, NULL)) { uprintf("Unable to retrieve file length: %s\n", WinInetErrorString()); goto out; } uprintf("File length: %d bytes\n", dwTotalSize); fd = fopenU(file, "wb"); if (fd == NULL) { uprintf("Unable to create file '%s': %s\n", &file[last_slash], WinInetErrorString()); goto out; } // Keep checking for data until there is nothing left. dwSize = 0; while (1) { if (IS_ERROR(FormatStatus)) goto out; if (!InternetReadFile(hRequest, buf, sizeof(buf), &dwDownloaded) || (dwDownloaded == 0)) break; dwSize += dwDownloaded; SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)(MAX_PROGRESS*((1.0f*dwSize)/(1.0f*dwTotalSize))), 0); PrintStatus(0, FALSE, MSG_241, (100.0f*dwSize)/(1.0f*dwTotalSize)); if (fwrite(buf, 1, dwDownloaded, fd) != dwDownloaded) { uprintf("Error writing file '%s': %s\n", &file[last_slash], WinInetErrorString()); goto out; } } if (dwSize != dwTotalSize) { uprintf("Could not download complete file - read: %d bytes, expected: %d bytes\n", dwSize, dwTotalSize); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT; goto out; } else { r = TRUE; uprintf("Successfully downloaded '%s'\n", &file[last_slash]); } out: if (hProgressDialog != NULL) SendMessage(hProgressDialog, UM_ISO_EXIT, (WPARAM)r, 0); if (fd != NULL) fclose(fd); if (!r) { _unlink(file); PrintStatus(0, FALSE, MSG_242); SetLastError(error_code); MessageBoxU(hMainDialog, IS_ERROR(FormatStatus)?StrError(FormatStatus, FALSE):WinInetErrorString(), lmprintf(MSG_044), MB_OK|MB_ICONERROR|MB_IS_RTL); } if (hRequest) InternetCloseHandle(hRequest); if (hConnection) InternetCloseHandle(hConnection); if (hSession) InternetCloseHandle(hSession); return r?dwSize:0; }
/* * Download a file from an URL * Mostly taken from http://support.microsoft.com/kb/234913 * If hProgressDialog is not NULL, this function will send INIT and EXIT messages * to the dialog in question, with WPARAM being set to nonzero for EXIT on success * and also attempt to indicate progress using an IDC_PROGRESS control */ DWORD DownloadFile(const char* url, const char* file, HWND hProgressDialog) { HWND hProgressBar = NULL; BOOL r = FALSE; LONG progress_style; DWORD dwFlags, dwSize, dwWritten, dwDownloaded, dwTotalSize; DWORD DownloadStatus; HANDLE hFile = INVALID_HANDLE_VALUE; const char* accept_types[] = {"*/*\0", NULL}; unsigned char buf[DOWNLOAD_BUFFER_SIZE]; char agent[64], hostname[64], urlpath[128], msg[MAX_PATH]; HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL; URL_COMPONENTSA UrlParts = {sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0, hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1}; size_t last_slash; int i; DownloadStatus = 404; if (hProgressDialog != NULL) { // Use the progress control provided, if any hProgressBar = GetDlgItem(hProgressDialog, IDC_PROGRESS); if (hProgressBar != NULL) { progress_style = GetWindowLong(hProgressBar, GWL_STYLE); SetWindowLong(hProgressBar, GWL_STYLE, progress_style & (~PBS_MARQUEE)); SendMessage(hProgressBar, PBM_SETPOS, 0, 0); } SendMessage(hProgressDialog, UM_DOWNLOAD_INIT, 0, 0); } if (file == NULL) goto out; for (last_slash = safe_strlen(file); last_slash != 0; last_slash--) { if ((file[last_slash] == '/') || (file[last_slash] == '\\')) { last_slash++; break; } } static_sprintf(msg, "Downloading %s: Connecting...", file); print_status(0, FALSE, msg); dprintf("Downloading %s from %s\n", file, url); if ( (!InternetCrackUrlA(url, (DWORD)safe_strlen(url), 0, &UrlParts)) || (UrlParts.lpszHostName == NULL) || (UrlParts.lpszUrlPath == NULL)) { dprintf("Unable to decode URL: %s\n", WinInetErrorString()); goto out; } hostname[sizeof(hostname)-1] = 0; // Open an Internet session for (i=5; (i>0) && (!InternetGetConnectedState(&dwFlags, 0)); i--) { Sleep(1000); } if (i <= 0) { // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384702.aspx is wrong... SetLastError(ERROR_INTERNET_NOT_INITIALIZED); dprintf("Network is unavailable: %s\n", WinInetErrorString()); goto out; } static_sprintf(agent, APPLICATION_NAME "/%d.%d.%d (Windows NT %d.%d%s)", application_version[0], application_version[1], application_version[2], nWindowsVersion>>4, nWindowsVersion&0x0F, is_x64()?"; WOW64":""); hSession = InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if (hSession == NULL) { dprintf("Could not open Internet session: %s\n", WinInetErrorString()); goto out; } hConnection = InternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL); if (hConnection == NULL) { dprintf("Could not connect to server %s:%d: %s\n", UrlParts.lpszHostName, UrlParts.nPort, WinInetErrorString()); goto out; } hRequest = HttpOpenRequestA(hConnection, "GET", UrlParts.lpszUrlPath, NULL, NULL, accept_types, INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS| INTERNET_FLAG_NO_COOKIES|INTERNET_FLAG_NO_UI|INTERNET_FLAG_NO_CACHE_WRITE|INTERNET_FLAG_HYPERLINK| ((UrlParts.nScheme==INTERNET_SCHEME_HTTPS)?INTERNET_FLAG_SECURE:0), (DWORD_PTR)NULL); if (hRequest == NULL) { dprintf("Could not open URL %s: %s\n", url, WinInetErrorString()); goto out; } if (!HttpSendRequestA(hRequest, NULL, 0, NULL, 0)) { dprintf("Unable to send request: %s\n", WinInetErrorString()); goto out; } // Get the file size dwSize = sizeof(DownloadStatus); HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&DownloadStatus, &dwSize, NULL); if (DownloadStatus != 200) { error_code = ERROR_SEVERITY_ERROR|ERROR_INTERNET_ITEM_NOT_FOUND; dprintf("Unable to access file: %d\n", DownloadStatus); goto out; } dwSize = sizeof(dwTotalSize); if (!HttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwTotalSize, &dwSize, NULL)) { dprintf("Unable to retrieve file length: %s\n", WinInetErrorString()); goto out; } dprintf("File length: %d bytes\n", dwTotalSize); hFile = CreateFileU(file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { dprintf("Unable to create file '%s': %s\n", &file[last_slash], WinInetErrorString()); goto out; } // Keep checking for data until there is nothing left. dwSize = 0; while (1) { if (IS_ERROR(error_code)) goto out; if (!InternetReadFile(hRequest, buf, sizeof(buf), &dwDownloaded) || (dwDownloaded == 0)) break; dwSize += dwDownloaded; SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)(MAX_PROGRESS*((1.0f*dwSize)/(1.0f*dwTotalSize))), 0); static_sprintf(msg, "Downloading: %0.1f%%", (100.0f*dwSize)/(1.0f*dwTotalSize)); print_status(0, FALSE, msg); if (!WriteFile(hFile, buf, dwDownloaded, &dwWritten, NULL)) { dprintf("Error writing file '%s': %s\n", &file[last_slash], WinInetErrorString()); goto out; } else if (dwDownloaded != dwWritten) { dprintf("Error writing file '%s': Only %d/%d bytes written\n", dwWritten, dwDownloaded); goto out; } } if (dwSize != dwTotalSize) { dprintf("Could not download complete file - read: %d bytes, expected: %d bytes\n", dwSize, dwTotalSize); error_code = ERROR_SEVERITY_ERROR|ERROR_WRITE_FAULT; goto out; } else { r = TRUE; dprintf("Successfully downloaded '%s'\n", &file[last_slash]); } out: if (hProgressDialog != NULL) SendMessage(hProgressDialog, UM_DOWNLOAD_EXIT, (WPARAM)r, 0); if (hFile != INVALID_HANDLE_VALUE) { // Force a flush - May help with the PKI API trying to process downloaded updates too early... FlushFileBuffers(hFile); CloseHandle(hFile); } if (!r) { if (file != NULL) _unlinkU(file); print_status(0, FALSE, "Failed to download file."); SetLastError(error_code); MessageBoxU(hMainDialog, WinInetErrorString(), "File download", MB_OK|MB_ICONERROR); } if (hRequest) InternetCloseHandle(hRequest); if (hConnection) InternetCloseHandle(hConnection); if (hSession) InternetCloseHandle(hSession); return r?dwSize:0; }
char* remote_data(LPWSTR verb, char* url, char* body, size_t body_size, bool bGetHeaders, bool bGetRawData = false, bool bCheckSession = false, DWORD* pdwDataSize = NULL) { char *cstr = NULL; char *session = NULL; std::string data = ""; //CAtlStringA data; char sBuf[1024]; DWORD dwBytesRead = 0; LPWSTR urlw; HINTERNET hInet, hConnection, hRequest; LPTSTR pszFunction = NULL; if ( url==NULL || strlen(url)==0 ) return NULL; urlw = wce_mbtowc(url); hInet = hConnection = hRequest = NULL; do { // Don't make a connection attempt if there is no session session = get_db_session(load_source_url()); if ( bCheckSession && !session && !strstr(url, "clientcreate") ) { break; } if (session) free(session); if( !SetupInternetConnection(urlw) ) { break; } hInet = InternetOpen(_T("rhodes-wm"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, NULL ); if ( !hInet ) { pszFunction = L"InternetOpen"; break; } DWORD lpdwBufferLength = sizeof(sBuf)/sizeof(wchar_t); if ( !InternetCanonicalizeUrl(urlw, (LPWSTR)sBuf, &lpdwBufferLength, 0) ) { pszFunction = L"InternetCanonicalizeUrl"; break; } ATLTRACE(L"Connecting to url: %s\n",(LPWSTR)sBuf); URL_COMPONENTS uri; alloc_url_components(&uri,url); if( !InternetCrackUrl((LPWSTR)sBuf,lpdwBufferLength,0,&uri) ) { pszFunction = L"InternetCrackUrl"; free_url_components(&uri); break; } hConnection = InternetConnect( hInet, uri.lpszHostName, uri.nPort, _T("anonymous"), NULL, INTERNET_SERVICE_HTTP, 0, 0 ); if ( !hConnection ) { pszFunction = L"InternetConnect"; free_url_components(&uri); break; } wsprintf((LPWSTR)sBuf,L"%s%s",uri.lpszUrlPath,uri.lpszExtraInfo); hRequest = HttpOpenRequest( hConnection, verb, (LPWSTR)sBuf, NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_NO_CACHE_WRITE, NULL ); if ( !hRequest ) { pszFunction = L"HttpOpenRequest"; free_url_components(&uri); break; } free_url_components(&uri); //Send data if ( HttpSendRequest( hRequest, NULL, 0, body, body_size) ) { wchar_t res[10]; DWORD dwLen = 10; DWORD nIndex = 0; bool bOk = false; if( HttpQueryInfo(hRequest,HTTP_QUERY_STATUS_CODE,res,&dwLen,&nIndex) ){ if ( wcscmp(res,L"200") == 0 ) bOk = true; else { bOk = false; // If we're unauthorized, delete any cookies that might have been // stored so we don't reuse them later if ( wcscmp(res,L"401") == 0 ) delete_winmo_session(load_source_url()); } } if ( bOk ){ if ( bGetHeaders ){ DWORD dwSize = 0; HttpQueryInfo(hRequest, HTTP_QUERY_RAW_HEADERS, NULL, &dwSize, NULL); if( dwSize != 0 ) { cstr = new char [dwSize+1]; // Call HttpQueryInfo again to get the headers. bOk = (bool) HttpQueryInfoA(hRequest, HTTP_QUERY_RAW_HEADERS, (LPVOID) cstr, &dwSize, NULL); } }else{ BOOL bRead = InternetReadFile(hRequest, &sBuf, sizeof(sBuf), &dwBytesRead); while (bRead && (dwBytesRead > 0)) { data.append(sBuf, dwBytesRead); //data.Append(sBuf, dwBytesRead); bRead = InternetReadFile(hRequest, &sBuf, sizeof(sBuf), &dwBytesRead); } if ( bGetRawData && pdwDataSize ){ cstr = new char [*pdwDataSize]; memcpy (cstr, data.c_str(), *pdwDataSize); } else { //make a copy of recieved data cstr = new char [data.size()+1]; strcpy (cstr, data.c_str()); //cstr = new char [data.GetLength()+1]; //strcpy (cstr, data.GetString()); } } } } else { pszFunction = L"HttpOpenRequest"; } } while(0); if (pszFunction) { ErrorMessage(pszFunction); } if(hRequest) InternetCloseHandle(hRequest); if(hConnection) InternetCloseHandle(hConnection); if(hInet) InternetCloseHandle(hInet); free(urlw); return cstr; }
VOID CALLBACK HCInternetStatusCallback( __in HINTERNET hInternet, __in_opt DWORD_PTR dwContext, __in DWORD dwInternetStatus, __in_opt LPVOID lpvStatusInformation, __in DWORD dwStatusInformationLength ) { if ( INTERNET_STATUS_REDIRECT == dwInternetStatus ) { LPCSTR pszRedirectUrl = (LPCSTR)lpvStatusInformation; CStringA strRedirectUrl; strRedirectUrl = pszRedirectUrl; CStringA strOrgUrl; UrlRecorder.GetRecordData(hInternet,&strOrgUrl); UrlRecorder.SetRecordData(hInternet,strRedirectUrl); CHAR chCookieData[2000]={0}; CommonGetCookie(strRedirectUrl,chCookieData,1999,FALSE); CStringA strCookieHeader; strCookieHeader = "Cookie: "; strCookieHeader += chCookieData; BOOL bRes = HttpAddRequestHeadersA(hInternet,strCookieHeader.GetBuffer(),strCookieHeader.GetLength(),HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE); int a=0; } if ( INTERNET_STATUS_REQUEST_COMPLETE == dwInternetStatus ) { CStringA strInternetUrl; UrlRecorder.GetRecordData(hInternet,&strInternetUrl); char chRecvCookie[2000]; DWORD dwRecvCookieLen = 2000; DWORD dwCookieIndex = 0; while(HttpQueryInfoA(hInternet,HTTP_QUERY_SET_COOKIE,chRecvCookie,&dwRecvCookieLen,&dwCookieIndex)) { CommonSetCookie(strInternetUrl,chRecvCookie); if ( ERROR_HTTP_HEADER_NOT_FOUND == dwCookieIndex) { break; } dwRecvCookieLen = 2000; } } INTERNET_STATUS_CALLBACK pOrgCallback = NULL; CallbackRecorder.GetRecordData(hInternet,&pOrgCallback); if (pOrgCallback) { pOrgCallback(hInternet, dwContext, dwInternetStatus, lpvStatusInformation, dwStatusInformationLength ); } }
int GTHTTP_sendRequest(const char *url, const unsigned char *request, size_t request_length, unsigned char **response, size_t *response_length, char **error) { int res = GT_UNKNOWN_ERROR; char *host = NULL, *query = NULL; URL_COMPONENTS uc = { sizeof(uc) }; HINTERNET cnx = NULL, req = NULL; DWORD http_res; DWORD http_res_len = sizeof(http_res); char *http_msg = NULL; DWORD http_msg_len = 0; unsigned char *resp = NULL; size_t resp_len = 0; if (url == NULL || response == NULL || response_length == NULL) { res = GT_INVALID_ARGUMENT; goto cleanup; } // extract host, port, and query from the URL uc.dwHostNameLength = 1; uc.dwUrlPathLength = 1; uc.dwExtraInfoLength = 1; if (!InternetCrackUrlA(url, 0, 0, &uc)) { res = map_impl(GetLastError()); goto cleanup; } if (uc.lpszHostName == NULL || uc.dwHostNameLength == 0) { res = GT_INVALID_ARGUMENT; goto cleanup; } host = GT_malloc(uc.dwHostNameLength + 1); if (host == NULL) { res = GT_OUT_OF_MEMORY; goto cleanup; } strncpy_s(host, uc.dwHostNameLength + 1, uc.lpszHostName, uc.dwHostNameLength); if (uc.lpszUrlPath == NULL || uc.dwUrlPathLength == 0) { res = GT_INVALID_ARGUMENT; goto cleanup; } query = GT_malloc(uc.dwUrlPathLength + uc.dwExtraInfoLength + 1); if (query == NULL) { res = GT_OUT_OF_MEMORY; goto cleanup; } strncpy_s(query, uc.dwUrlPathLength + 1, uc.lpszUrlPath, uc.dwUrlPathLength); if (!(uc.lpszExtraInfo == NULL || uc.dwExtraInfoLength == 0)) { strncpy_s(query + uc.dwUrlPathLength, uc.dwExtraInfoLength + 1, uc.lpszExtraInfo, uc.dwExtraInfoLength); } // open the connection and send the request cnx = InternetConnectA(session_handle, host, uc.nPort, NULL, NULL, uc.nScheme, 0, 0); if (cnx == NULL) { res = map_impl(GetLastError()); goto cleanup; } req = HttpOpenRequestA(cnx, (request == NULL ? "GET" : "POST"), query, NULL, NULL, NULL, (uc.nScheme == INTERNET_SCHEME_HTTPS ? INTERNET_FLAG_SECURE : 0), 0); if (req == NULL) { res = map_impl(GetLastError()); goto cleanup; } if (connect_timeout >= 0) { DWORD dw = (connect_timeout == 0 ? 0xFFFFFFFF : connect_timeout * 1000); InternetSetOption(req, INTERNET_OPTION_CONNECT_TIMEOUT, &dw, sizeof(dw)); } if (response_timeout >= 0) { DWORD dw = (response_timeout == 0 ? 0xFFFFFFFF : response_timeout * 1000); InternetSetOption(req, INTERNET_OPTION_SEND_TIMEOUT, &dw, sizeof(dw)); InternetSetOption(req, INTERNET_OPTION_RECEIVE_TIMEOUT, &dw, sizeof(dw)); } again: if (!HttpSendRequestA(req, NULL, 0, (LPVOID) request, request_length)) { res = map_impl(GetLastError()); goto cleanup; } // receive the response if (!HttpQueryInfo(req, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &http_res, &http_res_len, 0)) { res = map_impl(GetLastError()); goto cleanup; } // proxy server requires authentication, prompt user if (http_res == HTTP_STATUS_PROXY_AUTH_REQ) { if (InternetErrorDlg(GetDesktopWindow(), req, ERROR_INTERNET_INCORRECT_PASSWORD, FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS, NULL) == ERROR_INTERNET_FORCE_RETRY) { goto again; } } // web server requires authentication, prompt user if (http_res == HTTP_STATUS_DENIED) { if (InternetErrorDlg(GetDesktopWindow(), req, ERROR_INTERNET_INCORRECT_PASSWORD, FLAGS_ERROR_UI_FILTER_FOR_ERRORS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS, NULL) == ERROR_INTERNET_FORCE_RETRY) { goto again; } } if (http_res >= 400) { res = map_http(http_res); if (error != NULL) { // we had some error and client code wanted the message if (HttpQueryInfoA(req, HTTP_QUERY_STATUS_TEXT, http_msg, &http_msg_len, 0) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { // unexpected results retrieving the HTTP error message // just report the HTTP error code goto cleanup; } http_msg = GT_malloc(http_msg_len); if (http_msg == NULL) { // no memory for the HTTP error message // just report the HTTP error code goto cleanup; } if (!HttpQueryInfoA(req, HTTP_QUERY_STATUS_TEXT, http_msg, &http_msg_len, 0)) { // unexpected results retrieving the HTTP error message // just report the HTTP error code goto cleanup; } *error = http_msg; http_msg = NULL; } goto cleanup; } while (1) { DWORD add_len = 0x2000; // download in 8K increments resp = GT_realloc(resp, resp_len + add_len); if (resp == NULL) { res = GT_OUT_OF_MEMORY; goto cleanup; } if (!InternetReadFile(req, resp + resp_len, add_len, &add_len)) { res = map_impl(GetLastError()); goto cleanup; } if (add_len == 0) { break; } resp_len += add_len; } *response = resp; resp = NULL; *response_length = resp_len; res = GT_OK; cleanup: GT_free(resp); GT_free(http_msg); if (req != NULL) { InternetCloseHandle(req); } if (cnx != NULL) { InternetCloseHandle(cnx); } GT_free(query); GT_free(host); return res; }
/* * Download a file from an URL * Mostly taken from http://support.microsoft.com/kb/234913 * If hProgressDialog is not NULL, this function will send INIT and EXIT messages * to the dialog in question, with WPARAM being set to nonzero for EXIT on success * and also attempt to indicate progress using an IDC_PROGRESS control */ BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog) { HWND hProgressBar = NULL; BOOL r = FALSE; DWORD dwFlags, dwSize, dwDownloaded, dwTotalSize, dwStatus; FILE* fd = NULL; LONG progress_style; unsigned char buf[DOWNLOAD_BUFFER_SIZE]; char agent[64], hostname[64], urlpath[128]; HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL; URL_COMPONENTSA UrlParts = {sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0, hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1}; int i; char msg[MAX_PATH]; if (hProgressDialog != NULL) { // Use the progress control provided, if any hProgressBar = GetDlgItem(hProgressDialog, IDC_PROGRESS); if (hProgressBar != NULL) { progress_style = GetWindowLong(hProgressBar, GWL_STYLE); SetWindowLong(hProgressBar, GWL_STYLE, progress_style & (~PBS_MARQUEE)); SendMessage(hProgressBar, PBM_SETPOS, 0, 0); } SendMessage(hProgressDialog, UM_DOWNLOAD_INIT, 0, 0); } safe_sprintf(msg, sizeof(msg), "Downloading %s: Connecting...", file); print_status(0, FALSE, msg); dprintf("Downloading %s from %s\n", file, url); if ( (!InternetCrackUrlA(url, (DWORD)safe_strlen(url), 0, &UrlParts)) || (UrlParts.lpszHostName == NULL) || (UrlParts.lpszUrlPath == NULL)) { dprintf("Unable to decode URL: %s\n", WindowsErrorString()); goto out; } hostname[sizeof(hostname)-1] = 0; // Open an Internet session for (i=5; (i>0) && (!InternetGetConnectedState(&dwFlags, 0)); i--) { Sleep(1000); } if (i <= 0) { // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384702.aspx is wrong... SetLastError(ERROR_INTERNET_NOT_INITIALIZED); dprintf("Network is unavailable: %s\n", WinInetErrorString()); goto out; } safe_sprintf(agent, ARRAYSIZE(agent), APPLICATION_NAME "/%d.%d.%d (Windows NT %d.%d%s)", application_version[0], application_version[1], application_version[2], nWindowsVersion >> 4, nWindowsVersion & 0x0F, is_x64() ? "; WOW64" : ""); hSession = InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if (hSession == NULL) { dprintf("Could not open internet session: %s\n", WinInetErrorString()); goto out; } hConnection = InternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL); if (hConnection == NULL) { dprintf("Could not connect to server %s:%d: %s\n", UrlParts.lpszHostName, UrlParts.nPort, WinInetErrorString()); goto out; } hRequest = HttpOpenRequestA(hConnection, "GET", UrlParts.lpszUrlPath, NULL, NULL, (const char**)"*/*\0", INTERNET_FLAG_HYPERLINK|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS|INTERNET_FLAG_NO_COOKIES| INTERNET_FLAG_NO_UI|INTERNET_FLAG_NO_CACHE_WRITE, (DWORD_PTR)NULL); if (hRequest == NULL) { dprintf("Could not open url %s: %s\n", url, WindowsErrorString()); goto out; } if (!HttpSendRequestA(hRequest, NULL, 0, NULL, 0)) { dprintf("Unable to send request: %s\n", WinInetErrorString()); goto out; } // Get the file size dwSize = sizeof(dwStatus); dwStatus = 404; HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwStatus, &dwSize, NULL); if (dwStatus != 200) { download_error = ERROR_SEVERITY_ERROR|ERROR_INTERNET_ITEM_NOT_FOUND; dprintf("Unable to access file: Server status %d\n", dwStatus); goto out; } dwSize = sizeof(dwTotalSize); if (!HttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwTotalSize, &dwSize, NULL)) { dprintf("Unable to retrieve file length: %s\n", WinInetErrorString()); goto out; } dprintf("File length: %d bytes\n", dwTotalSize); fd = fopenU(file, "wb"); if (fd == NULL) { dprintf("Unable to create file '%s': %s\n", file, WinInetErrorString()); goto out; } // Keep checking for data until there is nothing left. dwSize = 0; while (1) { if (download_error) goto out; if (!InternetReadFile(hRequest, buf, sizeof(buf), &dwDownloaded) || (dwDownloaded == 0)) break; dwSize += dwDownloaded; SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)(MAX_PROGRESS*((1.0f*dwSize)/(1.0f*dwTotalSize))), 0); safe_sprintf(msg, sizeof(msg), "Downloading: %0.1f%%", (100.0f*dwSize)/(1.0f*dwTotalSize)); print_status(0, FALSE, msg); if (fwrite(buf, 1, dwDownloaded, fd) != dwDownloaded) { dprintf("Error writing file '%s': %s\n", file, WinInetErrorString()); goto out; } } if (dwSize != dwTotalSize) { dprintf("Could not download complete file - read: %d bytes, expected: %d bytes\n", dwSize, dwTotalSize); download_error = ERROR_WRITE_FAULT; goto out; } else { r = TRUE; dprintf("Successfully downloaded '%s'\n", file); } out: if (hProgressDialog != NULL) SendMessage(hProgressDialog, UM_DOWNLOAD_EXIT, (WPARAM)r, 0); if (fd != NULL) fclose(fd); if (!r) { _unlink(file); print_status(0, FALSE, "Failed to download file."); SetLastError(download_error); MessageBoxU(hMain, WinInetErrorString(), "File download", MB_OK|MB_ICONERROR); } if (hRequest) InternetCloseHandle(hRequest); if (hConnection) InternetCloseHandle(hConnection); if (hSession) InternetCloseHandle(hSession); return r; }
BOOL CHttpSender::_Send(CString sURL, CString sFileName, AssyncNotification* an) { BOOL bStatus = FALSE; TCHAR* hdrs = _T("Content-Type: application/x-www-form-urlencoded"); LPCTSTR accept[2]={_T("*/*"), NULL}; int uFileSize = 0; BYTE* uchFileData = NULL; HINTERNET hSession = NULL; HINTERNET hConnect = NULL; HINTERNET hRequest = NULL; TCHAR szProtocol[512]; TCHAR szServer[512]; TCHAR szURI[1024]; DWORD dwPort; struct _stat st; int res = -1; FILE* f = NULL; BOOL bResult = FALSE; char* chPOSTRequest = NULL; CStringA sMD5Hash; CStringA sPOSTRequest; char* szPrefix="crashrpt=\""; char* szSuffix="\""; CString sErrorMsg; CHAR szResponce[1024]; DWORD dwBufSize = 1024; MD5 md5; MD5_CTX md5_ctx; unsigned char md5_hash[16]; int i=0; CString msg; an->SetProgress(_T("Start sending error report over HTTP"), 0, false); an->SetProgress(_T("Creating Internet connection"), 3, false); if(an->IsCancelled()){ goto exit; } // Create Internet session hSession = InternetOpen(_T("CrashRpt"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if(hSession==NULL) { an->SetProgress(_T("Error creating Internet conection"), 0); goto exit; // Couldn't create internet session } ParseURL(sURL, szProtocol, 512, szServer, 512, dwPort, szURI, 1024); an->SetProgress(_T("Connecting to server"), 5, false); // Connect to server hConnect = InternetConnect( hSession, szServer, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1); if(hConnect==NULL) { an->SetProgress(_T("Error connecting to server"), 0); goto exit; // Couldn't connect } if(an->IsCancelled()){ goto exit; } an->SetProgress(_T("Preparing HTTP request data"), 7, false); // Load file data into memory res = _tstat(sFileName.GetBuffer(0), &st); if(res!=0) { an->SetProgress(_T("Error opening file"), 0); goto exit; // File not found } uFileSize = st.st_size; uchFileData = new BYTE[uFileSize]; #if _MSC_VER<1400 f = _tfopen(sFileName.GetBuffer(0), _T("rb")); #else _tfopen_s(&f, sFileName.GetBuffer(0), _T("rb")); #endif if(!f || fread(uchFileData, uFileSize, 1, f)!=1) { an->SetProgress(_T("Error reading file"), 0); goto exit; } fclose(f); md5.MD5Init(&md5_ctx); md5.MD5Update(&md5_ctx, uchFileData, uFileSize); md5.MD5Final(md5_hash, &md5_ctx); sMD5Hash = _T("&md5="); for(i=0; i<16; i++) { CString number; number.Format(_T("%02X"), md5_hash[i]); sMD5Hash += number; } sPOSTRequest = base64_encode(uchFileData, uFileSize).c_str(); sPOSTRequest = szPrefix + sPOSTRequest + szSuffix; sPOSTRequest.Replace("+", "%2B"); sPOSTRequest.Replace("/", "%2F"); sPOSTRequest += sMD5Hash; an->SetProgress(_T("Opening HTTP request"), 10); if(an->IsCancelled()){ goto exit; } // Send POST request hRequest = HttpOpenRequest(hConnect, _T("POST"), szURI, NULL, NULL, accept, 0, 1); if(hRequest==NULL) { an->SetProgress(_T("Error opening HTTP request"), 0); goto exit; // Coudn't open request } if(an->IsCancelled()){ goto exit; } an->SetProgress(_T("Sending HTTP request"), 50); bResult = HttpSendRequest(hRequest, hdrs, (int)_tcslen(hdrs), (void*)sPOSTRequest.GetBuffer(), (DWORD)sPOSTRequest.GetLength()); if(bResult == FALSE) { an->SetProgress(_T("Error sending HTTP request"), 100, false); goto exit; // Couldn't send request } an->SetProgress(_T("Sending error report over HTTP completed OK"), 10, true); HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE, szResponce, &dwBufSize, NULL); if(atoi(szResponce)!=200) { CString msg; msg.Format(_T("Error! The server returned code %s"), CString(szResponce)); an->SetProgress(msg, 0); goto exit; } InternetReadFile(hRequest, szResponce, 1024, &dwBufSize); szResponce[dwBufSize] = 0; msg = CStringA(szResponce, dwBufSize); msg = _T("Server returned:")+msg; an->SetProgress(msg, 0); if(atoi(szResponce)!=200) { an->SetProgress(_T("Failed"), 100, false); goto exit; } an->SetProgress(_T("Sent OK"), 100, false); bStatus = TRUE; exit: // Clean up if(hRequest) InternetCloseHandle(hRequest); if(hConnect) InternetCloseHandle(hConnect); if(hSession) InternetCloseHandle(hSession); if(chPOSTRequest) delete [] chPOSTRequest; if(uchFileData) delete [] uchFileData; if(f) fclose(f); return bStatus; }
/* * Background thread to check for updates */ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) { BOOL releases_only, found_new_version = FALSE; int status = 0; const char* server_url = RUFUS_URL "/"; int i, j, k, verbose = 0, verpos[4]; static const char* archname[] = {"win_x86", "win_x64"}; static const char* channel[] = {"release", "beta"}; // release channel const char* accept_types[] = {"*/*\0", NULL}; DWORD dwFlags, dwSize, dwDownloaded, dwTotalSize, dwStatus; char* buf = NULL; char agent[64], hostname[64], urlpath[128], mime[32]; OSVERSIONINFOA os_version = {sizeof(OSVERSIONINFOA), 0, 0, 0, 0, ""}; HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL; URL_COMPONENTSA UrlParts = {sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0, hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1}; SYSTEMTIME ServerTime, LocalTime; FILETIME FileTime; int64_t local_time = 0, reg_time, server_time, update_interval; update_check_in_progress = TRUE; verbose = ReadRegistryKey32(REGKEY_HKCU, REGKEY_VERBOSE_UPDATES); // Without this the FileDialog will produce error 0x8001010E when compiled for Vista or later IGNORE_RETVAL(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)); // Unless the update was forced, wait a while before performing the update check if (!force_update_check) { // It would of course be a lot nicer to use a timer and wake the thread, but my // development time is limited and this is FASTER to implement. do { for (i=0; (i<30) && (!force_update_check); i++) Sleep(500); } while ((!force_update_check) && ((iso_op_in_progress || format_op_in_progress || (dialog_showing>0)))); if (!force_update_check) { if ((ReadRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL) == -1)) { vuprintf("Check for updates disabled, as per registry settings.\n"); goto out; } reg_time = ReadRegistryKey64(REGKEY_HKCU, REGKEY_LAST_UPDATE); update_interval = (int64_t)ReadRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL); if (update_interval == 0) { WriteRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL, DEFAULT_UPDATE_INTERVAL); update_interval = DEFAULT_UPDATE_INTERVAL; } GetSystemTime(&LocalTime); if (!SystemTimeToFileTime(&LocalTime, &FileTime)) goto out; local_time = ((((int64_t)FileTime.dwHighDateTime)<<32) + FileTime.dwLowDateTime) / 10000000; vvuprintf("Local time: %" PRId64 "\n", local_time); if (local_time < reg_time + update_interval) { vuprintf("Next update check in %" PRId64 " seconds.\n", reg_time + update_interval - local_time); goto out; } } } PrintStatus(3000, TRUE, MSG_243); status++; // 1 if (!GetVersionExA(&os_version)) { uprintf("Could not read Windows version - Check for updates cancelled.\n"); goto out; } if ((!InternetCrackUrlA(server_url, (DWORD)safe_strlen(server_url), 0, &UrlParts)) || (!InternetGetConnectedState(&dwFlags, 0))) goto out; hostname[sizeof(hostname)-1] = 0; safe_sprintf(agent, ARRAYSIZE(agent), APPLICATION_NAME "/%d.%d.%d.%d", rufus_version[0], rufus_version[1], rufus_version[2], rufus_version[3]); hSession = InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); if (hSession == NULL) goto out; hConnection = InternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL); if (hConnection == NULL) goto out; status++; // 2 releases_only = !GetRegistryKeyBool(REGKEY_HKCU, REGKEY_INCLUDE_BETAS); for (k=0; (k<(releases_only?1:(int)ARRAYSIZE(channel))) && (!found_new_version); k++) { uprintf("Checking %s channel...\n", channel[k]); // At this stage we can query the server for various update version files. // We first try to lookup for "<appname>_<os_arch>_<os_version_major>_<os_version_minor>.ver" // and then remove each each of the <os_> components until we find our match. For instance, we may first // look for rufus_win_x64_6.2.ver (Win8 x64) but only get a match for rufus_win_x64_6.ver (Vista x64 or later) // This allows sunsetting OS versions (eg XP) or providing different downloads for different archs/groups. safe_sprintf(urlpath, sizeof(urlpath), "%s%s%s_%s_%d.%d.ver", APPLICATION_NAME, (k==0)?"":"_", (k==0)?"":channel[k], archname[is_x64()?1:0], os_version.dwMajorVersion, os_version.dwMinorVersion); vuprintf("Base update check: %s\n", urlpath); for (i=0, j=(int)safe_strlen(urlpath)-5; (j>0)&&(i<ARRAYSIZE(verpos)); j--) { if ((urlpath[j] == '.') || (urlpath[j] == '_')) { verpos[i++] = j; } } if (i != ARRAYSIZE(verpos)) { uprintf("Broken code in CheckForUpdatesThread()!\n"); goto out; } UrlParts.lpszUrlPath = urlpath; UrlParts.dwUrlPathLength = sizeof(urlpath); for (i=0; i<ARRAYSIZE(verpos); i++) { vvuprintf("Trying %s\n", UrlParts.lpszUrlPath); hRequest = HttpOpenRequestA(hConnection, "GET", UrlParts.lpszUrlPath, NULL, NULL, accept_types, INTERNET_FLAG_HYPERLINK|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS|INTERNET_FLAG_NO_COOKIES| INTERNET_FLAG_NO_UI|INTERNET_FLAG_NO_CACHE_WRITE, (DWORD_PTR)NULL); if ((hRequest == NULL) || (!HttpSendRequestA(hRequest, NULL, 0, NULL, 0))) goto out; // Ensure that we get a text file dwSize = sizeof(dwStatus); dwStatus = 404; HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwStatus, &dwSize, NULL); if (dwStatus == 200) break; InternetCloseHandle(hRequest); hRequest = NULL; safe_strcpy(&urlpath[verpos[i]], 5, ".ver"); } if (dwStatus != 200) { vuprintf("Could not find a %s version file on server %s", channel[k], server_url); if ((releases_only) || (k+1 >= ARRAYSIZE(channel))) goto out; continue; } vuprintf("Found match for %s on server %s", urlpath, server_url); dwSize = sizeof(mime); HttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_TYPE, (LPVOID)&mime, &dwSize, NULL); if (strcmp(mime, "text/plain") != 0) goto out; // We also get a date from Apache, which we'll use to avoid out of sync check, // in case some set their clock way into the future and back. // On the other hand, if local clock is set way back in the past, we will never check. dwSize = sizeof(ServerTime); // If we can't get a date we can trust, don't bother... if ( (!HttpQueryInfoA(hRequest, HTTP_QUERY_DATE|HTTP_QUERY_FLAG_SYSTEMTIME, (LPVOID)&ServerTime, &dwSize, NULL)) || (!SystemTimeToFileTime(&ServerTime, &FileTime)) ) goto out; server_time = ((((int64_t)FileTime.dwHighDateTime)<<32) + FileTime.dwLowDateTime) / 10000000; vvuprintf("Server time: %" PRId64 "\n", server_time); // Always store the server response time - the only clock we trust! WriteRegistryKey64(REGKEY_HKCU, REGKEY_LAST_UPDATE, server_time); // Might as well let the user know if (!force_update_check) { if ((local_time > server_time + 600) || (local_time < server_time - 600)) { uprintf("IMPORTANT: Your local clock is more than 10 minutes in the %s. Unless you fix this, " APPLICATION_NAME " may not be able to check for updates...", (local_time > server_time + 600)?"future":"past"); } } dwSize = sizeof(dwTotalSize); if (!HttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwTotalSize, &dwSize, NULL)) goto out; safe_free(buf); // Make sure the file is NUL terminated buf = (char*)calloc(dwTotalSize+1, 1); if (buf == NULL) goto out; // This is a version file - we should be able to gulp it down in one go if (!InternetReadFile(hRequest, buf, dwTotalSize, &dwDownloaded) || (dwDownloaded != dwTotalSize)) goto out; status++; vuprintf("Successfully downloaded version file (%d bytes)\n", dwTotalSize); parse_update(buf, dwTotalSize+1); vuprintf("UPDATE DATA:\n"); vuprintf(" version: %d.%d.%d.%d (%s)\n", update.version[0], update.version[1], update.version[2], update.version[3], channel[k]); vuprintf(" platform_min: %d.%d\n", update.platform_min[0], update.platform_min[1]); vuprintf(" url: %s\n", update.download_url); found_new_version = ((to_uint64_t(update.version) > to_uint64_t(rufus_version)) || (force_update)) && ( (os_version.dwMajorVersion > update.platform_min[0]) || ( (os_version.dwMajorVersion == update.platform_min[0]) && (os_version.dwMinorVersion >= update.platform_min[1])) ); uprintf("N%sew %s version found%c\n", found_new_version?"":"o n", channel[k], found_new_version?'!':'.'); } out: safe_free(buf); if (hRequest) InternetCloseHandle(hRequest); if (hConnection) InternetCloseHandle(hConnection); if (hSession) InternetCloseHandle(hSession); switch(status) { case 1: PrintStatus(3000, TRUE, MSG_244); break; case 2: PrintStatus(3000, TRUE, MSG_245); break; case 3: case 4: PrintStatus(3000, FALSE, found_new_version?MSG_246:MSG_247); default: break; } // Start the new download after cleanup if (found_new_version) { // User may have started an operation while we were checking while ((!force_update_check) && (iso_op_in_progress || format_op_in_progress || (dialog_showing>0))) { Sleep(15000); } DownloadNewVersion(); } force_update_check = FALSE; update_check_in_progress = FALSE; ExitThread(0); }