// From smartmontools os_win32.cpp void GetWindowsVersion(void) { OSVERSIONINFOEXA vi, vi2; const char* w = 0; const char* w64 = "32 bit"; char *vptr, build_number[10] = ""; size_t vlen; unsigned major, minor; ULONGLONG major_equal, minor_equal; BOOL ws; nWindowsVersion = WINDOWS_UNDEFINED; safe_strcpy(WindowsVersionStr, sizeof(WindowsVersionStr), "Windows Undefined"); memset(&vi, 0, sizeof(vi)); vi.dwOSVersionInfoSize = sizeof(vi); if (!GetVersionExA((OSVERSIONINFOA *)&vi)) { memset(&vi, 0, sizeof(vi)); vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); if (!GetVersionExA((OSVERSIONINFOA *)&vi)) return; } if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) { if (vi.dwMajorVersion > 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion >= 2)) { // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx // And starting with Windows 10 Preview 2, Windows enforces the use of the application/supportedOS // manifest in order for VerSetConditionMask() to report the ACTUAL OS major and minor... major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); for (major = vi.dwMajorVersion; major <= 9; major++) { memset(&vi2, 0, sizeof(vi2)); vi2.dwOSVersionInfoSize = sizeof(vi2); vi2.dwMajorVersion = major; if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal)) continue; if (vi.dwMajorVersion < major) { vi.dwMajorVersion = major; vi.dwMinorVersion = 0; } minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL); for (minor = vi.dwMinorVersion; minor <= 9; minor++) { memset(&vi2, 0, sizeof(vi2)); vi2.dwOSVersionInfoSize = sizeof(vi2); vi2.dwMinorVersion = minor; if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal)) continue; vi.dwMinorVersion = minor; break; } break; } } if (vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) { ws = (vi.wProductType <= VER_NT_WORKSTATION); nWindowsVersion = vi.dwMajorVersion << 4 | vi.dwMinorVersion; switch (nWindowsVersion) { case 0x51: w = "XP"; break; case 0x52: w = (!GetSystemMetrics(89)?"2003":"2003_R2"); break; case 0x60: w = (ws?"Vista":"2008"); break; case 0x61: w = (ws?"7":"2008_R2"); break; case 0x62: w = (ws?"8":"2012"); break; case 0x63: w = (ws?"8.1":"2012_R2"); break; case 0x64: w = (ws?"10 (Preview 1)":"Server 10 (Preview 1)"); break; // Starting with Windows 10 Preview 2, the major is the same as the public-facing version case 0xA0: w = (ws?"10":"Server 10"); break; default: if (nWindowsVersion < 0x51) nWindowsVersion = WINDOWS_UNSUPPORTED; else w = "11 or later"; break; } } } if (is_x64()) w64 = "64-bit"; vptr = &WindowsVersionStr[sizeof("Windows ") - 1]; vlen = sizeof(WindowsVersionStr) - sizeof("Windows ") - 1; if (!w) safe_sprintf(vptr, vlen, "%s %u.%u %s", (vi.dwPlatformId==VER_PLATFORM_WIN32_NT?"NT":"??"), (unsigned)vi.dwMajorVersion, (unsigned)vi.dwMinorVersion, w64); else if (vi.wServicePackMinor) safe_sprintf(vptr, vlen, "%s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, w64); else if (vi.wServicePackMajor) safe_sprintf(vptr, vlen, "%s SP%u %s", w, vi.wServicePackMajor, w64); else safe_sprintf(vptr, vlen, "%s %s", w, w64); // Add the build number for Windows 8.0 and later if (nWindowsVersion >= 0x62) { GetRegistryKeyStr(REGKEY_HKLM, "Microsoft\\Windows NT\\CurrentVersion\\CurrentBuildNumber", build_number, sizeof(build_number)); if (build_number[0] != 0) { safe_strcat(WindowsVersionStr, sizeof(WindowsVersionStr), " (Build "); safe_strcat(WindowsVersionStr, sizeof(WindowsVersionStr), build_number); safe_strcat(WindowsVersionStr, sizeof(WindowsVersionStr), ")"); } } }
/* * 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; }
/* * 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; 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; DownloadStatus = 0; 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_PROGRESS_INIT, 0, 0); } for (last_slash = safe_strlen(file); last_slash != 0; last_slash--) { if ((file[last_slash] == '/') || (file[last_slash] == '\\')) { last_slash++; break; } } PrintInfo(0, MSG_240, &file[last_slash]); uprintf("Downloading '%s' from %s\n", &file[last_slash], url); if ( (!InternetCrackUrlA(url, (DWORD)safe_strlen(url), 0, &UrlParts)) || (UrlParts.lpszHostName == NULL) || (UrlParts.lpszUrlPath == NULL)) { 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 (WinNT %d.%d%s)", rufus_version[0], rufus_version[1], rufus_version[2], nWindowsVersion>>4, nWindowsVersion&0x0F, is_x64()?"; WOW64":""); 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(DownloadStatus); DownloadStatus = 404; HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&DownloadStatus, &dwSize, NULL); if (DownloadStatus != 200) { error_code = ERROR_INTERNET_ITEM_NOT_FOUND; uprintf("Unable to access file: Server status %d\n", DownloadStatus); 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); PrintInfo(0, 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_PROGRESS_EXIT, (WPARAM)r, 0); if (fd != NULL) fclose(fd); if (!r) { _unlink(file); if (PromptOnError) { PrintInfo(0, 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; }
// From smartmontools os_win32.cpp void GetWindowsVersion(void) { OSVERSIONINFOEXA vi, vi2; const char* w = 0; const char* w64 = "32 bit"; char* vptr; size_t vlen; unsigned major, minor; ULONGLONG major_equal, minor_equal; BOOL ws; nWindowsVersion = WINDOWS_UNDEFINED; safe_strcpy(WindowsVersionStr, sizeof(WindowsVersionStr), "Windows Undefined"); memset(&vi, 0, sizeof(vi)); vi.dwOSVersionInfoSize = sizeof(vi); if (!GetVersionExA((OSVERSIONINFOA *)&vi)) { memset(&vi, 0, sizeof(vi)); vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); if (!GetVersionExA((OSVERSIONINFOA *)&vi)) return; } if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) { if (vi.dwMajorVersion > 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion >= 2)) { // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); for (major = vi.dwMajorVersion; major <= 9; major++) { memset(&vi2, 0, sizeof(vi2)); vi2.dwOSVersionInfoSize = sizeof(vi2); vi2.dwMajorVersion = major; if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal)) continue; if (vi.dwMajorVersion < major) { vi.dwMajorVersion = major; vi.dwMinorVersion = 0; } minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL); for (minor = vi.dwMinorVersion; minor <= 9; minor++) { memset(&vi2, 0, sizeof(vi2)); vi2.dwOSVersionInfoSize = sizeof(vi2); vi2.dwMinorVersion = minor; if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal)) continue; vi.dwMinorVersion = minor; break; } break; } } if (vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) { ws = (vi.wProductType <= VER_NT_WORKSTATION); nWindowsVersion = vi.dwMajorVersion << 4 | vi.dwMinorVersion; switch (nWindowsVersion) { case 0x50: w = "2000"; break; case 0x51: w = "XP"; break; case 0x52: w = (!GetSystemMetrics(89)?"2003":"2003_R2"); break; case 0x60: w = (ws?"Vista":"2008"); break; case 0x61: w = (ws?"7":"2008_R2"); break; case 0x62: w = (ws?"8":"2012"); break; case 0x63: w = (ws?"8.1":"2012_R2"); break; case 0x64: w = (ws?"8.2":"2012_R3"); break; default: if (nWindowsVersion < 0x50) nWindowsVersion = WINDOWS_UNSUPPORTED; else w = "9 or later"; break; } } } if (is_x64()) w64 = "64-bit"; vptr = &WindowsVersionStr[sizeof("Windows ") - 1]; vlen = sizeof(WindowsVersionStr) - sizeof("Windows ") - 1; if (!w) safe_sprintf(vptr, vlen, "%s %u.%u %s", (vi.dwPlatformId==VER_PLATFORM_WIN32_NT?"NT":"??"), (unsigned)vi.dwMajorVersion, (unsigned)vi.dwMinorVersion, w64); else if (vi.wServicePackMinor) safe_sprintf(vptr, vlen, "%s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, w64); else if (vi.wServicePackMajor) safe_sprintf(vptr, vlen, "%s SP%u %s", w, vi.wServicePackMajor, w64); else safe_sprintf(vptr, vlen, "%s %s", w, w64); }
static void get_windows_version(void) { OSVERSIONINFOEXA vi, vi2; const char *arch, *w = NULL; unsigned major, minor, version; ULONGLONG major_equal, minor_equal; BOOL ws; windows_version = WINDOWS_UNDEFINED; memset(&vi, 0, sizeof(vi)); vi.dwOSVersionInfoSize = sizeof(vi); if (!GetVersionExA((OSVERSIONINFOA *)&vi)) { memset(&vi, 0, sizeof(vi)); vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); if (!GetVersionExA((OSVERSIONINFOA *)&vi)) return; } if (vi.dwPlatformId != VER_PLATFORM_WIN32_NT) return; if ((vi.dwMajorVersion > 6) || ((vi.dwMajorVersion == 6) && (vi.dwMinorVersion >= 2))) { // Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version // See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL); for (major = vi.dwMajorVersion; major <= 9; major++) { memset(&vi2, 0, sizeof(vi2)); vi2.dwOSVersionInfoSize = sizeof(vi2); vi2.dwMajorVersion = major; if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal)) continue; if (vi.dwMajorVersion < major) { vi.dwMajorVersion = major; vi.dwMinorVersion = 0; } minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL); for (minor = vi.dwMinorVersion; minor <= 9; minor++) { memset(&vi2, 0, sizeof(vi2)); vi2.dwOSVersionInfoSize = sizeof(vi2); vi2.dwMinorVersion = minor; if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal)) continue; vi.dwMinorVersion = minor; break; } break; } } if ((vi.dwMajorVersion > 0xf) || (vi.dwMinorVersion > 0xf)) return; ws = (vi.wProductType <= VER_NT_WORKSTATION); version = vi.dwMajorVersion << 4 | vi.dwMinorVersion; switch (version) { case 0x50: windows_version = WINDOWS_2000; w = "2000"; break; case 0x51: windows_version = WINDOWS_XP; w = "XP"; break; case 0x52: windows_version = WINDOWS_2003; w = "2003"; break; case 0x60: windows_version = WINDOWS_VISTA; w = (ws ? "Vista" : "2008"); break; case 0x61: windows_version = WINDOWS_7; w = (ws ? "7" : "2008_R2"); break; case 0x62: windows_version = WINDOWS_8; w = (ws ? "8" : "2012"); break; case 0x63: windows_version = WINDOWS_8_1; w = (ws ? "8.1" : "2012_R2"); break; case 0x64: windows_version = WINDOWS_10; w = (ws ? "10" : "2016"); break; default: if (version < 0x50) { return; } else { windows_version = WINDOWS_11_OR_LATER; w = "11 or later"; } } arch = is_x64() ? "64-bit" : "32-bit"; if (vi.wServicePackMinor) usbi_dbg("Windows %s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, arch); else if (vi.wServicePackMajor) usbi_dbg("Windows %s SP%u %s", w, vi.wServicePackMajor, arch); else usbi_dbg("Windows %s %s", w, arch); }
/* * 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; }
int __cdecl main(int argc, char** argv) { static int opt_silent = 1, log_level = WDI_LOG_LEVEL_WARNING; struct wdi_device_info *list; int c,r; BOOL list_usbs=FALSE, bootloaderWinusbInstall=FALSE; BOOL pause=FALSE; char *inf_name = INF_NAME; char *ext_dir = DEFAULT_DIR; char *cert_name = NULL; static struct option long_options[] = { {"verbose", no_argument, 0, 'v'}, {"list", no_argument, 0, 'l'}, {"help", no_argument, 0, 'h'}, {"pause", no_argument, 0, 'p'}, {"bootloader", no_argument, 0, 'b'}, {0, 0, 0, 0} }; while(1) { c = getopt_long(argc, argv, "blhvp", long_options, NULL); oprintf("got argument: %d \n", c); if (c == -1) break; switch(c) { case 'v': opt_silent = 0; break; case 'h': usage(); break; case 'l': list_usbs=TRUE; break; case 'p': pause=TRUE; break; case 'b': bootloaderWinusbInstall = TRUE; break; default: usage(); exit(0); } } wdi_set_log_level(log_level); if (is_x64()) { oprintf("I see you are on a 64 bit system, nice\n"); } else { oprintf("What a lovely 32 bit system you have\n"); } if (list_usbs) { listDevices(opt_silent); } if (bootloaderWinusbInstall) { r=set_bootloader_to_winusb(opt_silent); <<<<<<< HEAD listDevices(opt_silent); // Print these before and after :) printf("RETURN:%d,%s", r, wdi_strerror(r)); //just print the return code for now =======
/* * 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); }