From 7426573dc11dfcc0f5ab68db0d8b87b3b12bdfd8 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Sun, 11 Mar 2012 01:55:25 +0000 Subject: [PATCH] [iso] add download & replace of obsolete vesamenu.c32 * adds http/https download capabilities * closes #46 --- src/.msvc/rufus_2010.vcxproj | 2 + src/.msvc/rufus_2010.vcxproj.filters | 6 + src/.msvc/rufus_sources | 2 +- src/Makefile.am | 2 +- src/Makefile.in | 20 +- src/format.c | 3 +- src/format.h | 25 -- src/icon.c | 6 + src/iso.c | 52 ++- src/net.c | 313 +++++++++++++++ src/net.h | 571 +++++++++++++++++++++++++++ src/rufus.c | 63 ++- src/rufus.h | 45 ++- src/rufus.rc | 12 +- src/stdio.c | 2 +- src/stdlg.c | 1 - 16 files changed, 1042 insertions(+), 83 deletions(-) create mode 100644 src/net.c create mode 100644 src/net.h diff --git a/src/.msvc/rufus_2010.vcxproj b/src/.msvc/rufus_2010.vcxproj index ba941f03..15f1ed88 100644 --- a/src/.msvc/rufus_2010.vcxproj +++ b/src/.msvc/rufus_2010.vcxproj @@ -165,6 +165,7 @@ + @@ -181,6 +182,7 @@ + diff --git a/src/.msvc/rufus_2010.vcxproj.filters b/src/.msvc/rufus_2010.vcxproj.filters index 9777c4de..9627380e 100644 --- a/src/.msvc/rufus_2010.vcxproj.filters +++ b/src/.msvc/rufus_2010.vcxproj.filters @@ -51,6 +51,9 @@ Source Files + + Source Files + @@ -92,6 +95,9 @@ Header Files + + Header Files + diff --git a/src/.msvc/rufus_sources b/src/.msvc/rufus_sources index 3f9490b3..83880acb 100644 --- a/src/.msvc/rufus_sources +++ b/src/.msvc/rufus_sources @@ -15,7 +15,6 @@ TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ $(SDK_LIB_PATH)\user32.lib \ $(SDK_LIB_PATH)\setupapi.lib \ $(SDK_LIB_PATH)\ole32.lib \ - $(SDK_LIB_PATH)\version.lib \ $(SDK_LIB_PATH)\uuid.lib \ $(SDK_LIB_PATH)\shell32.lib \ .\ms-sys\ms-sys.lib \ @@ -34,6 +33,7 @@ SOURCES=rufus.c \ stdlg.c \ icon.c \ parser.c \ + net.c \ iso.c \ dos.c \ dos_locale.c \ diff --git a/src/Makefile.am b/src/Makefile.am index 6f0f6471..0ec70283 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,7 +9,7 @@ pkg_v_rc_0 = @echo " RC $@"; %_rc.o: %.rc $(pkg_v_rc)$(WINDRES) $(AM_RCFLAGS) -i $< -o $@ -rufus_SOURCES = drive.c icon.c parser.c iso.c dos.c dos_locale.c badblocks.c syslinux.c format.c stdio.c stdlg.c rufus.c +rufus_SOURCES = drive.c icon.c parser.c iso.c net.c dos.c dos_locale.c badblocks.c syslinux.c format.c stdio.c stdlg.c rufus.c rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./libcdio $(AM_CFLAGS) rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows rufus_LDADD = rufus_rc.o ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \ diff --git a/src/Makefile.in b/src/Makefile.in index 94bd6cc4..ec099e89 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -44,11 +44,11 @@ CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = PROGRAMS = $(noinst_PROGRAMS) am_rufus_OBJECTS = rufus-drive.$(OBJEXT) rufus-icon.$(OBJEXT) \ - rufus-parser.$(OBJEXT) rufus-iso.$(OBJEXT) rufus-dos.$(OBJEXT) \ - rufus-dos_locale.$(OBJEXT) rufus-badblocks.$(OBJEXT) \ - rufus-syslinux.$(OBJEXT) rufus-format.$(OBJEXT) \ - rufus-stdio.$(OBJEXT) rufus-stdlg.$(OBJEXT) \ - rufus-rufus.$(OBJEXT) + rufus-parser.$(OBJEXT) rufus-iso.$(OBJEXT) rufus-net.$(OBJEXT) \ + rufus-dos.$(OBJEXT) rufus-dos_locale.$(OBJEXT) \ + rufus-badblocks.$(OBJEXT) rufus-syslinux.$(OBJEXT) \ + rufus-format.$(OBJEXT) rufus-stdio.$(OBJEXT) \ + rufus-stdlg.$(OBJEXT) rufus-rufus.$(OBJEXT) rufus_OBJECTS = $(am_rufus_OBJECTS) rufus_DEPENDENCIES = rufus_rc.o ms-sys/libmssys.a \ syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \ @@ -185,7 +185,7 @@ SUBDIRS = ms-sys syslinux/libfat syslinux/libinstaller libcdio/iso9660 libcdio/u pkg_v_rc = $(pkg_v_rc_$(V)) pkg_v_rc_ = $(pkg_v_rc_$(AM_DEFAULT_VERBOSITY)) pkg_v_rc_0 = @echo " RC $@"; -rufus_SOURCES = drive.c icon.c parser.c iso.c dos.c dos_locale.c badblocks.c syslinux.c format.c stdio.c stdlg.c rufus.c +rufus_SOURCES = drive.c icon.c parser.c iso.c net.c dos.c dos_locale.c badblocks.c syslinux.c format.c stdio.c stdlg.c rufus.c rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./libcdio $(AM_CFLAGS) rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows rufus_LDADD = rufus_rc.o ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \ @@ -278,6 +278,14 @@ rufus-iso.obj: iso.c $(AM_V_CC) @AM_BACKSLASH@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-iso.obj `if test -f 'iso.c'; then $(CYGPATH_W) 'iso.c'; else $(CYGPATH_W) '$(srcdir)/iso.c'; fi` +rufus-net.o: net.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-net.o `test -f 'net.c' || echo '$(srcdir)/'`net.c + +rufus-net.obj: net.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-net.obj `if test -f 'net.c'; then $(CYGPATH_W) 'net.c'; else $(CYGPATH_W) '$(srcdir)/net.c'; fi` + rufus-dos.o: dos.c $(AM_V_CC) @AM_BACKSLASH@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-dos.o `test -f 'dos.c' || echo '$(srcdir)/'`dos.c diff --git a/src/format.c b/src/format.c index 756e7c15..7edb6982 100644 --- a/src/format.c +++ b/src/format.c @@ -760,11 +760,12 @@ DWORD WINAPI FormatThread(LPVOID param) // Issue another complete remount before we exit, to ensure we're clean RemountVolume(drive_name[0]); // NTFS fixup (WinPE/AIK images don't seem to boot without an extra checkdisk) - if ((dt == DT_ISO) && (fs = FS_NTFS)) + if ((dt == DT_ISO) && (fs == FS_NTFS)) CheckDisk(drive_name[0]); } out: + SendMessage(hISOProgressDlg, UM_ISO_EXIT, 0, 0); safe_unlockclose(hLogicalVolume); safe_unlockclose(hPhysicalDrive); PostMessage(hMainDialog, UM_FORMAT_COMPLETED, 0, 0); diff --git a/src/format.h b/src/format.h index 54f28c89..948efae5 100644 --- a/src/format.h +++ b/src/format.h @@ -21,31 +21,6 @@ #pragma once -/* - * typedefs for the function prototypes. Use the something like: - * PF_DECL(FormatEx); - * which translates to: - * FormatEx_t pfFormatEx = NULL; - * in your code, to declare the entrypoint and then use: - * PF_INIT(FormatEx, fmifs); - * which translates to: - * pfFormatEx = (FormatEx_t) GetProcAddress(GetDLLHandle("fmifs"), "FormatEx"); - * to make it accessible. - */ -static __inline HMODULE GetDLLHandle(char* szDLLName) -{ - HMODULE h = NULL; - if ((h = GetModuleHandleA(szDLLName)) == NULL) - h = LoadLibraryA(szDLLName); - return h; -} -#define PF_DECL(proc) proc##_t pf##proc = NULL -#define PF_INIT(proc, dllname) pf##proc = (proc##_t) GetProcAddress(GetDLLHandle(#dllname), #proc) -#define PF_INIT_OR_OUT(proc, dllname) \ - PF_INIT(proc, dllname); if (pf##proc == NULL) { \ - uprintf("unable to access %s DLL: %s", #dllname, \ - WindowsErrorString()); goto out; } - /* Callback command types (some errorcode were filled from HPUSBFW V2.2.3 and their designation from msdn.microsoft.com/en-us/library/windows/desktop/aa819439.aspx */ typedef enum { diff --git a/src/icon.c b/src/icon.c index 29ad3615..1e821bee 100644 --- a/src/icon.c +++ b/src/icon.c @@ -17,6 +17,12 @@ * along with this program. If not, see . */ +/* Memory leaks detection - define _CRTDBG_MAP_ALLOC as preprocessor macro */ +#ifdef _CRTDBG_MAP_ALLOC +#include +#include +#endif + #include #include #include diff --git a/src/iso.c b/src/iso.c index f344d032..c94fd622 100644 --- a/src/iso.c +++ b/src/iso.c @@ -41,15 +41,6 @@ #include "msapi_utf8.h" #include "resource.h" -#ifndef MIN -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#endif -#ifndef PBS_MARQUEE -#define PBS_MARQUEE 0x08 -#endif -#ifndef PBM_SETMARQUEE -#define PBM_SETMARQUEE (WM_USER+10) -#endif // How often should we update the progress bar (in 2K blocks) as updating // the progress bar for every block will bring extraction to a crawl #define PROGRESS_THRESHOLD 1024 @@ -66,6 +57,8 @@ static const char *psz_extract_dir; static const char *bootmgr_name = "bootmgr"; static const char *ldlinux_name = "ldlinux.sys"; static const char *isolinux_name[] = { "isolinux.cfg", "syslinux.cfg", "extlinux.conf"}; +static const char *vesamenu_name = "vesamenu.c32"; +static int64_t old_vesamenu_threshold = 145000; static uint8_t i_joliet_level = 0; static uint64_t total_blocks, nb_blocks; static BOOL scan_only = FALSE; @@ -108,8 +101,8 @@ static void log_handler (cdio_log_level_t level, const char *message) * Scan and set ISO properties * Returns true if the the current file does not need to be processed further */ -static __inline BOOL check_iso_props(BOOL is_root, BOOL* is_syslinux_cfg, int64_t i_file_length, - const char* psz_basename, char* psz_fullpath) +static __inline BOOL check_iso_props(BOOL is_root, BOOL* is_syslinux_cfg, BOOL* is_old_vesamenu, + int64_t i_file_length, const char* psz_basename, char* psz_fullpath) { size_t i; @@ -120,6 +113,12 @@ static __inline BOOL check_iso_props(BOOL is_root, BOOL* is_syslinux_cfg, int64_ *is_syslinux_cfg = TRUE; } + // Check for an old vesamenu.c32 file anywhere + *is_old_vesamenu = FALSE; + if ((_stricmp(psz_basename, vesamenu_name) == 0) && (i_file_length <= old_vesamenu_threshold)) { + *is_old_vesamenu = TRUE; + } + if (scan_only) { // Check for a "bootmgr" file in root (psz_path = "") if (is_root && (_stricmp(psz_basename, bootmgr_name) == 0)) @@ -129,6 +128,8 @@ static __inline BOOL check_iso_props(BOOL is_root, BOOL* is_syslinux_cfg, int64_ // Maintain a list of all the isolinux/syslinux configs identified so far StrArrayAdd(&config_path, psz_fullpath); } + if (*is_old_vesamenu) + iso_report.has_old_vesamenu = TRUE; if (i_file_length >= FOUR_GIGABYTES) iso_report.has_4GB_file = TRUE; // Compute projected size needed @@ -151,7 +152,7 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha { HANDLE file_handle = NULL; DWORD buf_size, wr_size; - BOOL r, is_syslinux_cfg; + BOOL r, is_syslinux_cfg, is_old_vesamenu; int i_length; size_t i, nul_pos; char* psz_fullpath = NULL; @@ -185,7 +186,7 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha } } else { i_file_length = udf_get_file_length(p_udf_dirent); - if (check_iso_props((*psz_path == 0), &is_syslinux_cfg, i_file_length, psz_basename, psz_fullpath)) { + if (check_iso_props((*psz_path == 0), &is_syslinux_cfg, &is_old_vesamenu, i_file_length, psz_basename, psz_fullpath)) { safe_free(psz_fullpath); continue; } @@ -197,6 +198,13 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha SetWindowTextU(hISOFileName, psz_fullpath); // Remove the appended size for extraction psz_fullpath[nul_pos] = 0; + if (is_old_vesamenu && use_own_vesamenu) { + if (CopyFileA("vesamenu.c32", psz_fullpath, FALSE)) { + uprintf(" Replaced with local version\n"); + continue; + } + uprintf(" Could not replace file: %s\n", WindowsErrorString()); + } file_handle = CreateFileU(psz_fullpath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (file_handle == INVALID_HANDLE_VALUE) { @@ -252,7 +260,7 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) { HANDLE file_handle = NULL; DWORD buf_size, wr_size; - BOOL s, is_syslinux_cfg; + BOOL s, is_syslinux_cfg, is_old_vesamenu; int i_length, r = 1; char psz_fullpath[1024], *psz_basename; const char *psz_iso_name = &psz_fullpath[strlen(psz_extract_dir)]; @@ -292,7 +300,7 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) goto out; } else { i_file_length = p_statbuf->size; - if (check_iso_props((*psz_path == 0), &is_syslinux_cfg, i_file_length, psz_basename, psz_fullpath)) { + if (check_iso_props((*psz_path == 0), &is_syslinux_cfg, &is_old_vesamenu, i_file_length, psz_basename, psz_fullpath)) { continue; } // Replace slashes with backslashes and append the size to the path for UI display @@ -304,6 +312,13 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) // ISO9660 cannot handle backslashes for (i=0; i + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Memory leaks detection - define _CRTDBG_MAP_ALLOC as preprocessor macro */ +#ifdef _CRTDBG_MAP_ALLOC +#include +#include +#endif + +#include +#include +#include + +#include "msapi_utf8.h" +#include "rufus.h" +#include "resource.h" +// winhttp.h is not available for WDK and MinGW32, so we have to use a replacement +#include "net.h" + +/* + * FormatMessage does not handle WinHTTP + */ +const char* WinHTTPErrorString(void) +{ + static char err_string[34]; + DWORD error_code; + + error_code = GetLastError(); + + if ((error_code < WINHTTP_ERROR_BASE) || (error_code > WINHTTP_ERROR_LAST)) + return WindowsErrorString(); + + switch(error_code) { + case ERROR_WINHTTP_OUT_OF_HANDLES: + return "No more handles could be generated at this time."; + case ERROR_WINHTTP_TIMEOUT: + return "The request has timed out."; + case ERROR_WINHTTP_INTERNAL_ERROR: + return "An internal error has occurred."; + case ERROR_WINHTTP_INVALID_URL: + return "The URL is invalid."; + case ERROR_WINHTTP_UNRECOGNIZED_SCHEME: + return "The URL scheme could not be recognized or is not supported."; + case ERROR_WINHTTP_NAME_NOT_RESOLVED: + return "The server name could not be resolved."; + case ERROR_WINHTTP_INVALID_OPTION: + return "The request specified an invalid option value."; + case ERROR_WINHTTP_OPTION_NOT_SETTABLE: + return "The request option cannot be set, only queried."; + case ERROR_WINHTTP_SHUTDOWN: + return "The Win32 HTTP function support is being shut down or unloaded."; + case ERROR_WINHTTP_LOGIN_FAILURE: + return "The request to connect and log on to the server failed."; + case ERROR_WINHTTP_OPERATION_CANCELLED: + return "The operation was canceled"; + case ERROR_WINHTTP_INCORRECT_HANDLE_TYPE: + return "The type of handle supplied is incorrect for this operation."; + case ERROR_WINHTTP_INCORRECT_HANDLE_STATE: + return "The requested operation cannot be carried out because the handle supplied is not in the correct state."; + case ERROR_WINHTTP_CANNOT_CONNECT: + return "The attempt to connect to the server failed."; + case ERROR_WINHTTP_CONNECTION_ERROR: + return "The connection with the server has been terminated."; + case ERROR_WINHTTP_RESEND_REQUEST: + return "The Win32 HTTP function needs to redo the request."; + case ERROR_WINHTTP_SECURE_CERT_DATE_INVALID: + return "SSL certificate date indicates that the certificate is expired."; + case ERROR_WINHTTP_SECURE_CERT_CN_INVALID: + return "SSL certificate common name (host name field) is incorrect."; + case ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED: + return "Client Authentication certificate needed"; + case ERROR_WINHTTP_SECURE_INVALID_CA: + return "SSL certificate has been issued by an invalid Certification Authority."; + case ERROR_WINHTTP_SECURE_CERT_REV_FAILED: + return "SSL certificate revocation check failed."; + case ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN: + return "Cannot use this call before WinHttpOpen"; + case ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND: + return "Cannot use this call before WinHttpSend"; + case ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND: + return "Cannot use this call after WinHttpSend"; + case ERROR_WINHTTP_CANNOT_CALL_AFTER_OPEN: + return "Cannot use this call after WinHttpOpen"; + case ERROR_WINHTTP_HEADER_NOT_FOUND: + return "HTTP header was not found."; + case ERROR_WINHTTP_INVALID_SERVER_RESPONSE: + return "Invalid HTTP server response."; + case ERROR_WINHTTP_INVALID_HEADER: + return "Invalid HTTP header."; + case ERROR_WINHTTP_INVALID_QUERY_REQUEST: + return "Invalid HTTP query request."; + case ERROR_WINHTTP_HEADER_ALREADY_EXISTS: + return "HTTP header already exists."; + case ERROR_WINHTTP_REDIRECT_FAILED: + return "HTTP redirect failed."; + case ERROR_WINHTTP_SECURE_CHANNEL_ERROR: + return "Unnable to establish secure HTTP channel."; + case ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT: + return "Bad auto proxy script."; + case ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT: + return "Unable to download script."; + case ERROR_WINHTTP_SECURE_INVALID_CERT: + return "SSL certificate is invalid."; + case ERROR_WINHTTP_SECURE_CERT_REVOKED: + return "SSL certificate has been revoked."; + case ERROR_WINHTTP_NOT_INITIALIZED: + return "WinHTTP has not be initialized."; + case ERROR_WINHTTP_SECURE_FAILURE: + return "SSL failure."; + case ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR: + return "Auto proxy service error."; + case ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE: + return "Wrong SSL certificate usage."; + case ERROR_WINHTTP_AUTODETECTION_FAILED: + return "HTTP autodetection failed."; + case ERROR_WINHTTP_HEADER_COUNT_EXCEEDED: + return "HTTP header count exceeded."; + case ERROR_WINHTTP_HEADER_SIZE_OVERFLOW: + return "HTTP header size overflow."; + case ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW: + return "Chunked encoding HTTP header size overflow."; + case ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW: + return "Response drain overflow."; + case ERROR_WINHTTP_CLIENT_CERT_NO_PRIVATE_KEY: + return "Certificate does not contain a private key."; + case ERROR_WINHTTP_CLIENT_CERT_NO_ACCESS_PRIVATE_KEY: + return "Unable to access client certificate's private key."; + default: + safe_sprintf(err_string, sizeof(err_string), "WinHTTP unknown error 0x%08X", error_code); + return err_string; + } +} + +/* + * Download a file from an URL + * Mostly taken from http://msdn.microsoft.com/en-us/library/aa384270.aspx + */ +BOOL DownloadFile(const char* url, const char* file) +{ + BOOL r=FALSE; + DWORD dwSize, dwDownloaded, dwTotalSize, dwReadSize, dwTotalSizeSize = sizeof(dwTotalSize); + FILE* fd = NULL; + LONG progress_style; + unsigned char* buf = NULL; + wchar_t wAgent[64], *wUrl = NULL, wHostName[64], wUrlPath[128]; + HINTERNET hSession=NULL, hConnect=NULL, hRequest=NULL; + URL_COMPONENTSW UrlParts = {sizeof(URL_COMPONENTSW), NULL, 1, (INTERNET_SCHEME)0, + wHostName, ARRAYSIZE(wHostName), INTERNET_DEFAULT_PORT, NULL, 1, wUrlPath, ARRAYSIZE(wUrlPath), NULL, 1}; + + PF_DECL(WinHttpCrackUrl); + PF_DECL(WinHttpOpen); + PF_DECL(WinHttpConnect); + PF_DECL(WinHttpOpenRequest); + PF_DECL(WinHttpSendRequest); + PF_DECL(WinHttpReceiveResponse); + PF_DECL(WinHttpQueryHeaders); + PF_DECL(WinHttpQueryDataAvailable); + PF_DECL(WinHttpReadData); + PF_DECL(WinHttpCloseHandle); + + PF_INIT_OR_OUT(WinHttpCrackUrl, winhttp); + PF_INIT_OR_OUT(WinHttpOpen, winhttp); + PF_INIT_OR_OUT(WinHttpConnect, winhttp); + PF_INIT_OR_OUT(WinHttpOpenRequest, winhttp); + PF_INIT_OR_OUT(WinHttpSendRequest, winhttp); + PF_INIT_OR_OUT(WinHttpReceiveResponse, winhttp); + PF_INIT_OR_OUT(WinHttpQueryHeaders, winhttp); + PF_INIT_OR_OUT(WinHttpQueryDataAvailable, winhttp); + PF_INIT_OR_OUT(WinHttpReadData, winhttp); + PF_INIT_OR_OUT(WinHttpCloseHandle, winhttp); + + wUrl = utf8_to_wchar(url); + if (wUrl == NULL) goto out; + + // We reuse the ISO progress dialog for download progress + SetWindowTextU(hISOProgressDlg, "Downloading file..."); + SetWindowTextU(hISOFileName, url); + progress_style = GetWindowLong(hISOProgressBar, GWL_STYLE); + SetWindowLong(hISOProgressBar, GWL_STYLE, progress_style & (~PBS_MARQUEE)); + SendMessage(hISOProgressBar, PBM_SETPOS, 0, 0); + ShowWindow(hISOProgressDlg, SW_SHOW); + UpdateWindow(hISOProgressDlg); +// Sleep(3000); + + PrintStatus(0, FALSE, "Downloading %s: Connecting...\n", file); + uprintf("Downloading %s from %s\n", file, url); + + if (!pfWinHttpCrackUrl(wUrl, 0, 0, &UrlParts)) { + uprintf("Unable to decode URL: %s\n", WinHTTPErrorString()); + goto out; + } + + _snwprintf(wAgent, ARRAYSIZE(wAgent), L"Rufus/%d.%d.%d.%d", rufus_version[0], rufus_version[1], rufus_version[2], rufus_version[3]); + // Use WinHttpOpen to obtain a session handle. + hSession = pfWinHttpOpen(wAgent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); + if (!hSession) { + uprintf("Could not open HTTP session: %s\n", WinHTTPErrorString()); + goto out; + } + + // Specify an HTTP server. + hConnect = pfWinHttpConnect(hSession, UrlParts.lpszHostName, UrlParts.nPort, 0); + if (!hConnect) { + uprintf("Could not connect to HTTP server: %s\n", WinHTTPErrorString()); + goto out; + } + + // Create an HTTP request handle. + hRequest = pfWinHttpOpenRequest(hConnect, L"GET", UrlParts.lpszUrlPath, + NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, + (UrlParts.nScheme == INTERNET_SCHEME_HTTPS)?WINHTTP_FLAG_SECURE:0); + if (!hRequest) { + uprintf("Could not create server request: %s\n", WinHTTPErrorString()); + goto out; + } + + if (!pfWinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0 )) { + uprintf("Could not send server request: %s\n", WinHTTPErrorString()); + goto out; + } + + if (!pfWinHttpReceiveResponse(hRequest, NULL)) { + uprintf("Failure to receive server response: %s\n", WinHTTPErrorString()); + goto out; + } + + if (!pfWinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CONTENT_LENGTH|WINHTTP_QUERY_FLAG_NUMBER, + WINHTTP_HEADER_NAME_BY_INDEX, &dwTotalSize, &dwTotalSizeSize, WINHTTP_NO_HEADER_INDEX)) { + uprintf("Could not retreive file length: %s\n", WinHTTPErrorString()); + goto out; + } + uprintf("File length: %d bytes\n", dwTotalSize); + + fd = fopen(file, "wb"); + if (fd == NULL) { + uprintf("Unable to create file %s\n", file); + goto out; + } + + // Keep checking for data until there is nothing left. + dwReadSize = 0; + while(1) { + if (IS_ERROR(FormatStatus)) + goto out; + + Sleep(250); + + dwSize = 0; + if (!pfWinHttpQueryDataAvailable(hRequest, &dwSize)) + uprintf("Error in WinHttpQueryDataAvailable: %s\n", WinHTTPErrorString()); + if (dwSize <= 0) + break; + + // Allocate space for the buffer. + buf = (unsigned char*)malloc(dwSize+1); + if (buf == NULL) { + uprintf("Could not allocate buffer for download.\n"); + goto out; + } + if (!pfWinHttpReadData(hRequest, (LPVOID)buf, dwSize, &dwDownloaded)) { + uprintf("Error in WinHttpReadData: %s\n", WinHTTPErrorString()); + goto out; + } + if (dwDownloaded != dwSize) { + uprintf("Error: expected %d bytes by received %d\n", dwSize, dwDownloaded); + goto out; + } + dwReadSize += dwDownloaded; + SendMessage(hISOProgressBar, PBM_SETPOS, (WPARAM)(MAX_PROGRESS*((1.0f*dwReadSize)/(1.0f*dwTotalSize))), 0); + PrintStatus(0, FALSE, "Downloading %s: %0.1f%%\n", file, (100.0f*dwReadSize)/(1.0f*dwTotalSize)); + if (fwrite(buf, 1, dwSize, fd) != dwSize) { + uprintf("Error writing file %s\n", file); + goto out; + } + safe_free(buf); + } + r = (dwReadSize == dwTotalSize); + if (r) + uprintf("Successfully downloaded %s\n", file); + +out: + ShowWindow(hISOProgressDlg, SW_HIDE); + safe_free(wUrl); + safe_free(buf); + if (fd != NULL) fclose(fd); + if (!r) { + _unlink(file); + PrintStatus(0, FALSE, "Failed to download file."); + MessageBoxA(hMainDialog, IS_ERROR(FormatStatus)?StrError(FormatStatus):WinHTTPErrorString(), + "File download", MB_OK|MB_ICONERROR); + } + if (hRequest) pfWinHttpCloseHandle(hRequest); + if (hConnect) pfWinHttpCloseHandle(hConnect); + if (hSession) pfWinHttpCloseHandle(hSession); + + return r; +} diff --git a/src/net.h b/src/net.h new file mode 100644 index 00000000..13e1aa44 --- /dev/null +++ b/src/net.h @@ -0,0 +1,571 @@ +/* + * Rufus: The Reliable USB Formatting Utility + * Networking functionality (web file download, etc.) + * Copyright (c) 2012 Pete Batard + * based on winhttp.h from the Wine project + * Copyright (C) 2007 Francois Gouget + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include + +#define WINHTTPAPI +#define BOOLAPI WINHTTPAPI BOOL WINAPI + +typedef LPVOID HINTERNET; +typedef HINTERNET *LPHINTERNET; + +#define INTERNET_DEFAULT_PORT 0 +#define INTERNET_DEFAULT_HTTP_PORT 80 +#define INTERNET_DEFAULT_HTTPS_PORT 443 +typedef WORD INTERNET_PORT; +typedef INTERNET_PORT *LPINTERNET_PORT; + +#define INTERNET_SCHEME_HTTP 1 +#define INTERNET_SCHEME_HTTPS 2 +typedef int INTERNET_SCHEME, *LPINTERNET_SCHEME; + +#define ICU_ESCAPE 0x80000000 + +/* flags for WinHttpOpen */ +#define WINHTTP_FLAG_ASYNC 0x10000000 + +/* flags for WinHttpOpenRequest */ +#define WINHTTP_FLAG_ESCAPE_PERCENT 0x00000004 +#define WINHTTP_FLAG_NULL_CODEPAGE 0x00000008 +#define WINHTTP_FLAG_ESCAPE_DISABLE 0x00000040 +#define WINHTTP_FLAG_ESCAPE_DISABLE_QUERY 0x00000080 +#define WINHTTP_FLAG_BYPASS_PROXY_CACHE 0x00000100 +#define WINHTTP_FLAG_REFRESH WINHTTP_FLAG_BYPASS_PROXY_CACHE +#define WINHTTP_FLAG_SECURE 0x00800000 + +#define WINHTTP_ACCESS_TYPE_DEFAULT_PROXY 0 +#define WINHTTP_ACCESS_TYPE_NO_PROXY 1 +#define WINHTTP_ACCESS_TYPE_NAMED_PROXY 3 + +#define WINHTTP_NO_PROXY_NAME NULL +#define WINHTTP_NO_PROXY_BYPASS NULL + +#define WINHTTP_NO_REFERER NULL +#define WINHTTP_DEFAULT_ACCEPT_TYPES NULL + +#define WINHTTP_NO_ADDITIONAL_HEADERS NULL +#define WINHTTP_NO_REQUEST_DATA NULL + +#define WINHTTP_HEADER_NAME_BY_INDEX NULL +#define WINHTTP_NO_OUTPUT_BUFFER NULL +#define WINHTTP_NO_HEADER_INDEX NULL + +#define WINHTTP_ADDREQ_INDEX_MASK 0x0000FFFF +#define WINHTTP_ADDREQ_FLAGS_MASK 0xFFFF0000 +#define WINHTTP_ADDREQ_FLAG_ADD_IF_NEW 0x10000000 +#define WINHTTP_ADDREQ_FLAG_ADD 0x20000000 +#define WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA 0x40000000 +#define WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON 0x01000000 +#define WINHTTP_ADDREQ_FLAG_COALESCE WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA +#define WINHTTP_ADDREQ_FLAG_REPLACE 0x80000000 + +#define WINHTTP_IGNORE_REQUEST_TOTAL_LENGTH 0 + +/* flags for WinHttp{Set/Query}Options */ +#define WINHTTP_FIRST_OPTION WINHTTP_OPTION_CALLBACK +#define WINHTTP_OPTION_CALLBACK 1 +#define WINHTTP_OPTION_RESOLVE_TIMEOUT 2 +#define WINHTTP_OPTION_CONNECT_TIMEOUT 3 +#define WINHTTP_OPTION_CONNECT_RETRIES 4 +#define WINHTTP_OPTION_SEND_TIMEOUT 5 +#define WINHTTP_OPTION_RECEIVE_TIMEOUT 6 +#define WINHTTP_OPTION_RECEIVE_RESPONSE_TIMEOUT 7 +#define WINHTTP_OPTION_HANDLE_TYPE 9 +#define WINHTTP_OPTION_READ_BUFFER_SIZE 12 +#define WINHTTP_OPTION_WRITE_BUFFER_SIZE 13 +#define WINHTTP_OPTION_PARENT_HANDLE 21 +#define WINHTTP_OPTION_EXTENDED_ERROR 24 +#define WINHTTP_OPTION_SECURITY_FLAGS 31 +#define WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT 32 +#define WINHTTP_OPTION_URL 34 +#define WINHTTP_OPTION_SECURITY_KEY_BITNESS 36 +#define WINHTTP_OPTION_PROXY 38 +#define WINHTTP_OPTION_USER_AGENT 41 +#define WINHTTP_OPTION_CONTEXT_VALUE 45 +#define WINHTTP_OPTION_CLIENT_CERT_CONTEXT 47 +#define WINHTTP_OPTION_REQUEST_PRIORITY 58 +#define WINHTTP_OPTION_HTTP_VERSION 59 +#define WINHTTP_OPTION_DISABLE_FEATURE 63 +#define WINHTTP_OPTION_CODEPAGE 68 +#define WINHTTP_OPTION_MAX_CONNS_PER_SERVER 73 +#define WINHTTP_OPTION_MAX_CONNS_PER_1_0_SERVER 74 +#define WINHTTP_OPTION_AUTOLOGON_POLICY 77 +#define WINHTTP_OPTION_SERVER_CERT_CONTEXT 78 +#define WINHTTP_OPTION_ENABLE_FEATURE 79 +#define WINHTTP_OPTION_WORKER_THREAD_COUNT 80 +#define WINHTTP_OPTION_PASSPORT_COBRANDING_TEXT 81 +#define WINHTTP_OPTION_PASSPORT_COBRANDING_URL 82 +#define WINHTTP_OPTION_CONFIGURE_PASSPORT_AUTH 83 +#define WINHTTP_OPTION_SECURE_PROTOCOLS 84 +#define WINHTTP_OPTION_ENABLETRACING 85 +#define WINHTTP_OPTION_PASSPORT_SIGN_OUT 86 +#define WINHTTP_OPTION_PASSPORT_RETURN_URL 87 +#define WINHTTP_OPTION_REDIRECT_POLICY 88 +#define WINHTTP_OPTION_MAX_HTTP_AUTOMATIC_REDIRECTS 89 +#define WINHTTP_OPTION_MAX_HTTP_STATUS_CONTINUE 90 +#define WINHTTP_OPTION_MAX_RESPONSE_HEADER_SIZE 91 +#define WINHTTP_OPTION_MAX_RESPONSE_DRAIN_SIZE 92 +#define WINHTTP_OPTION_CONNECTION_INFO 93 +#define WINHTTP_OPTION_CLIENT_CERT_ISSUER_LIST 94 +#define WINHTTP_OPTION_SPN 96 +#define WINHTTP_OPTION_GLOBAL_PROXY_CREDS 97 +#define WINHTTP_OPTION_GLOBAL_SERVER_CREDS 98 +#define WINHTTP_OPTION_UNLOAD_NOTIFY_EVENT 99 +#define WINHTTP_OPTION_REJECT_USERPWD_IN_URL 100 +#define WINHTTP_OPTION_USE_GLOBAL_SERVER_CREDENTIALS 101 +#define WINHTTP_LAST_OPTION WINHTTP_OPTION_USE_GLOBAL_SERVER_CREDENTIALS +#define WINHTTP_OPTION_USERNAME 0x1000 +#define WINHTTP_OPTION_PASSWORD 0x1001 +#define WINHTTP_OPTION_PROXY_USERNAME 0x1002 +#define WINHTTP_OPTION_PROXY_PASSWORD 0x1003 + +#define WINHTTP_CONNS_PER_SERVER_UNLIMITED 0xFFFFFFFF + +#define WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM 0 +#define WINHTTP_AUTOLOGON_SECURITY_LEVEL_LOW 1 +#define WINHTTP_AUTOLOGON_SECURITY_LEVEL_HIGH 2 +#define WINHTTP_AUTOLOGON_SECURITY_LEVEL_DEFAULT WINHTTP_AUTOLOGON_SECURITY_LEVEL_MEDIUM + +#define WINHTTP_OPTION_REDIRECT_POLICY_NEVER 0 +#define WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP 1 +#define WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS 2 +#define WINHTTP_OPTION_REDIRECT_POLICY_LAST WINHTTP_OPTION_REDIRECT_POLICY_ALWAYS +#define WINHTTP_OPTION_REDIRECT_POLICY_DEFAULT WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP + +#define WINHTTP_DISABLE_PASSPORT_AUTH 0x00000000 +#define WINHTTP_ENABLE_PASSPORT_AUTH 0x10000000 +#define WINHTTP_DISABLE_PASSPORT_KEYRING 0x20000000 +#define WINHTTP_ENABLE_PASSPORT_KEYRING 0x40000000 + +#define WINHTTP_DISABLE_COOKIES 0x00000001 +#define WINHTTP_DISABLE_REDIRECTS 0x00000002 +#define WINHTTP_DISABLE_AUTHENTICATION 0x00000004 +#define WINHTTP_DISABLE_KEEP_ALIVE 0x00000008 +#define WINHTTP_ENABLE_SSL_REVOCATION 0x00000001 +#define WINHTTP_ENABLE_SSL_REVERT_IMPERSONATION 0x00000002 +#define WINHTTP_DISABLE_SPN_SERVER_PORT 0x00000000 +#define WINHTTP_ENABLE_SPN_SERVER_PORT 0x00000001 +#define WINHTTP_OPTION_SPN_MASK WINHTTP_ENABLE_SPN_SERVER_PORT + +/* Options for WinHttpOpenRequest */ +#define WINHTTP_NO_REFERER NULL +#define WINHTTP_DEFAULT_ACCEPT_TYPES NULL + +/* Options for WinHttpSendRequest */ +#define WINHTTP_NO_ADDITIONAL_HEADERS NULL +#define WINHTTP_NO_REQUEST_DATA NULL + +/* WinHTTP error codes */ +#define WINHTTP_ERROR_BASE 12000 +#define ERROR_WINHTTP_OUT_OF_HANDLES (WINHTTP_ERROR_BASE + 1) +#define ERROR_WINHTTP_TIMEOUT (WINHTTP_ERROR_BASE + 2) +#define ERROR_WINHTTP_INTERNAL_ERROR (WINHTTP_ERROR_BASE + 4) +#define ERROR_WINHTTP_INVALID_URL (WINHTTP_ERROR_BASE + 5) +#define ERROR_WINHTTP_UNRECOGNIZED_SCHEME (WINHTTP_ERROR_BASE + 6) +#define ERROR_WINHTTP_NAME_NOT_RESOLVED (WINHTTP_ERROR_BASE + 7) +#define ERROR_WINHTTP_INVALID_OPTION (WINHTTP_ERROR_BASE + 9) +#define ERROR_WINHTTP_OPTION_NOT_SETTABLE (WINHTTP_ERROR_BASE + 11) +#define ERROR_WINHTTP_SHUTDOWN (WINHTTP_ERROR_BASE + 12) +#define ERROR_WINHTTP_LOGIN_FAILURE (WINHTTP_ERROR_BASE + 15) +#define ERROR_WINHTTP_OPERATION_CANCELLED (WINHTTP_ERROR_BASE + 17) +#define ERROR_WINHTTP_INCORRECT_HANDLE_TYPE (WINHTTP_ERROR_BASE + 18) +#define ERROR_WINHTTP_INCORRECT_HANDLE_STATE (WINHTTP_ERROR_BASE + 19) +#define ERROR_WINHTTP_CANNOT_CONNECT (WINHTTP_ERROR_BASE + 29) +#define ERROR_WINHTTP_CONNECTION_ERROR (WINHTTP_ERROR_BASE + 30) +#define ERROR_WINHTTP_RESEND_REQUEST (WINHTTP_ERROR_BASE + 32) +#define ERROR_WINHTTP_SECURE_CERT_DATE_INVALID (WINHTTP_ERROR_BASE + 37) +#define ERROR_WINHTTP_SECURE_CERT_CN_INVALID (WINHTTP_ERROR_BASE + 38) +#define ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED (WINHTTP_ERROR_BASE + 44) +#define ERROR_WINHTTP_SECURE_INVALID_CA (WINHTTP_ERROR_BASE + 45) +#define ERROR_WINHTTP_SECURE_CERT_REV_FAILED (WINHTTP_ERROR_BASE + 57) +#define ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN (WINHTTP_ERROR_BASE + 100) +#define ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND (WINHTTP_ERROR_BASE + 101) +#define ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND (WINHTTP_ERROR_BASE + 102) +#define ERROR_WINHTTP_CANNOT_CALL_AFTER_OPEN (WINHTTP_ERROR_BASE + 103) +#define ERROR_WINHTTP_HEADER_NOT_FOUND (WINHTTP_ERROR_BASE + 150) +#define ERROR_WINHTTP_INVALID_SERVER_RESPONSE (WINHTTP_ERROR_BASE + 152) +#define ERROR_WINHTTP_INVALID_HEADER (WINHTTP_ERROR_BASE + 153) +#define ERROR_WINHTTP_INVALID_QUERY_REQUEST (WINHTTP_ERROR_BASE + 154) +#define ERROR_WINHTTP_HEADER_ALREADY_EXISTS (WINHTTP_ERROR_BASE + 155) +#define ERROR_WINHTTP_REDIRECT_FAILED (WINHTTP_ERROR_BASE + 156) +#define ERROR_WINHTTP_SECURE_CHANNEL_ERROR (WINHTTP_ERROR_BASE + 157) +#define ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT (WINHTTP_ERROR_BASE + 166) +#define ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT (WINHTTP_ERROR_BASE + 167) +#define ERROR_WINHTTP_SECURE_INVALID_CERT (WINHTTP_ERROR_BASE + 169) +#define ERROR_WINHTTP_SECURE_CERT_REVOKED (WINHTTP_ERROR_BASE + 170) +#define ERROR_WINHTTP_NOT_INITIALIZED (WINHTTP_ERROR_BASE + 172) +#define ERROR_WINHTTP_SECURE_FAILURE (WINHTTP_ERROR_BASE + 175) +#define ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR (WINHTTP_ERROR_BASE + 178) +#define ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE (WINHTTP_ERROR_BASE + 179) +#define ERROR_WINHTTP_AUTODETECTION_FAILED (WINHTTP_ERROR_BASE + 180) +#define ERROR_WINHTTP_HEADER_COUNT_EXCEEDED (WINHTTP_ERROR_BASE + 181) +#define ERROR_WINHTTP_HEADER_SIZE_OVERFLOW (WINHTTP_ERROR_BASE + 182) +#define ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW (WINHTTP_ERROR_BASE + 183) +#define ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW (WINHTTP_ERROR_BASE + 184) +#define ERROR_WINHTTP_CLIENT_CERT_NO_PRIVATE_KEY (WINHTTP_ERROR_BASE + 185) +#define ERROR_WINHTTP_CLIENT_CERT_NO_ACCESS_PRIVATE_KEY (WINHTTP_ERROR_BASE + 186) +#define WINHTTP_ERROR_LAST (WINHTTP_ERROR_BASE + 186) + +/* WinHttp status codes */ +#define HTTP_STATUS_CONTINUE 100 +#define HTTP_STATUS_SWITCH_PROTOCOLS 101 +#define HTTP_STATUS_OK 200 +#define HTTP_STATUS_CREATED 201 +#define HTTP_STATUS_ACCEPTED 202 +#define HTTP_STATUS_PARTIAL 203 +#define HTTP_STATUS_NO_CONTENT 204 +#define HTTP_STATUS_RESET_CONTENT 205 +#define HTTP_STATUS_PARTIAL_CONTENT 206 +#define HTTP_STATUS_WEBDAV_MULTI_STATUS 207 +#define HTTP_STATUS_AMBIGUOUS 300 +#define HTTP_STATUS_MOVED 301 +#define HTTP_STATUS_REDIRECT 302 +#define HTTP_STATUS_REDIRECT_METHOD 303 +#define HTTP_STATUS_NOT_MODIFIED 304 +#define HTTP_STATUS_USE_PROXY 305 +#define HTTP_STATUS_REDIRECT_KEEP_VERB 307 +#define HTTP_STATUS_BAD_REQUEST 400 +#define HTTP_STATUS_DENIED 401 +#define HTTP_STATUS_PAYMENT_REQ 402 +#define HTTP_STATUS_FORBIDDEN 403 +#define HTTP_STATUS_NOT_FOUND 404 +#define HTTP_STATUS_BAD_METHOD 405 +#define HTTP_STATUS_NONE_ACCEPTABLE 406 +#define HTTP_STATUS_PROXY_AUTH_REQ 407 +#define HTTP_STATUS_REQUEST_TIMEOUT 408 +#define HTTP_STATUS_CONFLICT 409 +#define HTTP_STATUS_GONE 410 +#define HTTP_STATUS_LENGTH_REQUIRED 411 +#define HTTP_STATUS_PRECOND_FAILED 412 +#define HTTP_STATUS_REQUEST_TOO_LARGE 413 +#define HTTP_STATUS_URI_TOO_LONG 414 +#define HTTP_STATUS_UNSUPPORTED_MEDIA 415 +#define HTTP_STATUS_RETRY_WITH 449 +#define HTTP_STATUS_SERVER_ERROR 500 +#define HTTP_STATUS_NOT_SUPPORTED 501 +#define HTTP_STATUS_BAD_GATEWAY 502 +#define HTTP_STATUS_SERVICE_UNAVAIL 503 +#define HTTP_STATUS_GATEWAY_TIMEOUT 504 +#define HTTP_STATUS_VERSION_NOT_SUP 505 +#define HTTP_STATUS_FIRST HTTP_STATUS_CONTINUE +#define HTTP_STATUS_LAST HTTP_STATUS_VERSION_NOT_SUP + +#define SECURITY_FLAG_IGNORE_UNKNOWN_CA 0x00000100 +#define SECURITY_FLAG_IGNORE_CERT_DATE_INVALID 0x00002000 +#define SECURITY_FLAG_IGNORE_CERT_CN_INVALID 0x00001000 +#define SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE 0x00000200 +#define SECURITY_FLAG_SECURE 0x00000001 +#define SECURITY_FLAG_STRENGTH_WEAK 0x10000000 +#define SECURITY_FLAG_STRENGTH_MEDIUM 0x40000000 +#define SECURITY_FLAG_STRENGTH_STRONG 0x20000000 + +#define ICU_NO_ENCODE 0x20000000 +#define ICU_DECODE 0x10000000 +#define ICU_NO_META 0x08000000 +#define ICU_ENCODE_SPACES_ONLY 0x04000000 +#define ICU_BROWSER_MODE 0x02000000 +#define ICU_ENCODE_PERCENT 0x00001000 + +/* Query flags */ +#define WINHTTP_QUERY_MIME_VERSION 0 +#define WINHTTP_QUERY_CONTENT_TYPE 1 +#define WINHTTP_QUERY_CONTENT_TRANSFER_ENCODING 2 +#define WINHTTP_QUERY_CONTENT_ID 3 +#define WINHTTP_QUERY_CONTENT_DESCRIPTION 4 +#define WINHTTP_QUERY_CONTENT_LENGTH 5 +#define WINHTTP_QUERY_CONTENT_LANGUAGE 6 +#define WINHTTP_QUERY_ALLOW 7 +#define WINHTTP_QUERY_PUBLIC 8 +#define WINHTTP_QUERY_DATE 9 +#define WINHTTP_QUERY_EXPIRES 10 +#define WINHTTP_QUERY_LAST_MODIFIED 11 +#define WINHTTP_QUERY_MESSAGE_ID 12 +#define WINHTTP_QUERY_URI 13 +#define WINHTTP_QUERY_DERIVED_FROM 14 +#define WINHTTP_QUERY_COST 15 +#define WINHTTP_QUERY_LINK 16 +#define WINHTTP_QUERY_PRAGMA 17 +#define WINHTTP_QUERY_VERSION 18 +#define WINHTTP_QUERY_STATUS_CODE 19 +#define WINHTTP_QUERY_STATUS_TEXT 20 +#define WINHTTP_QUERY_RAW_HEADERS 21 +#define WINHTTP_QUERY_RAW_HEADERS_CRLF 22 +#define WINHTTP_QUERY_CONNECTION 23 +#define WINHTTP_QUERY_ACCEPT 24 +#define WINHTTP_QUERY_ACCEPT_CHARSET 25 +#define WINHTTP_QUERY_ACCEPT_ENCODING 26 +#define WINHTTP_QUERY_ACCEPT_LANGUAGE 27 +#define WINHTTP_QUERY_AUTHORIZATION 28 +#define WINHTTP_QUERY_CONTENT_ENCODING 29 +#define WINHTTP_QUERY_FORWARDED 30 +#define WINHTTP_QUERY_FROM 31 +#define WINHTTP_QUERY_IF_MODIFIED_SINCE 32 +#define WINHTTP_QUERY_LOCATION 33 +#define WINHTTP_QUERY_ORIG_URI 34 +#define WINHTTP_QUERY_REFERER 35 +#define WINHTTP_QUERY_RETRY_AFTER 36 +#define WINHTTP_QUERY_SERVER 37 +#define WINHTTP_QUERY_TITLE 38 +#define WINHTTP_QUERY_USER_AGENT 39 +#define WINHTTP_QUERY_WWW_AUTHENTICATE 40 +#define WINHTTP_QUERY_PROXY_AUTHENTICATE 41 +#define WINHTTP_QUERY_ACCEPT_RANGES 42 +#define WINHTTP_QUERY_SET_COOKIE 43 +#define WINHTTP_QUERY_COOKIE 44 +#define WINHTTP_QUERY_REQUEST_METHOD 45 +#define WINHTTP_QUERY_REFRESH 46 +#define WINHTTP_QUERY_CONTENT_DISPOSITION 47 +#define WINHTTP_QUERY_AGE 48 +#define WINHTTP_QUERY_CACHE_CONTROL 49 +#define WINHTTP_QUERY_CONTENT_BASE 50 +#define WINHTTP_QUERY_CONTENT_LOCATION 51 +#define WINHTTP_QUERY_CONTENT_MD5 52 +#define WINHTTP_QUERY_CONTENT_RANGE 53 +#define WINHTTP_QUERY_ETAG 54 +#define WINHTTP_QUERY_HOST 55 +#define WINHTTP_QUERY_IF_MATCH 56 +#define WINHTTP_QUERY_IF_NONE_MATCH 57 +#define WINHTTP_QUERY_IF_RANGE 58 +#define WINHTTP_QUERY_IF_UNMODIFIED_SINCE 59 +#define WINHTTP_QUERY_MAX_FORWARDS 60 +#define WINHTTP_QUERY_PROXY_AUTHORIZATION 61 +#define WINHTTP_QUERY_RANGE 62 +#define WINHTTP_QUERY_TRANSFER_ENCODING 63 +#define WINHTTP_QUERY_UPGRADE 64 +#define WINHTTP_QUERY_VARY 65 +#define WINHTTP_QUERY_VIA 66 +#define WINHTTP_QUERY_WARNING 67 +#define WINHTTP_QUERY_EXPECT 68 +#define WINHTTP_QUERY_PROXY_CONNECTION 69 +#define WINHTTP_QUERY_UNLESS_MODIFIED_SINCE 70 +#define WINHTTP_QUERY_PROXY_SUPPORT 75 +#define WINHTTP_QUERY_AUTHENTICATION_INFO 76 +#define WINHTTP_QUERY_PASSPORT_URLS 77 +#define WINHTTP_QUERY_PASSPORT_CONFIG 78 +#define WINHTTP_QUERY_MAX 78 +#define WINHTTP_QUERY_CUSTOM 65535 +#define WINHTTP_QUERY_FLAG_REQUEST_HEADERS 0x80000000 +#define WINHTTP_QUERY_FLAG_SYSTEMTIME 0x40000000 +#define WINHTTP_QUERY_FLAG_NUMBER 0x20000000 + +/* Callback options */ +#define WINHTTP_CALLBACK_STATUS_RESOLVING_NAME 0x00000001 +#define WINHTTP_CALLBACK_STATUS_NAME_RESOLVED 0x00000002 +#define WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER 0x00000004 +#define WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER 0x00000008 +#define WINHTTP_CALLBACK_STATUS_SENDING_REQUEST 0x00000010 +#define WINHTTP_CALLBACK_STATUS_REQUEST_SENT 0x00000020 +#define WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE 0x00000040 +#define WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED 0x00000080 +#define WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION 0x00000100 +#define WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED 0x00000200 +#define WINHTTP_CALLBACK_STATUS_HANDLE_CREATED 0x00000400 +#define WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING 0x00000800 +#define WINHTTP_CALLBACK_STATUS_DETECTING_PROXY 0x00001000 +#define WINHTTP_CALLBACK_STATUS_REDIRECT 0x00004000 +#define WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE 0x00008000 +#define WINHTTP_CALLBACK_STATUS_SECURE_FAILURE 0x00010000 +#define WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE 0x00020000 +#define WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE 0x00040000 +#define WINHTTP_CALLBACK_STATUS_READ_COMPLETE 0x00080000 +#define WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE 0x00100000 +#define WINHTTP_CALLBACK_STATUS_REQUEST_ERROR 0x00200000 +#define WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE 0x00400000 +#define WINHTTP_CALLBACK_FLAG_RESOLVE_NAME (WINHTTP_CALLBACK_STATUS_RESOLVING_NAME | WINHTTP_CALLBACK_STATUS_NAME_RESOLVED) +#define WINHTTP_CALLBACK_FLAG_CONNECT_TO_SERVER (WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER | WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER) +#define WINHTTP_CALLBACK_FLAG_SEND_REQUEST (WINHTTP_CALLBACK_STATUS_SENDING_REQUEST | WINHTTP_CALLBACK_STATUS_REQUEST_SENT) +#define WINHTTP_CALLBACK_FLAG_RECEIVE_RESPONSE (WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE | WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED) +#define WINHTTP_CALLBACK_FLAG_CLOSE_CONNECTION (WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION | WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED) +#define WINHTTP_CALLBACK_FLAG_HANDLES (WINHTTP_CALLBACK_STATUS_HANDLE_CREATED | WINHTTP_CALLBACK_STATUS_HANDLE_CLOSING) +#define WINHTTP_CALLBACK_FLAG_DETECTING_PROXY WINHTTP_CALLBACK_STATUS_DETECTING_PROXY +#define WINHTTP_CALLBACK_FLAG_REDIRECT WINHTTP_CALLBACK_STATUS_REDIRECT +#define WINHTTP_CALLBACK_FLAG_INTERMEDIATE_RESPONSE WINHTTP_CALLBACK_STATUS_INTERMEDIATE_RESPONSE +#define WINHTTP_CALLBACK_FLAG_SECURE_FAILURE WINHTTP_CALLBACK_STATUS_SECURE_FAILURE +#define WINHTTP_CALLBACK_FLAG_SENDREQUEST_COMPLETE WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE +#define WINHTTP_CALLBACK_FLAG_HEADERS_AVAILABLE WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE +#define WINHTTP_CALLBACK_FLAG_DATA_AVAILABLE WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE +#define WINHTTP_CALLBACK_FLAG_READ_COMPLETE WINHTTP_CALLBACK_STATUS_READ_COMPLETE +#define WINHTTP_CALLBACK_FLAG_WRITE_COMPLETE WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE +#define WINHTTP_CALLBACK_FLAG_REQUEST_ERROR WINHTTP_CALLBACK_STATUS_REQUEST_ERROR +#define WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS (WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE | WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE \ + | WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE | WINHTTP_CALLBACK_STATUS_READ_COMPLETE \ + | WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE | WINHTTP_CALLBACK_STATUS_REQUEST_ERROR) +#define WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS 0xffffffff +#define WINHTTP_INVALID_STATUS_CALLBACK ((WINHTTP_STATUS_CALLBACK)(-1L)) + +#define API_RECEIVE_RESPONSE (1) +#define API_QUERY_DATA_AVAILABLE (2) +#define API_READ_DATA (3) +#define API_WRITE_DATA (4) +#define API_SEND_REQUEST (5) + +#define WINHTTP_HANDLE_TYPE_SESSION 1 +#define WINHTTP_HANDLE_TYPE_CONNECT 2 +#define WINHTTP_HANDLE_TYPE_REQUEST 3 + +#define WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED 0x00000001 +#define WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT 0x00000002 +#define WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED 0x00000004 +#define WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA 0x00000008 +#define WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID 0x00000010 +#define WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID 0x00000020 +#define WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE 0x00000040 +#define WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR 0x80000000 + +#define WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 0x00000008 +#define WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 0x00000020 +#define WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 0x00000080 +#define WINHTTP_FLAG_SECURE_PROTOCOL_ALL (WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 | WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1) + +#define WINHTTP_AUTH_SCHEME_BASIC 0x00000001 +#define WINHTTP_AUTH_SCHEME_NTLM 0x00000002 +#define WINHTTP_AUTH_SCHEME_PASSPORT 0x00000004 +#define WINHTTP_AUTH_SCHEME_DIGEST 0x00000008 +#define WINHTTP_AUTH_SCHEME_NEGOTIATE 0x00000010 + +#define WINHTTP_AUTH_TARGET_SERVER 0x00000000 +#define WINHTTP_AUTH_TARGET_PROXY 0x00000001 + +#define WINHTTP_TIME_FORMAT_BUFSIZE 62 + +typedef struct +{ + DWORD dwStructSize; + LPWSTR lpszScheme; + DWORD dwSchemeLength; + INTERNET_SCHEME nScheme; + LPWSTR lpszHostName; + DWORD dwHostNameLength; + INTERNET_PORT nPort; + LPWSTR lpszUserName; + DWORD dwUserNameLength; + LPWSTR lpszPassword; + DWORD dwPasswordLength; + LPWSTR lpszUrlPath; + DWORD dwUrlPathLength; + LPWSTR lpszExtraInfo; + DWORD dwExtraInfoLength; +} URL_COMPONENTS, *LPURL_COMPONENTS; +typedef URL_COMPONENTS URL_COMPONENTSW; +typedef LPURL_COMPONENTS LPURL_COMPONENTSW; + +typedef struct +{ + DWORD_PTR dwResult; + DWORD dwError; +} WINHTTP_ASYNC_RESULT, *LPWINHTTP_ASYNC_RESULT; + +typedef struct +{ + FILETIME ftExpiry; + FILETIME ftStart; + LPWSTR lpszSubjectInfo; + LPWSTR lpszIssuerInfo; + LPWSTR lpszProtocolName; + LPWSTR lpszSignatureAlgName; + LPWSTR lpszEncryptionAlgName; + DWORD dwKeySize; +} WINHTTP_CERTIFICATE_INFO; + +typedef struct +{ + DWORD dwAccessType; + LPCWSTR lpszProxy; + LPCWSTR lpszProxyBypass; +} WINHTTP_PROXY_INFO, *LPWINHTTP_PROXY_INFO; +typedef WINHTTP_PROXY_INFO WINHTTP_PROXY_INFOW; +typedef LPWINHTTP_PROXY_INFO LPWINHTTP_PROXY_INFOW; + +typedef struct +{ + BOOL fAutoDetect; + LPWSTR lpszAutoConfigUrl; + LPWSTR lpszProxy; + LPWSTR lpszProxyBypass; +} WINHTTP_CURRENT_USER_IE_PROXY_CONFIG; + +typedef VOID (CALLBACK *WINHTTP_STATUS_CALLBACK)(HINTERNET,DWORD_PTR,DWORD,LPVOID,DWORD); + +typedef struct +{ + DWORD dwFlags; + DWORD dwAutoDetectFlags; + LPCWSTR lpszAutoConfigUrl; + LPVOID lpvReserved; + DWORD dwReserved; + BOOL fAutoLogonIfChallenged; +} WINHTTP_AUTOPROXY_OPTIONS; + +typedef struct +{ + DWORD dwMajorVersion; + DWORD dwMinorVersion; +} HTTP_VERSION_INFO, *LPHTTP_VERSION_INFO; + + +#ifdef __cplusplus +extern "C" { +#endif + +BOOL WINAPI WinHttpAddRequestHeaders(HINTERNET,LPCWSTR,DWORD,DWORD); +BOOL WINAPI WinHttpDetectAutoProxyConfigUrl(DWORD,LPWSTR*); +BOOL WINAPI WinHttpCheckPlatform(void); +BOOL WINAPI WinHttpCloseHandle(HINTERNET); +HINTERNET WINAPI WinHttpConnect(HINTERNET,LPCWSTR,INTERNET_PORT,DWORD); +BOOL WINAPI WinHttpCrackUrl(LPCWSTR,DWORD,DWORD,LPURL_COMPONENTS); +BOOL WINAPI WinHttpCreateUrl(LPURL_COMPONENTS,DWORD,LPWSTR,LPDWORD); +BOOL WINAPI WinHttpGetDefaultProxyConfiguration(WINHTTP_PROXY_INFO*); +BOOL WINAPI WinHttpGetIEProxyConfigForCurrentUser(WINHTTP_CURRENT_USER_IE_PROXY_CONFIG*); +BOOL WINAPI WinHttpGetProxyForUrl(HINTERNET,LPCWSTR,WINHTTP_AUTOPROXY_OPTIONS*,WINHTTP_PROXY_INFO*); +HINTERNET WINAPI WinHttpOpen(LPCWSTR,DWORD,LPCWSTR,LPCWSTR,DWORD); +HINTERNET WINAPI WinHttpOpenRequest(HINTERNET,LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR*,DWORD); +BOOL WINAPI WinHttpQueryAuthParams(HINTERNET,DWORD,LPVOID*); +BOOL WINAPI WinHttpQueryAuthSchemes(HINTERNET,LPDWORD,LPDWORD,LPDWORD); +BOOL WINAPI WinHttpQueryDataAvailable(HINTERNET,LPDWORD); +BOOL WINAPI WinHttpQueryHeaders(HINTERNET,DWORD,LPCWSTR,LPVOID,LPDWORD,LPDWORD); +BOOL WINAPI WinHttpQueryOption(HINTERNET,DWORD,LPVOID,LPDWORD); +BOOL WINAPI WinHttpReadData(HINTERNET,LPVOID,DWORD,LPDWORD); +BOOL WINAPI WinHttpReceiveResponse(HINTERNET,LPVOID); +BOOL WINAPI WinHttpSendRequest(HINTERNET,LPCWSTR,DWORD,LPVOID,DWORD,DWORD,DWORD_PTR); +BOOL WINAPI WinHttpSetDefaultProxyConfiguration(WINHTTP_PROXY_INFO*); +BOOL WINAPI WinHttpSetCredentials(HINTERNET,DWORD,DWORD,LPCWSTR,LPCWSTR,LPVOID); +BOOL WINAPI WinHttpSetOption(HINTERNET,DWORD,LPVOID,DWORD); +WINHTTP_STATUS_CALLBACK WINAPI WinHttpSetStatusCallback(HINTERNET,WINHTTP_STATUS_CALLBACK,DWORD,DWORD_PTR); +BOOL WINAPI WinHttpSetTimeouts(HINTERNET,int,int,int,int); +BOOL WINAPI WinHttpTimeFromSystemTime(CONST SYSTEMTIME *,LPWSTR); +BOOL WINAPI WinHttpTimeToSystemTime(LPCWSTR,SYSTEMTIME*); +BOOL WINAPI WinHttpWriteData(HINTERNET,LPCVOID,DWORD,LPDWORD); + +// These are the function calls we'll need for Rufus without going through an import lib +typedef BOOL (WINAPI *WinHttpCrackUrl_t)(LPCWSTR,DWORD,DWORD,LPURL_COMPONENTS); +typedef HINTERNET (WINAPI *WinHttpOpen_t)(LPCWSTR,DWORD,LPCWSTR,LPCWSTR,DWORD); +typedef HINTERNET (WINAPI *WinHttpConnect_t)(HINTERNET,LPCWSTR,INTERNET_PORT,DWORD); +typedef HINTERNET (WINAPI *WinHttpOpenRequest_t)(HINTERNET,LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR*,DWORD); +typedef BOOL (WINAPI *WinHttpSendRequest_t)(HINTERNET,LPCWSTR,DWORD,LPVOID,DWORD,DWORD,DWORD_PTR); +typedef BOOL (WINAPI *WinHttpReceiveResponse_t)(HINTERNET,LPVOID); +typedef BOOL (WINAPI *WinHttpQueryHeaders_t)(HINTERNET,DWORD,LPCWSTR,LPVOID,LPDWORD,LPDWORD); +typedef BOOL (WINAPI *WinHttpQueryDataAvailable_t)(HINTERNET,LPDWORD); +typedef BOOL (WINAPI *WinHttpReadData_t)(HINTERNET,LPVOID,DWORD,LPDWORD); +typedef BOOL (WINAPI *WinHttpCloseHandle_t)(HINTERNET); + +#ifdef __cplusplus +} +#endif diff --git a/src/rufus.c b/src/rufus.c index 6ea4327e..6e9539a5 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -60,7 +60,8 @@ float fScale = 1.0f; int default_fs; HWND hDeviceList, hCapacity, hFileSystem, hClusterSize, hLabel, hDOSType, hNBPasses; HWND hISOProgressDlg = NULL, hISOProgressBar, hISOFileName; -BOOL bWithFreeDOS; +BOOL bWithFreeDOS, use_own_vesamenu = FALSE; +int rufus_version[4]; extern char szStatusMessage[256]; static HANDLE format_thid = NULL; @@ -1008,7 +1009,8 @@ BOOL CALLBACK ISOProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) PrintStatus(0, FALSE, "Cancelling - Please wait..."); uprintf("Cancelling (from ISO proc.)\n"); EnableWindow(GetDlgItem(hISOProgressDlg, IDC_ISO_ABORT), FALSE); - EnableWindow(GetDlgItem(hMainDialog, IDCANCEL), FALSE); + if (format_thid != NULL) + EnableWindow(GetDlgItem(hMainDialog, IDCANCEL), FALSE); // Start a timer to detect blocking operations during ISO file extraction if (iso_blocking_status >= 0) { last_iso_blocking_status = iso_blocking_status; @@ -1020,30 +1022,58 @@ BOOL CALLBACK ISOProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) return TRUE; } return FALSE; -} +} // The scanning process can be blocking for message processing => use a thread DWORD WINAPI ISOScanThread(LPVOID param) { int i; + FILE* fd; + const char* vesamenu_filename = "vesamenu.c32"; if (iso_path == NULL) goto out; PrintStatus(0, TRUE, "Scanning ISO image...\n"); if (!ExtractISO(iso_path, "", TRUE)) { + SendMessage(hISOProgressDlg, UM_ISO_EXIT, 0, 0); PrintStatus(0, TRUE, "Failed to scan ISO image."); safe_free(iso_path); goto out; } - uprintf("ISO label: '%s'\n size: %lld bytes, 4GB:%c, bootmgr:%c, isolinux:%c\n", - iso_report.label, iso_report.projected_size, - iso_report.has_4GB_file?'Y':'N', iso_report.has_bootmgr?'Y':'N', iso_report.has_isolinux?'Y':'N'); + uprintf("ISO label: '%s'\n size: %lld bytes, 4GB:%c, bootmgr:%c, isolinux:%c, old vesa:%c\n", + iso_report.label, iso_report.projected_size, iso_report.has_4GB_file?'Y':'N', + iso_report.has_bootmgr?'Y':'N', iso_report.has_isolinux?'Y':'N', iso_report.has_old_vesamenu?'Y':'N'); if ((!iso_report.has_bootmgr) && (!iso_report.has_isolinux)) { MessageBoxU(hMainDialog, "This version of Rufus only supports bootable ISOs\n" "based on 'bootmgr' or 'isolinux'.\n" "This ISO image doesn't appear to use either...", "Unsupported ISO", MB_OK|MB_ICONINFORMATION); safe_free(iso_path); } else { + if (iso_report.has_old_vesamenu) { + fd = fopen(vesamenu_filename, "rb"); + if (fd != NULL) { + // If a file already exists in the current directory, use that one + uprintf("Will replace obsolete '%s' from ISO with the one found in current directory\n", vesamenu_filename); + fclose(fd); + use_own_vesamenu = TRUE; + } else { + PrintStatus(0, FALSE, "Obsolete vesamenu.c32 detected"); + if (MessageBoxA(hMainDialog, + "This ISO image seems to use an obsolete version of vesamenu.c32\n" + "that may prevent boot menus from displaying properly...\n\n" + "Rufus can fix this issue by downloading a newer version for you:\n" + "- Select 'Yes' to connect to the internet and replace the file.\n" + "- Select 'No' to leave the existing ISO file unmodified.\n" + "If you don't know what to do, you should select 'Yes'.\n\n" + "Note: the file will be downloaded in the current directory. Once a\n" + "vesamenu.c32 exists there, it will always be used as replacement.\n", "Replace vesamenu.c32?", + MB_YESNO|MB_ICONWARNING) == IDYES) { + if (DownloadFile(VESAMENU_URL, vesamenu_filename)) + use_own_vesamenu = TRUE; + } + } + } + // Enable DOS, set DOS Type to ISO (last item) and set FS accordingly CheckDlgButton(hMainDialog, IDC_DOS, BST_CHECKED); SetFSFromISO(); @@ -1061,18 +1091,10 @@ DWORD WINAPI ISOScanThread(LPVOID param) } out: + SendMessage(hISOProgressDlg, UM_ISO_EXIT, 0, 0); ExitThread(0); } -// Helper function to obtain a handle to a DLL -static __inline HMODULE GetDLLHandle(char* szDLLName) -{ - HMODULE h = NULL; - if ((h = GetModuleHandleA(szDLLName)) == NULL) - h = LoadLibraryA(szDLLName); - return h; -} - void InitDialog(HWND hDlg) { // MinGW fails to link those @@ -1097,9 +1119,9 @@ void InitDialog(HWND hDlg) } bi = {0}; // BUTTON_IMAGELIST HINSTANCE hDllInst; HDC hDC; - int i16; + int i, i16; HICON hSmallIcon, hBigIcon; - char tmp[128]; + char tmp[128], *token; #ifdef RUFUS_TEST ShowWindow(GetDlgItem(hDlg, IDC_TEST), SW_SHOW); @@ -1129,6 +1151,13 @@ void InitDialog(HWND hDlg) SendMessage (hDlg, WM_SETICON, ICON_SMALL, (LPARAM)hSmallIcon); hBigIcon = (HICON)LoadImage(hMainInstance, MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 32, 32, 0); SendMessage (hDlg, WM_SETICON, ICON_BIG, (LPARAM)hBigIcon); + GetWindowTextA(hDlg, tmp, sizeof(tmp)); + // Count of Microsoft for making it more attractive to read a + // version using strtok() than using GetFileVersionInfo() + token = strtok(tmp, "v"); + for (i=0; (i<4) && ((token = strtok(NULL, ".")) != NULL); i++) + rufus_version[i] = atoi(token); + // Update the title if we have FreeDOS support if (bWithFreeDOS) { GetWindowTextA(hDlg, &tmp[15], sizeof(tmp)-15); diff --git a/src/rufus.h b/src/rufus.h index 391f1075..f253a59c 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -40,6 +40,7 @@ #define SEPARATOR_GREY RGB(223,223,223) #define RUFUS_URL "http://rufus.akeo.ie" #define BUG_URL "https://github.com/pbatard/rufus/issues" +#define VESAMENU_URL "http://cloud.github.com/downloads/pbatard/rufus/vesamenu.c32" #define IGNORE_RETVAL(expr) do { (void)(expr); } while(0) #ifndef ARRAYSIZE #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) @@ -149,6 +150,7 @@ typedef struct { BOOL has_bootmgr; BOOL has_isolinux; BOOL has_autorun; + BOOL has_old_vesamenu; } RUFUS_ISO_REPORT; /* @@ -164,9 +166,10 @@ extern char* iso_path; extern DWORD FormatStatus; extern RUFUS_DRIVE_INFO SelectedDrive; extern const int nb_steps[FS_MAX]; -extern BOOL bWithFreeDOS; +extern BOOL bWithFreeDOS, use_own_vesamenu; extern RUFUS_ISO_REPORT iso_report; extern int64_t iso_blocking_status; +extern int rufus_version[4]; /* * Shared prototypes @@ -194,7 +197,8 @@ extern BOOL UnmountDrive(HANDLE hDrive); extern BOOL CreateProgress(void); extern BOOL SetAutorun(const char* path); extern char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_desc); -extern LONG GetEntryWidth(HWND hDropDown, const char *entry); +extern LONG GetEntryWidth(HWND hDropDown, const char* entry); +extern BOOL DownloadFile(const char* url, const char* file); __inline static BOOL UnlockDrive(HANDLE hDrive) { @@ -213,7 +217,30 @@ extern void StrArrayAdd(StrArray* arr, const char* str); extern void StrArrayClear(StrArray* arr); extern void StrArrayDestroy(StrArray* arr); - +/* + * typedefs for the function prototypes. Use the something like: + * PF_DECL(FormatEx); + * which translates to: + * FormatEx_t pfFormatEx = NULL; + * in your code, to declare the entrypoint and then use: + * PF_INIT(FormatEx, fmifs); + * which translates to: + * pfFormatEx = (FormatEx_t) GetProcAddress(GetDLLHandle("fmifs"), "FormatEx"); + * to make it accessible. + */ +static __inline HMODULE GetDLLHandle(char* szDLLName) +{ + HMODULE h = NULL; + if ((h = GetModuleHandleA(szDLLName)) == NULL) + h = LoadLibraryA(szDLLName); + return h; +} +#define PF_DECL(proc) proc##_t pf##proc = NULL +#define PF_INIT(proc, dllname) pf##proc = (proc##_t) GetProcAddress(GetDLLHandle(#dllname), #proc) +#define PF_INIT_OR_OUT(proc, dllname) \ + PF_INIT(proc, dllname); if (pf##proc == NULL) { \ + uprintf("unable to access %s DLL: %s", #dllname, \ + WindowsErrorString()); goto out; } /* Clang/MinGW32 has an issue with intptr_t */ #ifndef _UINTPTR_T_DEFINED @@ -232,7 +259,6 @@ typedef struct { ULONG PartitionNumber; } STORAGE_DEVICE_NUMBER_REDEF; - /* Custom application errors */ #define FAC(f) (f<<16) #define APPERR(err) (APPLICATION_ERROR_MASK|err) @@ -245,3 +271,14 @@ typedef struct { #define ERROR_ISO_SCAN 0x1207 #define ERROR_ISO_EXTRACT 0x1208 #define ERROR_CANT_REMOUNT_VOLUME 0x1209 + +/* More niceties */ +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif +#ifndef PBS_MARQUEE +#define PBS_MARQUEE 0x08 +#endif +#ifndef PBM_SETMARQUEE +#define PBM_SETMARQUEE (WM_USER+10) +#endif \ No newline at end of file diff --git a/src/rufus.rc b/src/rufus.rc index 65d7a2c5..771bec22 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 206, 289 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW -CAPTION "Rufus v1.1.5.151" +CAPTION "Rufus v1.1.5.152" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,94,248,50,14 @@ -73,7 +73,7 @@ BEGIN DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP CONTROL "http://rufus.akeo.ie",IDC_ABOUT_RUFUS_URL, "SysLink",WS_TABSTOP,46,47,114,9 - LTEXT "Version 1.1.5 (Build 151)",IDC_STATIC,46,19,78,8 + LTEXT "Version 1.1.5 (Build 152)",IDC_STATIC,46,19,78,8 PUSHBUTTON "License...",IDC_ABOUT_LICENSE,46,175,50,14,WS_GROUP EDITTEXT IDC_ABOUT_COPYRIGHTS,46,107,235,63,ES_MULTILINE | ES_READONLY | WS_VSCROLL LTEXT "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8 @@ -223,8 +223,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,1,5,151 - PRODUCTVERSION 1,1,5,151 + FILEVERSION 1,1,5,152 + PRODUCTVERSION 1,1,5,152 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -241,13 +241,13 @@ BEGIN BEGIN VALUE "CompanyName", "akeo.ie" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "1.1.5.151" + VALUE "FileVersion", "1.1.5.152" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "1.1.5.151" + VALUE "ProductVersion", "1.1.5.152" END END BLOCK "VarFileInfo" diff --git a/src/stdio.c b/src/stdio.c index d4f4169e..060ed838 100644 --- a/src/stdio.c +++ b/src/stdio.c @@ -108,7 +108,7 @@ static char err_string[256]; safe_sprintf(err_string, sizeof(err_string), "[0x%08X] ", error_code); - size = FormatMessageU(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error_code, + size = FormatMessageU(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &err_string[strlen(err_string)], sizeof(err_string)-(DWORD)strlen(err_string), NULL); if (size == 0) { diff --git a/src/stdlg.c b/src/stdlg.c index 6539b753..2ac69f6c 100644 --- a/src/stdlg.c +++ b/src/stdlg.c @@ -104,7 +104,6 @@ void DetectWindowsVersion(void) } } - /* * String array manipulation */