diff --git a/src/.msvc/rufus_2010.vcxproj b/src/.msvc/rufus_2010.vcxproj index 043a1aa6..ba941f03 100644 --- a/src/.msvc/rufus_2010.vcxproj +++ b/src/.msvc/rufus_2010.vcxproj @@ -165,6 +165,7 @@ + diff --git a/src/.msvc/rufus_2010.vcxproj.filters b/src/.msvc/rufus_2010.vcxproj.filters index 892b67eb..9777c4de 100644 --- a/src/.msvc/rufus_2010.vcxproj.filters +++ b/src/.msvc/rufus_2010.vcxproj.filters @@ -48,6 +48,9 @@ Source Files + + Source Files + diff --git a/src/.msvc/rufus_sources b/src/.msvc/rufus_sources index b53984cb..3f9490b3 100644 --- a/src/.msvc/rufus_sources +++ b/src/.msvc/rufus_sources @@ -33,6 +33,7 @@ SOURCES=rufus.c \ stdio.c \ stdlg.c \ icon.c \ + parser.c \ iso.c \ dos.c \ dos_locale.c \ diff --git a/src/Makefile.am b/src/Makefile.am index b9571418..6f0f6471 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 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 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 ecb00b5e..94bd6cc4 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -44,7 +44,7 @@ CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = PROGRAMS = $(noinst_PROGRAMS) am_rufus_OBJECTS = rufus-drive.$(OBJEXT) rufus-icon.$(OBJEXT) \ - rufus-iso.$(OBJEXT) rufus-dos.$(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) \ @@ -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 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 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 \ @@ -262,6 +262,14 @@ rufus-icon.obj: icon.c $(AM_V_CC) @AM_BACKSLASH@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-icon.obj `if test -f 'icon.c'; then $(CYGPATH_W) 'icon.c'; else $(CYGPATH_W) '$(srcdir)/icon.c'; fi` +rufus-parser.o: parser.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-parser.o `test -f 'parser.c' || echo '$(srcdir)/'`parser.c + +rufus-parser.obj: parser.c + $(AM_V_CC) @AM_BACKSLASH@ + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-parser.obj `if test -f 'parser.c'; then $(CYGPATH_W) 'parser.c'; else $(CYGPATH_W) '$(srcdir)/parser.c'; fi` + rufus-iso.o: iso.c $(AM_V_CC) @AM_BACKSLASH@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-iso.o `test -f 'iso.c' || echo '$(srcdir)/'`iso.c diff --git a/src/drive.c b/src/drive.c index fa0943ba..b5843b48 100644 --- a/src/drive.c +++ b/src/drive.c @@ -34,6 +34,8 @@ * Globals */ RUFUS_DRIVE_INFO SelectedDrive; +extern BOOL enable_fixed_disks; +extern char* get_token_data(const char* filename, const char* token); /* * Open a drive or volume with optional write and lock access @@ -103,7 +105,7 @@ HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BO drive_type = GetDriveTypeA(drive); // NB: the HP utility allows drive_type == DRIVE_FIXED, which we don't really really want for now // TODO: allow fixed drives after partitioning/preserving of existing partitions has been sorted out - if (drive_type != DRIVE_REMOVABLE) + if ((drive_type != DRIVE_REMOVABLE) && ((!enable_fixed_disks) || (drive_type != DRIVE_FIXED))) continue; safe_sprintf(logical_drive, sizeof(logical_drive), "\\\\.\\%c:", drive[0]); @@ -149,6 +151,7 @@ out: BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label) { HANDLE hDrive; + char AutorunPath[] = "#:\\autorun.inf", *AutorunLabel; wchar_t wDrivePath[] = L"#:\\"; wchar_t wVolumeLabel[MAX_PATH+1]; static char VolumeLabel[MAX_PATH+1]; @@ -159,9 +162,17 @@ BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label) if (hDrive == INVALID_HANDLE_VALUE) return FALSE; safe_closehandle(hDrive); + AutorunPath[0] = *letter; wDrivePath[0] = *letter; - if (GetVolumeInformationW(wDrivePath, wVolumeLabel, sizeof(wVolumeLabel), + // Try to read an extended label from autorun first. Fallback to regular label if not found. + AutorunLabel = get_token_data(AutorunPath, "label"); + if (AutorunLabel != NULL) { + uprintf("Using autorun.inf label for device %c:\n", *letter); + strncpy(VolumeLabel, AutorunLabel, sizeof(VolumeLabel)); + safe_free(AutorunLabel); + *label = VolumeLabel; + } else if (GetVolumeInformationW(wDrivePath, wVolumeLabel, sizeof(wVolumeLabel), NULL, NULL, NULL, NULL, 0) && *wVolumeLabel) { wchar_to_utf8_no_alloc(wVolumeLabel, VolumeLabel, sizeof(VolumeLabel)); *label = VolumeLabel; diff --git a/src/format.c b/src/format.c index 932b1b36..22b24339 100644 --- a/src/format.c +++ b/src/format.c @@ -656,8 +656,9 @@ DWORD WINAPI FormatThread(LPVOID param) if (iso_path != NULL) { PrintStatus(0, TRUE, "Copying ISO files..."); drive_name[2] = 0; - if ( (!ExtractISO(iso_path, drive_name, FALSE)) && (!FormatStatus)) { - FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY; + if (!ExtractISO(iso_path, drive_name, FALSE)) { + if (!FormatStatus) + FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY; goto out; } } diff --git a/src/iso.c b/src/iso.c index 99680523..ee375a3a 100644 --- a/src/iso.c +++ b/src/iso.c @@ -71,6 +71,8 @@ static uint64_t total_blocks, nb_blocks; static BOOL scan_only = FALSE; static StrArray config_path; +extern char* replace_in_token_data(const char* filename, const char* token, const char* src, const char* rep); + // TODO: Timestamp & permissions preservation // Convert a file size to human readable @@ -102,55 +104,6 @@ static void log_handler (cdio_log_level_t level, const char *message) } } -/* - * Workaround for isolinux config files requiring an ISO label for kernel - * append that may be different from our USB label. - * NB: this is intended as a quick-and-dirty workaround, because it is the - * distro creator's job to make their config and labels also work with USB. - * As such, this process may fail if: - * - the label is on the block size limit, for cfg files of more than 2KB - * - the user changed the label to one that is larger than the one from the cfg - * - the cfg is weird (more than one label on the same line, etc.) - */ -static void process_config(char* buf, size_t buf_size, const char* cfg_name) -{ - char last_char, eol_char, *label; - size_t i, j, k; - - // Don't apply workaround if USB label is the same or longer than ISO - if ( (strcmp(iso_report.label, iso_report.usb_label) == 0) - || (strlen(iso_report.label) < strlen(iso_report.usb_label)) ) - return; - - // Make sure our buffer is NUL terminated - if (buf_size >= UDF_BLOCKSIZE) // UDF_BLOCKSIZE = ISO_BLOCKSIZE = 2048 - buf_size = UDF_BLOCKSIZE-1; - last_char = buf[buf_size]; - buf[buf_size] = 0; - - for (i=0; i '%s'\n", psz_fullpath, iso_report.label, iso_report.usb_label); + } } safe_free(psz_fullpath); } @@ -363,8 +320,6 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) goto out; } buf_size = (DWORD)MIN(i_file_length, ISO_BLOCKSIZE); - if (is_syslinux_cfg) - process_config((char*)buf, (size_t)buf_size, psz_fullpath); ISO_BLOCKING(s = WriteFile(file_handle, buf, buf_size, &wr_size, NULL)); if ((!s) || (buf_size != wr_size)) { uprintf(" Error writing file: %s\n", WindowsErrorString()); @@ -376,6 +331,10 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) } } ISO_BLOCKING(safe_closehandle(file_handle)); + if (is_syslinux_cfg) { + if (replace_in_token_data(psz_fullpath, "append", iso_report.label, iso_report.usb_label) != NULL) + uprintf("Patched %s: '%s' -> '%s'\n", psz_fullpath, iso_report.label, iso_report.usb_label); + } } } r = 0; @@ -506,7 +465,8 @@ out: uprintf("Created: %s\n", syslinux_path); } } - fclose(fd); + if (fd != NULL) + fclose(fd); } SendMessage(hISOProgressDlg, UM_ISO_EXIT, 0, 0); if (p_iso != NULL) diff --git a/src/parser.c b/src/parser.c new file mode 100644 index 00000000..2796f875 --- /dev/null +++ b/src/parser.c @@ -0,0 +1,268 @@ +/* + * Rufus: The Reliable USB Formatting Utility + * Elementary Unicode compliant find/replace parser + * Copyright (c) 2012 Pete Batard + * + * 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 +#include +#include +#include + +#include "rufus.h" +#include "msapi_utf8.h" + +// Parse a file (ANSI or UTF-8 or UTF-16) and return the data for the first occurence of 'token' +// The parsed line is of the form: [ ]token[ ]=[ ]["]data["] +// The returned string is UTF-8 and MUST be freed by the caller +char* get_token_data(const char* filename, const char* token) +{ + wchar_t *wtoken = NULL, *wfilename = NULL; + wchar_t wspace[] = L" \t"; + wchar_t weol[] = L"\r\n"; + wchar_t buf[1024]; + FILE* fd = NULL; + size_t i, r; + char *ret = NULL; + + if ((filename == NULL) || (token == NULL)) + return NULL; + if ((filename[0] == 0) || (token[0] == 0)) + return NULL; + + wfilename = utf8_to_wchar(filename); + if (wfilename == NULL) { + uprintf("Could not convert '%s' to UTF-16\n", filename); + goto out; + } + wtoken = utf8_to_wchar(token); + if (wfilename == NULL) { + uprintf("Could not convert '%s' to UTF-16\n", token); + goto out; + } + fd = _wfopen(wfilename, L"r, ccs=UNICODE"); + if (fd == NULL) { + uprintf("Could not open file '%s'\n", filename); + goto out; + } + + // Process individual lines. NUL is always appended. + // Ideally, we'd check that our buffer fits the line + while (fgetws(buf, ARRAYSIZE(buf), fd) != NULL) { + + // Eliminate trailing EOL characters + buf[wcscspn(buf, weol)] = 0; + + i = 0; + + // Skip leading spaces + i += wcsspn(&buf[i], wspace); + + // Our token should begin a line + if (_wcsnicmp(&buf[i], wtoken, wcslen(wtoken)) != 0) + continue; + + // Token was found, move past token + i += wcslen(wtoken); + + // Skip spaces + i += wcsspn(&buf[i], wspace); + + // Check for an equal sign + if (buf[i] != L'=') + continue; + i++; + + // Skip spaces after equal sign + i += wcsspn(&buf[i], wspace); + + // eliminate leading quote, if it exists + if (buf[i] == L'"') + i++; + + // Keep the starting pos of our data + r = i; + + // locate end of string or quote + while ((buf[i] != 0) && (buf[i] != L'"')) + i++; + buf[i] = 0; + ret = wchar_to_utf8(&buf[r]); + break; + } + +out: + if (fd != NULL) + fclose(fd); + safe_free(wfilename); + safe_free(wtoken); + return ret; +} + +// Search for a specific 'src' substring the data for all occurences of 'token', and replace +// if with 'rep'. File can be ANSI or UNICODE and is overwritten. Parameters are UTF-8. +// The parsed line is of the form: [ ]token[ ]data +// Returns a pointer to rep if replacement occured, NULL otherwise +char* replace_in_token_data(const char* filename, const char* token, const char* src, const char* rep) +{ + const wchar_t* outmode[] = { L"w", L"w, ccs=UTF-8", L"w, ccs=UTF-16LE" }; + wchar_t *wtoken = NULL, *wfilename = NULL, *wtmpname = NULL, *wsrc = NULL, *wrep = NULL, bom = 0; + wchar_t wspace[] = L" \t"; + wchar_t buf[1024], *torep; + FILE *fd_in = NULL, *fd_out = NULL; + size_t i, size; + int mode; + char *ret = NULL, tmp[2]; + + if ((filename == NULL) || (token == NULL) || (src == NULL) || (rep == NULL)) + return NULL; + if ((filename[0] == 0) || (token[0] == 0) || (src[0] == 0) || (rep[0] == 0)) + return NULL; + if (strcmp(src, rep) == 0) // No need for processing is source is same as replacement + return NULL; + + wfilename = utf8_to_wchar(filename); + if (wfilename == NULL) { + uprintf("Could not convert '%s' to UTF-16\n", filename); + goto out; + } + wtoken = utf8_to_wchar(token); + if (wfilename == NULL) { + uprintf("Could not convert '%s' to UTF-16\n", token); + goto out; + } + wsrc = utf8_to_wchar(src); + if (wsrc == NULL) { + uprintf("Could not convert '%s' to UTF-16\n", src); + goto out; + } + wrep = utf8_to_wchar(rep); + if (wsrc == NULL) { + uprintf("Could not convert '%s' to UTF-16\n", rep); + goto out; + } + + fd_in = _wfopen(wfilename, L"r, ccs=UNICODE"); + if (fd_in == NULL) { + uprintf("Could not open file '%s'\n", filename); + goto out; + } + // Check the input file's BOM and create an output file with the same + fread(&bom, sizeof(bom), 1, fd_in); + switch(bom) { + case 0xFEFF: + mode = 2; // UTF-16 (LE) + break; + case 0xBBEF: // Yeah, the UTF-8 BOM is really 0xEF,0xBB,0xBF, but + mode = 1; // find me a non UTF-8 file that actually begins with "ï»" + break; + default: + mode = 0; // ANSI + break; + } + fseek(fd_in, 0, SEEK_SET); +// uprintf("'%s' was detected as %s\n", filename, +// (mode==0)?"ANSI/UTF8 (no BOM)":((mode==1)?"UTF8 (with BOM)":"UTF16 (with BOM")); + + + wtmpname = (wchar_t*)calloc(wcslen(wfilename)+2, sizeof(wchar_t)); + if (wtmpname == NULL) { + uprintf("Could not allocate space for temporary output name\n"); + goto out; + } + wcscpy(wtmpname, wfilename); + wtmpname[wcslen(wtmpname)] = '~'; + + fd_out = _wfopen(wtmpname, outmode[mode]); + if (fd_out == NULL) { + uprintf("Could not open temporary output file %s~\n", filename); + goto out; + } + + // Process individual lines. NUL is always appended. + while (fgetws(buf, ARRAYSIZE(buf), fd_in) != NULL) { + + i = 0; + + // Skip leading spaces + i += wcsspn(&buf[i], wspace); + + // Our token should begin a line + if (_wcsnicmp(&buf[i], wtoken, wcslen(wtoken)) != 0) { + fputws(buf, fd_out); + continue; + } + + // Token was found, move past token + i += strlen(token); + + // Skip spaces + i += wcsspn(&buf[i], wspace); + + torep = wcsstr(&buf[i], wsrc); + if (torep == NULL) { + fputws(buf, fd_out); + continue; + } + + i = (torep-buf) + wcslen(wsrc); + *torep = 0; + fwprintf(fd_out, L"%s%s%s", buf, wrep, &buf[i]); + ret = (char*)rep; + } + +out: + if (fd_in != NULL) fclose(fd_in); + if (fd_out != NULL) fclose(fd_out); + + // If a replacement occured, delete existing file and use the new one + if (ret != NULL) { + // We're in Windows text mode => Remove CRs + fd_in = _wfopen(wtmpname, L"rb"); + fd_out = _wfopen(wfilename, L"wb"); + // Don't check fds + if ((fd_in != NULL) && (fd_out != NULL)) { + size = (mode==2)?2:1; + while(fread(tmp, size, 1, fd_in) == 1) { + if (tmp[0] != 0x0D) + fwrite(tmp, size, 1, fd_out); + } + fclose(fd_in); + fclose(fd_out); + } else { + uprintf("Dos2Unix conversion failed for %s - file will be unusable!\n", filename); + if (fd_in != NULL) fclose(fd_in); + if (fd_out != NULL) fclose(fd_out); + } + } + _wunlink(wtmpname); + safe_free(wfilename); + safe_free(wtmpname); + safe_free(wtoken); + safe_free(wsrc); + safe_free(wrep); + + return ret; +} diff --git a/src/rufus.c b/src/rufus.c index 1fe21b2b..04815f7d 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -46,6 +46,7 @@ static const char* ClusterSizeLabel[] = { "512 bytes", "1024 bytes","2048 bytes" "1024 kilobytes","2048 kilobytes","4096 kilobytes","8192 kilobytes","16 megabytes","32 megabytes" }; static BOOL existing_key = FALSE; // For LGP set/restore static BOOL iso_size_check = TRUE; +BOOL enable_fixed_disks = FALSE; /* * Globals @@ -535,6 +536,8 @@ static BOOL GetUSBDevices(DWORD devnum) STORAGE_DEVICE_NUMBER_REDEF device_number; DWORD size, i, j, datatype; HANDLE hDrive; + LONG maxwidth = 0; + RECT rect; char drive_letter; char *label, entry[MAX_PATH], buffer[MAX_PATH]; const char* usbstor_name = "USBSTOR"; @@ -544,6 +547,7 @@ static BOOL GetUSBDevices(DWORD devnum) IGNORE_RETVAL(ComboBox_ResetContent(hDeviceList)); StrArrayClear(&DriveID); StrArrayClear(&DriveLabel); + GetClientRect(hDeviceList, &rect); dev_info = SetupDiGetClassDevsA(&_GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); if (dev_info == INVALID_HANDLE_VALUE) { @@ -623,6 +627,7 @@ static BOOL GetUSBDevices(DWORD devnum) safe_sprintf(entry, sizeof(entry), "%s (%c:)", label, drive_letter); IGNORE_RETVAL(ComboBox_SetItemData(hDeviceList, ComboBox_AddStringU(hDeviceList, entry), device_number.DeviceNumber + DRIVE_INDEX_MIN)); + maxwidth = max(maxwidth, GetEntryWidth(hDeviceList, entry)); safe_closehandle(hDrive); safe_free(devint_detail_data); break; @@ -631,6 +636,9 @@ static BOOL GetUSBDevices(DWORD devnum) } SetupDiDestroyDeviceInfoList(dev_info); + // Adjust the Dropdown width to the maximum text size + SendMessage(hDeviceList, CB_SETDROPPEDWIDTH, (WPARAM)maxwidth, 0); + if (devnum >= DRIVE_INDEX_MIN) { for (i=0; i toggle detection of fixed disks + if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'F')) { + enable_fixed_disks = !enable_fixed_disks; + PrintStatus(0, FALSE, "Fixed disks detection %s", enable_fixed_disks?"enabled":"disabled"); + GetUSBDevices(0); + continue; + } #ifdef DISABLE_AUTORUN // Alt-D => Delete the NoDriveTypeAutorun key on exit (useful if the app crashed) if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'D')) { diff --git a/src/rufus.h b/src/rufus.h index 6703b547..8b8f476d 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -196,6 +196,7 @@ 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); __inline static BOOL UnlockDrive(HANDLE hDrive) { diff --git a/src/rufus.rc b/src/rufus.rc index 72ad14c9..1fc71007 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,12 +33,12 @@ 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.4.147" +CAPTION "Rufus v1.1.4.148" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN DEFPUSHBUTTON "Start",IDC_START,94,248,50,14 PUSHBUTTON "Close",IDCANCEL,148,248,50,14 - COMBOBOX IDC_DEVICE,8,17,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_DEVICE,8,17,190,33,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "Device",IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,9,6,22,8 COMBOBOX IDC_FILESYSTEM,8,75,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP LTEXT "File system",IDC_STATIC,9,64,51,10 @@ -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.4 (Build 147)",IDC_STATIC,46,19,78,8 + LTEXT "Version 1.1.4 (Build 148)",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,4,147 - PRODUCTVERSION 1,1,4,147 + FILEVERSION 1,1,4,148 + PRODUCTVERSION 1,1,4,148 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -241,13 +241,13 @@ BEGIN BEGIN VALUE "CompanyName", "akeo.ie" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "1.1.4.147" + VALUE "FileVersion", "1.1.4.148" 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.4.147" + VALUE "ProductVersion", "1.1.4.148" END END BLOCK "VarFileInfo" diff --git a/src/stdlg.c b/src/stdlg.c index d7f04fe6..6539b753 100644 --- a/src/stdlg.c +++ b/src/stdlg.c @@ -806,3 +806,29 @@ void DestroyAllTooltips(void) safe_free(ttlist[i].wstring); } } + +/* Compute the width of a device list entry */ +LONG GetEntryWidth(HWND hDropDown, const char *entry) +{ + HDC hDC; + HFONT hFont, hDefFont; + SIZE size; + WCHAR* wentry = NULL; + int len; + + hDC = GetDC(hDropDown); + hFont = (HFONT)SendMessage(hDropDown, WM_GETFONT, 0, 0); + if (hFont != NULL) + hDefFont = (HFONT)SelectObject(hDC, hFont); + + wentry = utf8_to_wchar(entry); + len = (int)wcslen(wentry)+1; + GetTextExtentPoint32W(hDC, wentry, len, &size); + + if (hFont != NULL) + SelectObject(hDC, hDefFont); + + ReleaseDC(hDropDown, hDC); + free(wentry); + return size.cx; +}