BOOL DownloadWebPagePostA(std::string& page, HINTERNET hInternet, LPCSTR url, LPCSTR postData) { TRACEST(_T("DownloadWebPagePostA"), CA2CT(url)); BOOL bRet = FALSE; URL_COMPONENTSA comp; memset(&comp, 0, sizeof(URL_COMPONENTSA)); comp.dwStructSize = sizeof(URL_COMPONENTSA); CHAR hostName[100], URI[100]; comp.dwHostNameLength = comp.dwUrlPathLength = 100; comp.lpszHostName = hostName; comp.lpszUrlPath = URI; if (InternetCrackUrlA(url, 0, ICU_ESCAPE, &comp)) { HINTERNET hConnection = InternetConnectA(hInternet, comp.lpszHostName, comp.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, INTERNET_FLAG_KEEP_CONNECTION, 0); if (hConnection) { LPCSTR sAcceptTypes[] = {"*/*",NULL}; HINTERNET hRequest=::HttpOpenRequestA(hConnection, "POST", // HTTP Verb comp.lpszUrlPath, // Object Name HTTP_VERSIONA, // Version NULL, // Reference sAcceptTypes, // Accept Type INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_FORMS_SUBMIT, 0); // context call-back point if(hRequest) { static LPCSTR sHttpAccept = "Accept: */*\r\n"; ::HttpAddRequestHeadersA(hRequest, sHttpAccept, (DWORD)strlen(sHttpAccept), HTTP_ADDREQ_FLAG_ADD_IF_NEW); static LPCSTR szContentType = "Content-Type: application/x-www-form-urlencoded\r\n"; if(::HttpSendRequestA(hRequest, szContentType, (DWORD)strlen(szContentType), (LPVOID)postData, (DWORD)strlen(postData))) bRet = ReadInternetFile2StringA(hRequest, page); else HandleInternetError(_T("DownloadWebPagePostA. HttpSendRequestA")); InternetCloseHandle(hRequest); } else HandleInternetError(_T("DownloadWebPagePostA. HttpOpenRequestA")); InternetCloseHandle(hConnection); } else HandleInternetError(_T("DownloadWebPagePostA. InternetConnectA")); } else HandleInternetError(_T("DownloadWebPagePostA. InternetCrackUrlA")); return bRet; }
bstr_t CCommonUtils::GetUrlHostName(LPCSTR lpURL) { bstr_t lpRet = L""; URL_COMPONENTSA urlComponents = {0}; urlComponents.dwStructSize = sizeof(urlComponents); urlComponents.lpszHostName = (LPSTR)malloc(strlen(lpURL)+1); urlComponents.dwHostNameLength = strlen(lpURL)+1; if(InternetCrackUrlA(lpURL, 0, 0, &urlComponents)) { lpRet = urlComponents.lpszHostName; } free(urlComponents.lpszHostName); return lpRet; }
static void InternetCrackUrl_test(void) { URL_COMPONENTSA urlSrc, urlComponents; char protocol[32], hostName[1024], userName[1024]; char password[1024], extra[1024], path[1024]; BOOL ret, firstret; DWORD GLE, firstGLE; ZeroMemory(&urlSrc, sizeof(urlSrc)); urlSrc.dwStructSize = sizeof(urlSrc); urlSrc.lpszScheme = protocol; urlSrc.lpszHostName = hostName; urlSrc.lpszUserName = userName; urlSrc.lpszPassword = password; urlSrc.lpszUrlPath = path; urlSrc.lpszExtraInfo = extra; /* Tests for lpsz* members pointing to real strings while * some corresponding length members are set to zero. * As of IE7 (wininet 7.0*?) all members are checked. So we * run the first test and expect the outcome to be the same * for the first four (scheme, hostname, username and password). * The last two (path and extrainfo) are the same for all versions * of the wininet.dll. */ copy_compsA(&urlSrc, &urlComponents, 0, 1024, 1024, 1024, 2048, 1024); SetLastError(0xdeadbeef); firstret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents); firstGLE = GetLastError(); copy_compsA(&urlSrc, &urlComponents, 32, 0, 1024, 1024, 2048, 1024); SetLastError(0xdeadbeef); ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents); GLE = GetLastError(); ok(ret==firstret && (GLE==firstGLE), "InternetCrackUrl returned %d with GLE=%d (expected to return %d)\n", ret, GetLastError(), firstret); copy_compsA(&urlSrc, &urlComponents, 32, 1024, 0, 1024, 2048, 1024); SetLastError(0xdeadbeef); ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents); GLE = GetLastError(); ok(ret==firstret && (GLE==firstGLE), "InternetCrackUrl returned %d with GLE=%d (expected to return %d)\n", ret, GetLastError(), firstret); copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 0, 2048, 1024); SetLastError(0xdeadbeef); ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents); GLE = GetLastError(); ok(ret==firstret && (GLE==firstGLE), "InternetCrackUrl returned %d with GLE=%d (expected to return %d)\n", ret, GetLastError(), firstret); copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 0, 1024); SetLastError(0xdeadbeef); ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents); GLE = GetLastError(); todo_wine ok(ret==0 && (GLE==ERROR_INVALID_HANDLE || GLE==ERROR_INSUFFICIENT_BUFFER), "InternetCrackUrl returned %d with GLE=%d (expected to return 0 and ERROR_INVALID_HANDLE or ERROR_INSUFFICIENT_BUFFER)\n", ret, GLE); copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 0); SetLastError(0xdeadbeef); ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents); GLE = GetLastError(); todo_wine ok(ret==0 && (GLE==ERROR_INVALID_HANDLE || GLE==ERROR_INSUFFICIENT_BUFFER), "InternetCrackUrl returned %d with GLE=%d (expected to return 0 and ERROR_INVALID_HANDLE or ERROR_INSUFFICIENT_BUFFER)\n", ret, GLE); copy_compsA(&urlSrc, &urlComponents, 0, 0, 0, 0, 0, 0); ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents); GLE = GetLastError(); todo_wine ok(ret==0 && GLE==ERROR_INVALID_PARAMETER, "InternetCrackUrl returned %d with GLE=%d (expected to return 0 and ERROR_INVALID_PARAMETER)\n", ret, GLE); copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024); ret = InternetCrackUrl("about://host/blank", 0,0,&urlComponents); ok(ret, "InternetCrackUrl failed with %d\n", GetLastError()); ok(!strcmp(urlComponents.lpszScheme, "about"), "lpszScheme was \"%s\" instead of \"about\"\n", urlComponents.lpszScheme); ok(!strcmp(urlComponents.lpszHostName, "host"), "lpszHostName was \"%s\" instead of \"host\"\n", urlComponents.lpszHostName); ok(!strcmp(urlComponents.lpszUrlPath, "/blank"), "lpszUrlPath was \"%s\" instead of \"/blank\"\n", urlComponents.lpszUrlPath); /* try a NULL lpszUrl */ SetLastError(0xdeadbeef); copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024); ret = InternetCrackUrl(NULL, 0, 0, &urlComponents); GLE = GetLastError(); ok(ret == FALSE, "Expected InternetCrackUrl to fail\n"); ok(GLE == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GLE); /* try an empty lpszUrl, GetLastError returns 12006, whatever that means * we just need to fail and not return success */ SetLastError(0xdeadbeef); copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024); ret = InternetCrackUrl("", 0, 0, &urlComponents); GLE = GetLastError(); ok(ret == FALSE, "Expected InternetCrackUrl to fail\n"); ok(GLE != 0xdeadbeef && GLE != ERROR_SUCCESS, "Expected GLE to represent a failure\n"); /* Invalid Call: must set size of components structure (Windows only * enforces this on the InternetCrackUrlA version of the call) */ copy_compsA(&urlSrc, &urlComponents, 0, 1024, 1024, 1024, 2048, 1024); SetLastError(0xdeadbeef); urlComponents.dwStructSize = 0; ret = InternetCrackUrlA(TEST_URL, 0, 0, &urlComponents); ok(ret == FALSE, "Expected InternetCrackUrl to fail\n"); ok(GLE != 0xdeadbeef && GLE != ERROR_SUCCESS, "Expected GLE to represent a failure\n"); /* Invalid Call: size of dwStructSize must be one of the "standard" sizes * of the URL_COMPONENTS structure (Windows only enforces this on the * InternetCrackUrlA version of the call) */ copy_compsA(&urlSrc, &urlComponents, 0, 1024, 1024, 1024, 2048, 1024); SetLastError(0xdeadbeef); urlComponents.dwStructSize = sizeof(urlComponents) + 1; ret = InternetCrackUrlA(TEST_URL, 0, 0, &urlComponents); ok(ret == FALSE, "Expected InternetCrackUrl to fail\n"); ok(GLE != 0xdeadbeef && GLE != ERROR_SUCCESS, "Expected GLE to represent a failure\n"); }
static void test_crack_url(const crack_url_test_t *test) { WCHAR buf[INTERNET_MAX_URL_LENGTH]; URL_COMPONENTSW urlw; URL_COMPONENTSA url; BOOL b; zero_compsA(&url, 1, 1, 1, 1, 1, 1); b = InternetCrackUrlA(test->url, strlen(test->url), 0, &url); ok(b, "InternetCrackUrl failed with error %d\n", GetLastError()); if(test->scheme_off == -1) ok(!url.lpszScheme, "[%s] url.lpszScheme = %p, expected NULL\n", test->url, url.lpszScheme); else ok(url.lpszScheme == test->url+test->scheme_off, "[%s] url.lpszScheme = %p, expected %p\n", test->url, url.lpszScheme, test->url+test->scheme_off); ok(url.dwSchemeLength == test->scheme_len, "[%s] url.lpszSchemeLength = %d, expected %d\n", test->url, url.dwSchemeLength, test->scheme_len); ok(url.nScheme == test->scheme, "[%s] url.nScheme = %d, expected %d\n", test->url, url.nScheme, test->scheme); if(test->host_off == -1) ok(!url.lpszHostName, "[%s] url.lpszHostName = %p, expected NULL\n", test->url, url.lpszHostName); else ok(url.lpszHostName == test->url+test->host_off, "[%s] url.lpszHostName = %p, expected %p\n", test->url, url.lpszHostName, test->url+test->host_off); if(test->host_skip_broken != -1 && url.dwHostNameLength == test->host_skip_broken) { win_skip("skipping broken dwHostNameLength result\n"); return; } ok(url.dwHostNameLength == test->host_len, "[%s] url.lpszHostNameLength = %d, expected %d\n", test->url, url.dwHostNameLength, test->host_len); ok(url.nPort == test->port, "[%s] nPort = %d, expected %d\n", test->url, url.nPort, test->port); if(test->user_off == -1) ok(!url.lpszUserName, "[%s] url.lpszUserName = %p\n", test->url, url.lpszUserName); else ok(url.lpszUserName == test->url+test->user_off, "[%s] url.lpszUserName = %p, expected %p\n", test->url, url.lpszUserName, test->url+test->user_off); ok(url.dwUserNameLength == test->user_len, "[%s] url.lpszUserNameLength = %d, expected %d\n", test->url, url.dwUserNameLength, test->user_len); if(test->pass_off == -1) ok(!url.lpszPassword, "[%s] url.lpszPassword = %p\n", test->url, url.lpszPassword); else ok(url.lpszPassword == test->url+test->pass_off, "[%s] url.lpszPassword = %p, expected %p\n", test->url, url.lpszPassword, test->url+test->pass_off); ok(url.dwPasswordLength == test->pass_len, "[%s] url.lpszPasswordLength = %d, expected %d\n", test->url, url.dwPasswordLength, test->pass_len); if(test->path_off == -1) ok(!url.lpszUrlPath, "[%s] url.lpszPath = %p, expected NULL\n", test->url, url.lpszUrlPath); else ok(url.lpszUrlPath == test->url+test->path_off, "[%s] url.lpszPath = %p, expected %p\n", test->url, url.lpszUrlPath, test->url+test->path_off); ok(url.dwUrlPathLength == test->path_len, "[%s] url.lpszUrlPathLength = %d, expected %d\n", test->url, url.dwUrlPathLength, test->path_len); if(test->extra_off == -1) ok(!url.lpszExtraInfo, "[%s] url.lpszExtraInfo = %p, expected NULL\n", test->url, url.lpszExtraInfo); else ok(url.lpszExtraInfo == test->url+test->extra_off, "[%s] url.lpszExtraInfo = %p, expected %p\n", test->url, url.lpszExtraInfo, test->url+test->extra_off); ok(url.dwExtraInfoLength == test->extra_len, "[%s] url.lpszExtraInfoLength = %d, expected %d\n", test->url, url.dwExtraInfoLength, test->extra_len); memset(&urlw, 0, sizeof(URL_COMPONENTSW)); urlw.dwStructSize = sizeof(URL_COMPONENTSW); urlw.dwSchemeLength = 1; urlw.dwHostNameLength = 1; urlw.dwUserNameLength = 1; urlw.dwPasswordLength = 1; urlw.dwUrlPathLength = 1; urlw.dwExtraInfoLength = 1; MultiByteToWideChar(CP_ACP, 0, test->url, -1, buf, sizeof(buf)/sizeof(buf[0])); b = InternetCrackUrlW(buf, lstrlenW(buf), 0, &urlw); if(!b && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { win_skip("InternetCrackUrlW is not implemented\n"); return; } ok(b, "InternetCrackUrl failed with error %d\n", GetLastError()); if(test->scheme_off == -1) ok(!urlw.lpszScheme, "[%s] urlw.lpszScheme = %p, expected NULL\n", test->url, urlw.lpszScheme); else ok(urlw.lpszScheme == buf+test->scheme_off, "[%s] urlw.lpszScheme = %p, expected %p\n", test->url, urlw.lpszScheme, buf+test->scheme_off); ok(urlw.dwSchemeLength == test->scheme_len, "[%s] urlw.lpszSchemeLength = %d, expected %d\n", test->url, urlw.dwSchemeLength, test->scheme_len); ok(urlw.nScheme == test->scheme, "[%s] urlw.nScheme = %d, expected %d\n", test->url, urlw.nScheme, test->scheme); if(test->host_off == -1) { ok(!urlw.lpszHostName, "[%s] urlw.lpszHostName = %p, expected NULL\n", test->url, urlw.lpszHostName); ok(urlw.dwHostNameLength == 0 || broken(urlw.dwHostNameLength == 1), "[%s] urlw.lpszHostNameLength = %d, expected %d\n", test->url, urlw.dwHostNameLength, test->host_len); }else { ok(urlw.lpszHostName == buf+test->host_off, "[%s] urlw.lpszHostName = %p, expected %p\n", test->url, urlw.lpszHostName, test->url+test->host_off); ok(urlw.dwHostNameLength == test->host_len, "[%s] urlw.lpszHostNameLength = %d, expected %d\n", test->url, urlw.dwHostNameLength, test->host_len); } ok(urlw.nPort == test->port, "[%s] nPort = %d, expected %d\n", test->url, urlw.nPort, test->port); if(test->user_off == -1) { ok(!urlw.lpszUserName, "[%s] urlw.lpszUserName = %p\n", test->url, urlw.lpszUserName); ok(urlw.dwUserNameLength == 0 || broken(urlw.dwUserNameLength == 1), "[%s] urlw.lpszUserNameLength = %d, expected %d\n", test->url, urlw.dwUserNameLength, test->user_len); }else { ok(urlw.lpszUserName == buf+test->user_off, "[%s] urlw.lpszUserName = %p, expected %p\n", test->url, urlw.lpszUserName, buf+test->user_off); ok(urlw.dwUserNameLength == test->user_len, "[%s] urlw.lpszUserNameLength = %d, expected %d\n", test->url, urlw.dwUserNameLength, test->user_len); } if(test->pass_off == -1) { ok(!urlw.lpszPassword, "[%s] urlw.lpszPassword = %p\n", test->url, urlw.lpszPassword); ok(urlw.dwPasswordLength == 0 || broken(urlw.dwPasswordLength), "[%s] urlw.lpszPasswordLength = %d, expected %d\n", test->url, urlw.dwPasswordLength, test->pass_len); }else { ok(urlw.lpszPassword == buf+test->pass_off, "[%s] urlw.lpszPassword = %p, expected %p\n", test->url, urlw.lpszPassword, buf+test->pass_off); ok(urlw.dwPasswordLength == test->pass_len, "[%s] urlw.lpszPasswordLength = %d, expected %d\n", test->url, urlw.dwPasswordLength, test->pass_len); } if(test->path_off == -1) ok(!urlw.lpszUrlPath, "[%s] urlw.lpszPath = %p, expected NULL\n", test->url, urlw.lpszUrlPath); else ok(urlw.lpszUrlPath == buf+test->path_off, "[%s] urlw.lpszPath = %p, expected %p\n", test->url, urlw.lpszUrlPath, buf+test->path_off); ok(urlw.dwUrlPathLength == test->path_len, "[%s] urlw.lpszUrlPathLength = %d, expected %d\n", test->url, urlw.dwUrlPathLength, test->path_len); if(test->extra_off == -1) { ok(!urlw.lpszExtraInfo, "[%s] url.lpszExtraInfo = %p, expected NULL\n", test->url, urlw.lpszExtraInfo); ok(urlw.dwExtraInfoLength == 0 || broken(urlw.dwExtraInfoLength == 1), "[%s] urlw.lpszExtraInfoLength = %d, expected %d\n", test->url, urlw.dwExtraInfoLength, test->extra_len); }else { ok(urlw.lpszExtraInfo == buf+test->extra_off, "[%s] urlw.lpszExtraInfo = %p, expected %p\n", test->url, urlw.lpszExtraInfo, buf+test->extra_off); ok(urlw.dwExtraInfoLength == test->extra_len, "[%s] urlw.lpszExtraInfoLength = %d, expected %d\n", test->url, urlw.dwExtraInfoLength, test->extra_len); } }
/* * 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; }
/* gsoap documentation: Called from a client proxy to open a connection to a Web Service located at endpoint. Input parameters host and port are micro-parsed from endpoint. Should return a valid file descriptor, or SOAP_INVALID_SOCKET and soap->error set to an error code. Built-in gSOAP function: tcp_connect */ static SOAP_SOCKET wininet_connect( struct soap * soap, const char * a_pszEndpoint, const char * a_pszHost, int a_nPort ) { URL_COMPONENTSA urlComponents; char szUrlPath[MAX_PATH]; char szHost[MAX_PATH]; DWORD dwFlags; HINTERNET hConnection = NULL; HINTERNET hHttpRequest = NULL; struct wininet_data * pData = (struct wininet_data *) soap_lookup_plugin( soap, wininet_id ); soap->error = SOAP_OK; /* we parse the URL ourselves so we don't use these parameters */ UNUSED_ARG( a_pszHost ); UNUSED_ARG( a_nPort ); DBGLOG(TEST, SOAP_MESSAGE(fdebug, "wininet %p: connect, endpoint = '%s'\n", soap, a_pszEndpoint )); /* we should be initialized but not connected */ _ASSERTE( pData->hInternet ); _ASSERTE( !pData->hConnection ); _ASSERTE( soap->socket == SOAP_INVALID_SOCKET ); /* parse out the url path */ memset( &urlComponents, 0, sizeof(urlComponents) ); urlComponents.dwStructSize = sizeof(urlComponents); urlComponents.lpszHostName = szHost; urlComponents.dwHostNameLength = MAX_PATH; urlComponents.lpszUrlPath = szUrlPath; urlComponents.dwUrlPathLength = MAX_PATH; if ( !InternetCrackUrlA( a_pszEndpoint, 0, 0, &urlComponents ) ) { InternetCloseHandle( hConnection ); soap->error = GetLastError(); DBGLOG(TEST, SOAP_MESSAGE(fdebug, "wininet %p: connect, error %d (%s) in InternetCrackUrl\n", soap, soap->error, wininet_error_message(soap,soap->error) )); return SOAP_INVALID_SOCKET; } /* connect to the target url, if we haven't connected yet or if it was dropped */ hConnection = InternetConnectA( pData->hInternet, szHost, urlComponents.nPort, "", "", INTERNET_SERVICE_HTTP, 0, (DWORD_PTR) soap ); if ( !hConnection ) { soap->error = GetLastError(); DBGLOG(TEST, SOAP_MESSAGE(fdebug, "wininet %p: connect, error %d (%s) in InternetConnect\n", soap, soap->error, wininet_error_message(soap,soap->error) )); return SOAP_INVALID_SOCKET; } /* Note that although we specify HTTP/1.1 for the connection here, the actual connection may be HTTP/1.0 depending on the settings in the control panel. See the "Internet Options", "HTTP 1.1 settings". */ dwFlags = pData->dwRequestFlags; if ( soap->omode & SOAP_IO_KEEPALIVE ) { dwFlags |= INTERNET_FLAG_KEEP_CONNECTION; } if ( urlComponents.nScheme == INTERNET_SCHEME_HTTPS ) { dwFlags |= INTERNET_FLAG_SECURE; } hHttpRequest = HttpOpenRequestA( hConnection, "POST", szUrlPath, "HTTP/1.1", NULL, NULL, dwFlags, (DWORD_PTR) soap ); if ( !hHttpRequest ) { InternetCloseHandle( hConnection ); soap->error = GetLastError(); DBGLOG(TEST, SOAP_MESSAGE(fdebug, "wininet %p: connect, error %d (%s) in HttpOpenRequest\n", soap, soap->error, wininet_error_message(soap,soap->error) )); return SOAP_INVALID_SOCKET; } /* save the connection handle in our data structure */ pData->hConnection = hConnection; /* return the http request handle as our file descriptor. */ _ASSERTE( sizeof(soap->socket) >= sizeof(HINTERNET) ); return (SOAP_SOCKET) hHttpRequest; }
/* * 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; }
static void InternetCrackUrl_test(void) { URL_COMPONENTSA urlSrc, urlComponents; char protocol[32], hostName[1024], userName[1024]; char password[1024], extra[1024], path[1024]; BOOL ret, firstret; DWORD GLE, firstGLE; ZeroMemory(&urlSrc, sizeof(urlSrc)); urlSrc.dwStructSize = sizeof(urlSrc); urlSrc.lpszScheme = protocol; urlSrc.lpszHostName = hostName; urlSrc.lpszUserName = userName; urlSrc.lpszPassword = password; urlSrc.lpszUrlPath = path; urlSrc.lpszExtraInfo = extra; copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024); ret = InternetCrackUrl(TEST_URL, 0,0,&urlComponents); ok( ret, "InternetCrackUrl failed, error %d\n",GetLastError()); ok((strcmp(TEST_URL_PATH,path) == 0),"path cracked wrong\n"); /* Bug 1805: Confirm the returned lengths are correct: */ /* 1. When extra info split out explicitly */ zero_compsA(&urlComponents, 0, 1, 0, 0, 1, 1); ok(InternetCrackUrlA(TEST_URL2, 0, 0, &urlComponents),"InternetCrackUrl failed, error %d\n", GetLastError()); ok(urlComponents.dwUrlPathLength == strlen(TEST_URL2_PATH),".dwUrlPathLength should be %d, but is %d\n", (DWORD)strlen(TEST_URL2_PATH), urlComponents.dwUrlPathLength); ok(!strncmp(urlComponents.lpszUrlPath,TEST_URL2_PATH,strlen(TEST_URL2_PATH)),"lpszUrlPath should be %s but is %s\n", TEST_URL2_PATH, urlComponents.lpszUrlPath); ok(urlComponents.dwHostNameLength == strlen(TEST_URL2_SERVER),".dwHostNameLength should be %d, but is %d\n", (DWORD)strlen(TEST_URL2_SERVER), urlComponents.dwHostNameLength); ok(!strncmp(urlComponents.lpszHostName,TEST_URL2_SERVER,strlen(TEST_URL2_SERVER)),"lpszHostName should be %s but is %s\n", TEST_URL2_SERVER, urlComponents.lpszHostName); ok(urlComponents.dwExtraInfoLength == strlen(TEST_URL2_EXTRA),".dwExtraInfoLength should be %d, but is %d\n", (DWORD)strlen(TEST_URL2_EXTRA), urlComponents.dwExtraInfoLength); ok(!strncmp(urlComponents.lpszExtraInfo,TEST_URL2_EXTRA,strlen(TEST_URL2_EXTRA)),"lpszExtraInfo should be %s but is %s\n", TEST_URL2_EXTRA, urlComponents.lpszHostName); /* 2. When extra info is not split out explicitly and is in url path */ zero_compsA(&urlComponents, 0, 1, 0, 0, 1, 0); ok(InternetCrackUrlA(TEST_URL2, 0, 0, &urlComponents),"InternetCrackUrl failed with GLE %d\n",GetLastError()); ok(urlComponents.dwUrlPathLength == strlen(TEST_URL2_PATHEXTRA),".dwUrlPathLength should be %d, but is %d\n", (DWORD)strlen(TEST_URL2_PATHEXTRA), urlComponents.dwUrlPathLength); ok(!strncmp(urlComponents.lpszUrlPath,TEST_URL2_PATHEXTRA,strlen(TEST_URL2_PATHEXTRA)),"lpszUrlPath should be %s but is %s\n", TEST_URL2_PATHEXTRA, urlComponents.lpszUrlPath); ok(urlComponents.dwHostNameLength == strlen(TEST_URL2_SERVER),".dwHostNameLength should be %d, but is %d\n", (DWORD)strlen(TEST_URL2_SERVER), urlComponents.dwHostNameLength); ok(!strncmp(urlComponents.lpszHostName,TEST_URL2_SERVER,strlen(TEST_URL2_SERVER)),"lpszHostName should be %s but is %s\n", TEST_URL2_SERVER, urlComponents.lpszHostName); ok(urlComponents.nPort == INTERNET_DEFAULT_HTTP_PORT,"urlComponents->nPort should have been 80 instead of %d\n", urlComponents.nPort); ok(urlComponents.nScheme == INTERNET_SCHEME_HTTP,"urlComponents->nScheme should have been INTERNET_SCHEME_HTTP instead of %d\n", urlComponents.nScheme); zero_compsA(&urlComponents, 1, 1, 1, 1, 1, 1); ok(InternetCrackUrlA(TEST_URL, strlen(TEST_URL), 0, &urlComponents),"InternetCrackUrl failed with GLE %d\n",GetLastError()); ok(urlComponents.dwUrlPathLength == strlen(TEST_URL_PATH),".dwUrlPathLength should be %d, but is %d\n", lstrlenA(TEST_URL_PATH), urlComponents.dwUrlPathLength); ok(!strncmp(urlComponents.lpszUrlPath,TEST_URL_PATH,strlen(TEST_URL_PATH)),"lpszUrlPath should be %s but is %s\n", TEST_URL_PATH, urlComponents.lpszUrlPath); ok(urlComponents.dwHostNameLength == strlen(TEST_URL_HOST),".dwHostNameLength should be %d, but is %d\n", lstrlenA(TEST_URL_HOST), urlComponents.dwHostNameLength); ok(!strncmp(urlComponents.lpszHostName,TEST_URL_HOST,strlen(TEST_URL_HOST)),"lpszHostName should be %s but is %s\n", TEST_URL_HOST, urlComponents.lpszHostName); ok(urlComponents.nPort == INTERNET_DEFAULT_HTTP_PORT,"urlComponents->nPort should have been 80 instead of %d\n", urlComponents.nPort); ok(urlComponents.nScheme == INTERNET_SCHEME_HTTP,"urlComponents->nScheme should have been INTERNET_SCHEME_HTTP instead of %d\n", urlComponents.nScheme); ok(!urlComponents.lpszUserName, ".lpszUserName should have been set to NULL\n"); ok(!urlComponents.lpszPassword, ".lpszPassword should have been set to NULL\n"); ok(!urlComponents.lpszExtraInfo, ".lpszExtraInfo should have been set to NULL\n"); ok(!urlComponents.dwUserNameLength,".dwUserNameLength should be 0, but is %d\n", urlComponents.dwUserNameLength); ok(!urlComponents.dwPasswordLength,".dwPasswordLength should be 0, but is %d\n", urlComponents.dwPasswordLength); ok(!urlComponents.dwExtraInfoLength,".dwExtraInfoLength should be 0, but is %d\n", urlComponents.dwExtraInfoLength); /*3. Check for %20 */ copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024); ok(InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents),"InternetCrackUrl failed with GLE %d\n",GetLastError()); /* Tests for lpsz* members pointing to real strings while * some corresponding length members are set to zero. * As of IE7 (wininet 7.0*?) all members are checked. So we * run the first test and expect the outcome to be the same * for the first four (scheme, hostname, username and password). * The last two (path and extrainfo) are the same for all versions * of the wininet.dll. */ copy_compsA(&urlSrc, &urlComponents, 0, 1024, 1024, 1024, 2048, 1024); SetLastError(0xdeadbeef); firstret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents); firstGLE = GetLastError(); copy_compsA(&urlSrc, &urlComponents, 32, 0, 1024, 1024, 2048, 1024); SetLastError(0xdeadbeef); ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents); GLE = GetLastError(); ok(ret==firstret && (GLE==firstGLE), "InternetCrackUrl returned %d with GLE=%d (expected to return %d)\n", ret, GetLastError(), firstret); copy_compsA(&urlSrc, &urlComponents, 32, 1024, 0, 1024, 2048, 1024); SetLastError(0xdeadbeef); ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents); GLE = GetLastError(); ok(ret==firstret && (GLE==firstGLE), "InternetCrackUrl returned %d with GLE=%d (expected to return %d)\n", ret, GetLastError(), firstret); copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 0, 2048, 1024); SetLastError(0xdeadbeef); ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents); GLE = GetLastError(); ok(ret==firstret && (GLE==firstGLE), "InternetCrackUrl returned %d with GLE=%d (expected to return %d)\n", ret, GetLastError(), firstret); copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 0, 1024); SetLastError(0xdeadbeef); ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents); GLE = GetLastError(); todo_wine ok(ret==0 && (GLE==ERROR_INVALID_HANDLE || GLE==ERROR_INSUFFICIENT_BUFFER), "InternetCrackUrl returned %d with GLE=%d (expected to return 0 and ERROR_INVALID_HANDLE or ERROR_INSUFFICIENT_BUFFER)\n", ret, GLE); copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 0); SetLastError(0xdeadbeef); ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents); GLE = GetLastError(); todo_wine ok(ret==0 && (GLE==ERROR_INVALID_HANDLE || GLE==ERROR_INSUFFICIENT_BUFFER), "InternetCrackUrl returned %d with GLE=%d (expected to return 0 and ERROR_INVALID_HANDLE or ERROR_INSUFFICIENT_BUFFER)\n", ret, GLE); copy_compsA(&urlSrc, &urlComponents, 0, 0, 0, 0, 0, 0); ret = InternetCrackUrlA(TEST_URL3, 0, ICU_DECODE, &urlComponents); GLE = GetLastError(); todo_wine ok(ret==0 && GLE==ERROR_INVALID_PARAMETER, "InternetCrackUrl returned %d with GLE=%d (expected to return 0 and ERROR_INVALID_PARAMETER)\n", ret, GLE); copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024); ret = InternetCrackUrl("about://host/blank", 0,0,&urlComponents); ok(ret, "InternetCrackUrl failed with %d\n", GetLastError()); ok(!strcmp(urlComponents.lpszScheme, "about"), "lpszScheme was \"%s\" instead of \"about\"\n", urlComponents.lpszScheme); ok(!strcmp(urlComponents.lpszHostName, "host"), "lpszHostName was \"%s\" instead of \"host\"\n", urlComponents.lpszHostName); ok(!strcmp(urlComponents.lpszUrlPath, "/blank"), "lpszUrlPath was \"%s\" instead of \"/blank\"\n", urlComponents.lpszUrlPath); /* try a NULL lpszUrl */ SetLastError(0xdeadbeef); copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024); ret = InternetCrackUrl(NULL, 0, 0, &urlComponents); GLE = GetLastError(); ok(ret == FALSE, "Expected InternetCrackUrl to fail\n"); ok(GLE == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GLE); /* try an empty lpszUrl, GetLastError returns 12006, whatever that means * we just need to fail and not return success */ SetLastError(0xdeadbeef); copy_compsA(&urlSrc, &urlComponents, 32, 1024, 1024, 1024, 2048, 1024); ret = InternetCrackUrl("", 0, 0, &urlComponents); GLE = GetLastError(); ok(ret == FALSE, "Expected InternetCrackUrl to fail\n"); ok(GLE != 0xdeadbeef && GLE != ERROR_SUCCESS, "Expected GLE to represent a failure\n"); /* Invalid Call: must set size of components structure (Windows only * enforces this on the InternetCrackUrlA version of the call) */ copy_compsA(&urlSrc, &urlComponents, 0, 1024, 1024, 1024, 2048, 1024); SetLastError(0xdeadbeef); urlComponents.dwStructSize = 0; ret = InternetCrackUrlA(TEST_URL, 0, 0, &urlComponents); ok(ret == FALSE, "Expected InternetCrackUrl to fail\n"); ok(GLE != 0xdeadbeef && GLE != ERROR_SUCCESS, "Expected GLE to represent a failure\n"); /* Invalid Call: size of dwStructSize must be one of the "standard" sizes * of the URL_COMPONENTS structure (Windows only enforces this on the * InternetCrackUrlA version of the call) */ copy_compsA(&urlSrc, &urlComponents, 0, 1024, 1024, 1024, 2048, 1024); SetLastError(0xdeadbeef); urlComponents.dwStructSize = sizeof(urlComponents) + 1; ret = InternetCrackUrlA(TEST_URL, 0, 0, &urlComponents); ok(ret == FALSE, "Expected InternetCrackUrl to fail\n"); ok(GLE != 0xdeadbeef && GLE != ERROR_SUCCESS, "Expected GLE to represent a failure\n"); }
static void test_crack_url(const crack_url_test_t *test) { WCHAR buf[INTERNET_MAX_URL_LENGTH]; URL_COMPONENTSW urlw; URL_COMPONENTSA url; char scheme[32], hostname[1024], username[1024]; char password[1024], extrainfo[1024], urlpath[1024]; BOOL b; /* test InternetCrackUrlA with NULL buffers */ zero_compsA(&url, 1, 1, 1, 1, 1, 1); b = InternetCrackUrlA(test->url, strlen(test->url), 0, &url); ok(b, "InternetCrackUrl failed with error %d\n", GetLastError()); if(test->scheme_off == -1) ok(!url.lpszScheme, "[%s] url.lpszScheme = %p, expected NULL\n", test->url, url.lpszScheme); else ok(url.lpszScheme == test->url+test->scheme_off, "[%s] url.lpszScheme = %p, expected %p\n", test->url, url.lpszScheme, test->url+test->scheme_off); ok(url.dwSchemeLength == test->scheme_len, "[%s] url.lpszSchemeLength = %d, expected %d\n", test->url, url.dwSchemeLength, test->scheme_len); ok(url.nScheme == test->scheme, "[%s] url.nScheme = %d, expected %d\n", test->url, url.nScheme, test->scheme); if(test->host_off == -1) ok(!url.lpszHostName, "[%s] url.lpszHostName = %p, expected NULL\n", test->url, url.lpszHostName); else ok(url.lpszHostName == test->url+test->host_off, "[%s] url.lpszHostName = %p, expected %p\n", test->url, url.lpszHostName, test->url+test->host_off); if(test->host_skip_broken != -1 && url.dwHostNameLength == test->host_skip_broken) { win_skip("skipping broken dwHostNameLength result\n"); return; } ok(url.dwHostNameLength == test->host_len, "[%s] url.lpszHostNameLength = %d, expected %d\n", test->url, url.dwHostNameLength, test->host_len); ok(url.nPort == test->port, "[%s] nPort = %d, expected %d\n", test->url, url.nPort, test->port); if(test->user_off == -1) ok(!url.lpszUserName, "[%s] url.lpszUserName = %p\n", test->url, url.lpszUserName); else ok(url.lpszUserName == test->url+test->user_off, "[%s] url.lpszUserName = %p, expected %p\n", test->url, url.lpszUserName, test->url+test->user_off); ok(url.dwUserNameLength == test->user_len, "[%s] url.lpszUserNameLength = %d, expected %d\n", test->url, url.dwUserNameLength, test->user_len); if(test->pass_off == -1) ok(!url.lpszPassword, "[%s] url.lpszPassword = %p\n", test->url, url.lpszPassword); else ok(url.lpszPassword == test->url+test->pass_off, "[%s] url.lpszPassword = %p, expected %p\n", test->url, url.lpszPassword, test->url+test->pass_off); ok(url.dwPasswordLength == test->pass_len, "[%s] url.lpszPasswordLength = %d, expected %d\n", test->url, url.dwPasswordLength, test->pass_len); if(test->path_off == -1) ok(!url.lpszUrlPath, "[%s] url.lpszPath = %p, expected NULL\n", test->url, url.lpszUrlPath); else ok(url.lpszUrlPath == test->url+test->path_off, "[%s] url.lpszPath = %p, expected %p\n", test->url, url.lpszUrlPath, test->url+test->path_off); ok(url.dwUrlPathLength == test->path_len, "[%s] url.lpszUrlPathLength = %d, expected %d\n", test->url, url.dwUrlPathLength, test->path_len); if(test->extra_off == -1) ok(!url.lpszExtraInfo, "[%s] url.lpszExtraInfo = %p, expected NULL\n", test->url, url.lpszExtraInfo); else ok(url.lpszExtraInfo == test->url+test->extra_off, "[%s] url.lpszExtraInfo = %p, expected %p\n", test->url, url.lpszExtraInfo, test->url+test->extra_off); ok(url.dwExtraInfoLength == test->extra_len, "[%s] url.lpszExtraInfoLength = %d, expected %d\n", test->url, url.dwExtraInfoLength, test->extra_len); /* test InternetCrackUrlW with NULL buffers */ memset(&urlw, 0, sizeof(URL_COMPONENTSW)); urlw.dwStructSize = sizeof(URL_COMPONENTSW); urlw.dwSchemeLength = 1; urlw.dwHostNameLength = 1; urlw.dwUserNameLength = 1; urlw.dwPasswordLength = 1; urlw.dwUrlPathLength = 1; urlw.dwExtraInfoLength = 1; MultiByteToWideChar(CP_ACP, 0, test->url, -1, buf, sizeof(buf)/sizeof(buf[0])); b = InternetCrackUrlW(buf, lstrlenW(buf), 0, &urlw); if(!b && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { win_skip("InternetCrackUrlW is not implemented\n"); return; } ok(b, "InternetCrackUrl failed with error %d\n", GetLastError()); if(test->scheme_off == -1) ok(!urlw.lpszScheme, "[%s] urlw.lpszScheme = %p, expected NULL\n", test->url, urlw.lpszScheme); else ok(urlw.lpszScheme == buf+test->scheme_off, "[%s] urlw.lpszScheme = %p, expected %p\n", test->url, urlw.lpszScheme, buf+test->scheme_off); ok(urlw.dwSchemeLength == test->scheme_len, "[%s] urlw.lpszSchemeLength = %d, expected %d\n", test->url, urlw.dwSchemeLength, test->scheme_len); ok(urlw.nScheme == test->scheme, "[%s] urlw.nScheme = %d, expected %d\n", test->url, urlw.nScheme, test->scheme); if(test->host_off == -1) { ok(!urlw.lpszHostName, "[%s] urlw.lpszHostName = %p, expected NULL\n", test->url, urlw.lpszHostName); ok(urlw.dwHostNameLength == 0 || broken(urlw.dwHostNameLength == 1), "[%s] urlw.lpszHostNameLength = %d, expected %d\n", test->url, urlw.dwHostNameLength, test->host_len); }else { ok(urlw.lpszHostName == buf+test->host_off, "[%s] urlw.lpszHostName = %p, expected %p\n", test->url, urlw.lpszHostName, test->url+test->host_off); ok(urlw.dwHostNameLength == test->host_len, "[%s] urlw.lpszHostNameLength = %d, expected %d\n", test->url, urlw.dwHostNameLength, test->host_len); } ok(urlw.nPort == test->port, "[%s] nPort = %d, expected %d\n", test->url, urlw.nPort, test->port); if(test->user_off == -1) { ok(!urlw.lpszUserName, "[%s] urlw.lpszUserName = %p\n", test->url, urlw.lpszUserName); ok(urlw.dwUserNameLength == 0 || broken(urlw.dwUserNameLength == 1), "[%s] urlw.lpszUserNameLength = %d, expected %d\n", test->url, urlw.dwUserNameLength, test->user_len); }else { ok(urlw.lpszUserName == buf+test->user_off, "[%s] urlw.lpszUserName = %p, expected %p\n", test->url, urlw.lpszUserName, buf+test->user_off); ok(urlw.dwUserNameLength == test->user_len, "[%s] urlw.lpszUserNameLength = %d, expected %d\n", test->url, urlw.dwUserNameLength, test->user_len); } if(test->pass_off == -1) { ok(!urlw.lpszPassword, "[%s] urlw.lpszPassword = %p\n", test->url, urlw.lpszPassword); ok(urlw.dwPasswordLength == 0 || broken(urlw.dwPasswordLength), "[%s] urlw.lpszPasswordLength = %d, expected %d\n", test->url, urlw.dwPasswordLength, test->pass_len); }else { ok(urlw.lpszPassword == buf+test->pass_off, "[%s] urlw.lpszPassword = %p, expected %p\n", test->url, urlw.lpszPassword, buf+test->pass_off); ok(urlw.dwPasswordLength == test->pass_len, "[%s] urlw.lpszPasswordLength = %d, expected %d\n", test->url, urlw.dwPasswordLength, test->pass_len); } if(test->path_off == -1) ok(!urlw.lpszUrlPath, "[%s] urlw.lpszPath = %p, expected NULL\n", test->url, urlw.lpszUrlPath); else ok(urlw.lpszUrlPath == buf+test->path_off, "[%s] urlw.lpszPath = %p, expected %p\n", test->url, urlw.lpszUrlPath, buf+test->path_off); ok(urlw.dwUrlPathLength == test->path_len, "[%s] urlw.lpszUrlPathLength = %d, expected %d\n", test->url, urlw.dwUrlPathLength, test->path_len); if(test->extra_off == -1) { ok(!urlw.lpszExtraInfo, "[%s] url.lpszExtraInfo = %p, expected NULL\n", test->url, urlw.lpszExtraInfo); ok(urlw.dwExtraInfoLength == 0 || broken(urlw.dwExtraInfoLength == 1), "[%s] urlw.lpszExtraInfoLength = %d, expected %d\n", test->url, urlw.dwExtraInfoLength, test->extra_len); }else { ok(urlw.lpszExtraInfo == buf+test->extra_off, "[%s] urlw.lpszExtraInfo = %p, expected %p\n", test->url, urlw.lpszExtraInfo, buf+test->extra_off); ok(urlw.dwExtraInfoLength == test->extra_len, "[%s] urlw.lpszExtraInfoLength = %d, expected %d\n", test->url, urlw.dwExtraInfoLength, test->extra_len); } /* test InternetCrackUrlA with valid buffers */ memset(&url, 0, sizeof(URL_COMPONENTSA)); url.dwStructSize = sizeof(URL_COMPONENTSA); url.lpszScheme = scheme; url.dwSchemeLength = sizeof(scheme); url.lpszHostName = hostname; url.dwHostNameLength = sizeof(hostname); url.lpszUserName = username; url.dwUserNameLength = sizeof(username); url.lpszPassword = password; url.dwPasswordLength = sizeof(password); url.lpszUrlPath = urlpath; url.dwUrlPathLength = sizeof(urlpath); url.lpszExtraInfo = extrainfo; url.dwExtraInfoLength = sizeof(extrainfo); b = InternetCrackUrlA(test->url, strlen(test->url), 0, &url); ok(b, "InternetCrackUrlA failed with error %d\n", GetLastError()); ok(url.dwSchemeLength == strlen(test->exp_scheme), "[%s] Got wrong scheme length: %d\n", test->url, url.dwSchemeLength); ok(!strcmp(scheme, test->exp_scheme), "[%s] Got wrong scheme, expected: %s, got: %s\n", test->url, test->exp_scheme, scheme); ok(url.nScheme == test->scheme, "[%s] Got wrong nScheme, expected: %d, got: %d\n", test->url, test->scheme, url.nScheme); ok(url.dwHostNameLength == strlen(test->exp_hostname), "[%s] Got wrong hostname length: %d\n", test->url, url.dwHostNameLength); ok(!strcmp(hostname, test->exp_hostname), "[%s] Got wrong hostname, expected: %s, got: %s\n", test->url, test->exp_hostname, hostname); ok(url.nPort == test->port, "[%s] Got wrong port, expected: %d, got: %d\n", test->url, test->port, url.nPort); ok(url.dwUserNameLength == strlen(test->exp_username), "[%s] Got wrong username length: %d\n", test->url, url.dwUserNameLength); ok(!strcmp(username, test->exp_username), "[%s] Got wrong username, expected: %s, got: %s\n", test->url, test->exp_username, username); ok(url.dwPasswordLength == strlen(test->exp_password), "[%s] Got wrong password length: %d\n", test->url, url.dwPasswordLength); ok(!strcmp(password, test->exp_password), "[%s] Got wrong password, expected: %s, got: %s\n", test->url, test->exp_password, password); ok(url.dwUrlPathLength == strlen(test->exp_urlpath), "[%s] Got wrong urlpath length: %d\n", test->url, url.dwUrlPathLength); ok(!strcmp(urlpath, test->exp_urlpath), "[%s] Got wrong urlpath, expected: %s, got: %s\n", test->url, test->exp_urlpath, urlpath); ok(url.dwExtraInfoLength == strlen(test->exp_extrainfo), "[%s] Got wrong extrainfo length: %d\n", test->url, url.dwExtraInfoLength); ok(!strcmp(extrainfo, test->exp_extrainfo), "[%s] Got wrong extrainfo, expected: %s, got: %s\n", test->url, test->exp_extrainfo, extrainfo); /* test InternetCrackUrlW with valid buffers */ memset(&urlw, 0, sizeof(URL_COMPONENTSW)); urlw.dwStructSize = sizeof(URL_COMPONENTSW); urlw.lpszScheme = (WCHAR*)scheme; urlw.dwSchemeLength = sizeof(scheme) / sizeof(WCHAR); urlw.lpszHostName = (WCHAR*)hostname; urlw.dwHostNameLength = sizeof(hostname) / sizeof(WCHAR); urlw.lpszUserName = (WCHAR*)username; urlw.dwUserNameLength = sizeof(username) / sizeof(WCHAR); urlw.lpszPassword = (WCHAR*)password; urlw.dwPasswordLength = sizeof(password) / sizeof(WCHAR); urlw.lpszUrlPath = (WCHAR*)urlpath; urlw.dwUrlPathLength = sizeof(urlpath) / sizeof(WCHAR); urlw.lpszExtraInfo = (WCHAR*)extrainfo; urlw.dwExtraInfoLength = sizeof(extrainfo) / sizeof(WCHAR); b = InternetCrackUrlW(buf, lstrlenW(buf), 0, &urlw); ok(b, "InternetCrackUrlW failed with error %d\n", GetLastError()); ok(urlw.dwSchemeLength == strlen(test->exp_scheme), "[%s] Got wrong scheme length: %d\n", test->url, urlw.dwSchemeLength); ok(!lstrcmpW((WCHAR*)scheme, w_str_of(test->exp_scheme)), "[%s] Got wrong scheme, expected: %s, got: %s\n", test->url, test->exp_scheme, wine_dbgstr_w((WCHAR*)scheme)); ok(urlw.nScheme == test->scheme, "[%s] Got wrong nScheme, expected: %d, got: %d\n", test->url, test->scheme, urlw.nScheme); ok(urlw.dwHostNameLength == strlen(test->exp_hostname), "[%s] Got wrong hostname length: %d\n", test->url, urlw.dwHostNameLength); ok(!lstrcmpW((WCHAR*)hostname, w_str_of(test->exp_hostname)), "[%s] Got wrong hostname, expected: %s, got: %s\n", test->url, test->exp_hostname, wine_dbgstr_w((WCHAR*)hostname)); ok(urlw.nPort == test->port, "[%s] Got wrong port, expected: %d, got: %d\n", test->url, test->port, urlw.nPort); ok(urlw.dwUserNameLength == strlen(test->exp_username), "[%s] Got wrong username length: %d\n", test->url, urlw.dwUserNameLength); ok(!lstrcmpW((WCHAR*)username, w_str_of(test->exp_username)), "[%s] Got wrong username, expected: %s, got: %s\n", test->url, test->exp_username, wine_dbgstr_w((WCHAR*)username)); ok(urlw.dwPasswordLength == strlen(test->exp_password), "[%s] Got wrong password length: %d\n", test->url, urlw.dwPasswordLength); ok(!lstrcmpW((WCHAR*)password, w_str_of(test->exp_password)), "[%s] Got wrong password, expected: %s, got: %s\n", test->url, test->exp_password, wine_dbgstr_w((WCHAR*)password)); ok(urlw.dwUrlPathLength == strlen(test->exp_urlpath), "[%s] Got wrong urlpath length: %d\n", test->url, urlw.dwUrlPathLength); ok(!lstrcmpW((WCHAR*)urlpath, w_str_of(test->exp_urlpath)), "[%s] Got wrong urlpath, expected: %s, got: %s\n", test->url, test->exp_urlpath, wine_dbgstr_w((WCHAR*)urlpath)); ok(urlw.dwExtraInfoLength == strlen(test->exp_extrainfo), "[%s] Got wrong extrainfo length: %d\n", test->url, urlw.dwExtraInfoLength); ok(!lstrcmpW((WCHAR*)extrainfo, w_str_of(test->exp_extrainfo)), "[%s] Got wrong extrainfo, expected: %s, got: %s\n", test->url, test->exp_extrainfo, wine_dbgstr_w((WCHAR*)extrainfo)); }
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; }
bool CAmHttpSocket::PostUrl(const char *url, const char *PostData, int PostDataLength) { //check length of postdata if (PostDataLength == -1) PostDataLength = strlen(PostData); //some variable that we need... URL_COMPONENTSA uc; //let's split the url... uc.dwStructSize = sizeof(uc); uc.lpszScheme = NULL; uc.dwSchemeLength = 0; uc.lpszHostName = NULL; uc.dwHostNameLength = 1; uc.nPort = 0; uc.lpszUserName = NULL; uc.dwUserNameLength = 0; uc.lpszPassword = NULL; uc.dwPasswordLength = 0; uc.lpszUrlPath = NULL; uc.dwUrlPathLength = 1; uc.lpszExtraInfo = NULL; uc.dwExtraInfoLength = 0; InternetCrackUrlA(url, strlen(url), 0, &uc); //post the data... if (hCO != NULL) InternetCloseHandle(hCO); CHAR *HostName = strdup(uc.lpszHostName); if(!HostName){ LastError = -2; return false; } HostName[uc.dwHostNameLength] = '\0'; CHAR *FileName = strdup(uc.lpszUrlPath); FileName[uc.dwUrlPathLength] = '\0'; if (hIS != NULL) InternetCloseHandle(hIS); //if open, close the handle to the connection DWORD flags; if (uc.nPort == 80) { //we are talking plain http flags = INTERNET_FLAG_NO_CACHE_WRITE; } else { //we are talking secure https flags = INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_SECURE | INTERNET_FLAG_IGNORE_CERT_CN_INVALID | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID; } CHAR headers[] = ("Content-Type: application/x-www-form-urlencoded"); //content type for post... CHAR szAccept[] = ("*/*"); //we accept everything... LPSTR AcceptTypes[2]={0}; AcceptTypes[0]=szAccept; hCO = InternetConnectA(hIO, HostName, uc.nPort, (""), (""), INTERNET_SERVICE_HTTP, INTERNET_FLAG_NO_CACHE_WRITE, 0); hIS = HttpOpenRequestA(hCO, ("POST"), FileName, NULL, NULL, (LPCSTR *)AcceptTypes, flags, 0); if (!HttpSendRequestA(hIS, headers, strlen(headers), (TCHAR*)PostData, PostDataLength)) { LastError = GetLastError(); free(HostName); free(FileName); return false; } free(HostName); free(FileName); return true; }
/* * 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; }
/* * 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); }