mirror of
https://github.com/pbatard/rufus.git
synced 2025-05-21 02:15:11 -04:00
[misc] improved label and config handling
* add readout and display of extended autorun.inf label if available * use improved isolinux config parsing * also fix an issue that could leave drive unmounted on forced removal * also add Alt-F cheatmode to toggle detection of fixed USB disks
This commit is contained in:
parent
1fce90dc7c
commit
3721b0a570
13 changed files with 363 additions and 68 deletions
|
@ -165,6 +165,7 @@
|
||||||
<ClCompile Include="..\dos.c" />
|
<ClCompile Include="..\dos.c" />
|
||||||
<ClCompile Include="..\icon.c" />
|
<ClCompile Include="..\icon.c" />
|
||||||
<ClCompile Include="..\iso.c" />
|
<ClCompile Include="..\iso.c" />
|
||||||
|
<ClCompile Include="..\parser.c" />
|
||||||
<ClCompile Include="..\rufus.c" />
|
<ClCompile Include="..\rufus.c" />
|
||||||
<ClCompile Include="..\stdio.c" />
|
<ClCompile Include="..\stdio.c" />
|
||||||
<ClCompile Include="..\stdlg.c" />
|
<ClCompile Include="..\stdlg.c" />
|
||||||
|
|
|
@ -48,6 +48,9 @@
|
||||||
<ClCompile Include="..\icon.c">
|
<ClCompile Include="..\icon.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\parser.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\rufus.h">
|
<ClInclude Include="..\rufus.h">
|
||||||
|
|
|
@ -33,6 +33,7 @@ SOURCES=rufus.c \
|
||||||
stdio.c \
|
stdio.c \
|
||||||
stdlg.c \
|
stdlg.c \
|
||||||
icon.c \
|
icon.c \
|
||||||
|
parser.c \
|
||||||
iso.c \
|
iso.c \
|
||||||
dos.c \
|
dos.c \
|
||||||
dos_locale.c \
|
dos_locale.c \
|
||||||
|
|
|
@ -9,7 +9,7 @@ pkg_v_rc_0 = @echo " RC $@";
|
||||||
%_rc.o: %.rc
|
%_rc.o: %.rc
|
||||||
$(pkg_v_rc)$(WINDRES) $(AM_RCFLAGS) -i $< -o $@
|
$(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_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./libcdio $(AM_CFLAGS)
|
||||||
rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows
|
rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows
|
||||||
rufus_LDADD = rufus_rc.o ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \
|
rufus_LDADD = rufus_rc.o ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \
|
||||||
|
|
|
@ -44,7 +44,7 @@ CONFIG_CLEAN_FILES =
|
||||||
CONFIG_CLEAN_VPATH_FILES =
|
CONFIG_CLEAN_VPATH_FILES =
|
||||||
PROGRAMS = $(noinst_PROGRAMS)
|
PROGRAMS = $(noinst_PROGRAMS)
|
||||||
am_rufus_OBJECTS = rufus-drive.$(OBJEXT) rufus-icon.$(OBJEXT) \
|
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-dos_locale.$(OBJEXT) rufus-badblocks.$(OBJEXT) \
|
||||||
rufus-syslinux.$(OBJEXT) rufus-format.$(OBJEXT) \
|
rufus-syslinux.$(OBJEXT) rufus-format.$(OBJEXT) \
|
||||||
rufus-stdio.$(OBJEXT) rufus-stdlg.$(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_$(V))
|
||||||
pkg_v_rc_ = $(pkg_v_rc_$(AM_DEFAULT_VERBOSITY))
|
pkg_v_rc_ = $(pkg_v_rc_$(AM_DEFAULT_VERBOSITY))
|
||||||
pkg_v_rc_0 = @echo " RC $@";
|
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_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./libcdio $(AM_CFLAGS)
|
||||||
rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows
|
rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows
|
||||||
rufus_LDADD = rufus_rc.o ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \
|
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@
|
$(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`
|
$(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
|
rufus-iso.o: iso.c
|
||||||
$(AM_V_CC) @AM_BACKSLASH@
|
$(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
|
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-iso.o `test -f 'iso.c' || echo '$(srcdir)/'`iso.c
|
||||||
|
|
15
src/drive.c
15
src/drive.c
|
@ -34,6 +34,8 @@
|
||||||
* Globals
|
* Globals
|
||||||
*/
|
*/
|
||||||
RUFUS_DRIVE_INFO SelectedDrive;
|
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
|
* 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);
|
drive_type = GetDriveTypeA(drive);
|
||||||
// NB: the HP utility allows drive_type == DRIVE_FIXED, which we don't really really want for now
|
// 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
|
// 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;
|
continue;
|
||||||
|
|
||||||
safe_sprintf(logical_drive, sizeof(logical_drive), "\\\\.\\%c:", drive[0]);
|
safe_sprintf(logical_drive, sizeof(logical_drive), "\\\\.\\%c:", drive[0]);
|
||||||
|
@ -149,6 +151,7 @@ out:
|
||||||
BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label)
|
BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label)
|
||||||
{
|
{
|
||||||
HANDLE hDrive;
|
HANDLE hDrive;
|
||||||
|
char AutorunPath[] = "#:\\autorun.inf", *AutorunLabel;
|
||||||
wchar_t wDrivePath[] = L"#:\\";
|
wchar_t wDrivePath[] = L"#:\\";
|
||||||
wchar_t wVolumeLabel[MAX_PATH+1];
|
wchar_t wVolumeLabel[MAX_PATH+1];
|
||||||
static char VolumeLabel[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)
|
if (hDrive == INVALID_HANDLE_VALUE)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
safe_closehandle(hDrive);
|
safe_closehandle(hDrive);
|
||||||
|
AutorunPath[0] = *letter;
|
||||||
wDrivePath[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) {
|
NULL, NULL, NULL, NULL, 0) && *wVolumeLabel) {
|
||||||
wchar_to_utf8_no_alloc(wVolumeLabel, VolumeLabel, sizeof(VolumeLabel));
|
wchar_to_utf8_no_alloc(wVolumeLabel, VolumeLabel, sizeof(VolumeLabel));
|
||||||
*label = VolumeLabel;
|
*label = VolumeLabel;
|
||||||
|
|
|
@ -656,7 +656,8 @@ DWORD WINAPI FormatThread(LPVOID param)
|
||||||
if (iso_path != NULL) {
|
if (iso_path != NULL) {
|
||||||
PrintStatus(0, TRUE, "Copying ISO files...");
|
PrintStatus(0, TRUE, "Copying ISO files...");
|
||||||
drive_name[2] = 0;
|
drive_name[2] = 0;
|
||||||
if ( (!ExtractISO(iso_path, drive_name, FALSE)) && (!FormatStatus)) {
|
if (!ExtractISO(iso_path, drive_name, FALSE)) {
|
||||||
|
if (!FormatStatus)
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY;
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
66
src/iso.c
66
src/iso.c
|
@ -71,6 +71,8 @@ static uint64_t total_blocks, nb_blocks;
|
||||||
static BOOL scan_only = FALSE;
|
static BOOL scan_only = FALSE;
|
||||||
static StrArray config_path;
|
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
|
// TODO: Timestamp & permissions preservation
|
||||||
|
|
||||||
// Convert a file size to human readable
|
// 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<buf_size; i++) {
|
|
||||||
// Check if there is a line starting with "append" (case insensitive)
|
|
||||||
if (_strnicmp(&buf[i], "append", sizeof("append")-1) == 0) {
|
|
||||||
for (j=i; (buf[j]!=0x00)&&(buf[j]!=0x0A)&&(buf[j]!=0x0D); j++); // EOL
|
|
||||||
eol_char = buf[j]; // Make sure the line is NUL terminated
|
|
||||||
buf[j] = 0;
|
|
||||||
label = strstr(&buf[i], iso_report.label);
|
|
||||||
if (label != NULL) {
|
|
||||||
// Since label is longer than usb_label we can replace it
|
|
||||||
for (k=0; k<strlen(iso_report.label); k++)
|
|
||||||
label[k] = (k<strlen(iso_report.usb_label))?iso_report.usb_label[k]:' ';
|
|
||||||
uprintf(" Patched config file to use USB label '%s'\n", iso_report.usb_label);
|
|
||||||
// uprintf(" Patched line: '%s'\n", &buf[i]);
|
|
||||||
}
|
|
||||||
// Revert EOL
|
|
||||||
buf[j] = eol_char;
|
|
||||||
i = j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Revert NUL terminator
|
|
||||||
buf[buf_size] = last_char;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Scan and set ISO properties
|
* Scan and set ISO properties
|
||||||
* Returns true if the the current file does not need to be processed further
|
* Returns true if the the current file does not need to be processed further
|
||||||
|
@ -259,8 +212,6 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
buf_size = (DWORD)MIN(i_file_length, i_read);
|
buf_size = (DWORD)MIN(i_file_length, i_read);
|
||||||
if (is_syslinux_cfg)
|
|
||||||
process_config((char*)buf, (size_t)buf_size, psz_fullpath);
|
|
||||||
ISO_BLOCKING(r = WriteFile(file_handle, buf, buf_size, &wr_size, NULL));
|
ISO_BLOCKING(r = WriteFile(file_handle, buf, buf_size, &wr_size, NULL));
|
||||||
if ((!r) || (buf_size != wr_size)) {
|
if ((!r) || (buf_size != wr_size)) {
|
||||||
uprintf(" Error writing file: %s\n", WindowsErrorString());
|
uprintf(" Error writing file: %s\n", WindowsErrorString());
|
||||||
|
@ -277,6 +228,12 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha
|
||||||
// The drawback however is with cancellation. With a large file, CloseHandle()
|
// The drawback however is with cancellation. With a large file, CloseHandle()
|
||||||
// may take forever to complete and is not interruptible. We try to detect this.
|
// may take forever to complete and is not interruptible. We try to detect this.
|
||||||
ISO_BLOCKING(safe_closehandle(file_handle));
|
ISO_BLOCKING(safe_closehandle(file_handle));
|
||||||
|
if (is_syslinux_cfg) {
|
||||||
|
// Workaround for isolinux config files requiring an ISO label for kernel
|
||||||
|
// append that may be different from our USB label.
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
safe_free(psz_fullpath);
|
safe_free(psz_fullpath);
|
||||||
}
|
}
|
||||||
|
@ -363,8 +320,6 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
buf_size = (DWORD)MIN(i_file_length, ISO_BLOCKSIZE);
|
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));
|
ISO_BLOCKING(s = WriteFile(file_handle, buf, buf_size, &wr_size, NULL));
|
||||||
if ((!s) || (buf_size != wr_size)) {
|
if ((!s) || (buf_size != wr_size)) {
|
||||||
uprintf(" Error writing file: %s\n", WindowsErrorString());
|
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));
|
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;
|
r = 0;
|
||||||
|
@ -506,6 +465,7 @@ out:
|
||||||
uprintf("Created: %s\n", syslinux_path);
|
uprintf("Created: %s\n", syslinux_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (fd != NULL)
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
}
|
}
|
||||||
SendMessage(hISOProgressDlg, UM_ISO_EXIT, 0, 0);
|
SendMessage(hISOProgressDlg, UM_ISO_EXIT, 0, 0);
|
||||||
|
|
268
src/parser.c
Normal file
268
src/parser.c
Normal file
|
@ -0,0 +1,268 @@
|
||||||
|
/*
|
||||||
|
* Rufus: The Reliable USB Formatting Utility
|
||||||
|
* Elementary Unicode compliant find/replace parser
|
||||||
|
* Copyright (c) 2012 Pete Batard <pete@akeo.ie>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Memory leaks detection - define _CRTDBG_MAP_ALLOC as preprocessor macro */
|
||||||
|
#ifdef _CRTDBG_MAP_ALLOC
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <crtdbg.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <wchar.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
15
src/rufus.c
15
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" };
|
"1024 kilobytes","2048 kilobytes","4096 kilobytes","8192 kilobytes","16 megabytes","32 megabytes" };
|
||||||
static BOOL existing_key = FALSE; // For LGP set/restore
|
static BOOL existing_key = FALSE; // For LGP set/restore
|
||||||
static BOOL iso_size_check = TRUE;
|
static BOOL iso_size_check = TRUE;
|
||||||
|
BOOL enable_fixed_disks = FALSE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Globals
|
* Globals
|
||||||
|
@ -535,6 +536,8 @@ static BOOL GetUSBDevices(DWORD devnum)
|
||||||
STORAGE_DEVICE_NUMBER_REDEF device_number;
|
STORAGE_DEVICE_NUMBER_REDEF device_number;
|
||||||
DWORD size, i, j, datatype;
|
DWORD size, i, j, datatype;
|
||||||
HANDLE hDrive;
|
HANDLE hDrive;
|
||||||
|
LONG maxwidth = 0;
|
||||||
|
RECT rect;
|
||||||
char drive_letter;
|
char drive_letter;
|
||||||
char *label, entry[MAX_PATH], buffer[MAX_PATH];
|
char *label, entry[MAX_PATH], buffer[MAX_PATH];
|
||||||
const char* usbstor_name = "USBSTOR";
|
const char* usbstor_name = "USBSTOR";
|
||||||
|
@ -544,6 +547,7 @@ static BOOL GetUSBDevices(DWORD devnum)
|
||||||
IGNORE_RETVAL(ComboBox_ResetContent(hDeviceList));
|
IGNORE_RETVAL(ComboBox_ResetContent(hDeviceList));
|
||||||
StrArrayClear(&DriveID);
|
StrArrayClear(&DriveID);
|
||||||
StrArrayClear(&DriveLabel);
|
StrArrayClear(&DriveLabel);
|
||||||
|
GetClientRect(hDeviceList, &rect);
|
||||||
|
|
||||||
dev_info = SetupDiGetClassDevsA(&_GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
|
dev_info = SetupDiGetClassDevsA(&_GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
|
||||||
if (dev_info == INVALID_HANDLE_VALUE) {
|
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);
|
safe_sprintf(entry, sizeof(entry), "%s (%c:)", label, drive_letter);
|
||||||
IGNORE_RETVAL(ComboBox_SetItemData(hDeviceList, ComboBox_AddStringU(hDeviceList, entry),
|
IGNORE_RETVAL(ComboBox_SetItemData(hDeviceList, ComboBox_AddStringU(hDeviceList, entry),
|
||||||
device_number.DeviceNumber + DRIVE_INDEX_MIN));
|
device_number.DeviceNumber + DRIVE_INDEX_MIN));
|
||||||
|
maxwidth = max(maxwidth, GetEntryWidth(hDeviceList, entry));
|
||||||
safe_closehandle(hDrive);
|
safe_closehandle(hDrive);
|
||||||
safe_free(devint_detail_data);
|
safe_free(devint_detail_data);
|
||||||
break;
|
break;
|
||||||
|
@ -631,6 +636,9 @@ static BOOL GetUSBDevices(DWORD devnum)
|
||||||
}
|
}
|
||||||
SetupDiDestroyDeviceInfoList(dev_info);
|
SetupDiDestroyDeviceInfoList(dev_info);
|
||||||
|
|
||||||
|
// Adjust the Dropdown width to the maximum text size
|
||||||
|
SendMessage(hDeviceList, CB_SETDROPPEDWIDTH, (WPARAM)maxwidth, 0);
|
||||||
|
|
||||||
if (devnum >= DRIVE_INDEX_MIN) {
|
if (devnum >= DRIVE_INDEX_MIN) {
|
||||||
for (i=0; i<ComboBox_GetCount(hDeviceList); i++) {
|
for (i=0; i<ComboBox_GetCount(hDeviceList); i++) {
|
||||||
if ((DWORD)ComboBox_GetItemData(hDeviceList, i) == devnum) {
|
if ((DWORD)ComboBox_GetItemData(hDeviceList, i) == devnum) {
|
||||||
|
@ -1505,6 +1513,13 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
||||||
PrintStatus(0, FALSE, "ISO size check %s", iso_size_check?"enabled":"disabled");
|
PrintStatus(0, FALSE, "ISO size check %s", iso_size_check?"enabled":"disabled");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// Alt-F => 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
|
#ifdef DISABLE_AUTORUN
|
||||||
// Alt-D => Delete the NoDriveTypeAutorun key on exit (useful if the app crashed)
|
// Alt-D => Delete the NoDriveTypeAutorun key on exit (useful if the app crashed)
|
||||||
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'D')) {
|
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'D')) {
|
||||||
|
|
|
@ -196,6 +196,7 @@ extern BOOL UnmountDrive(HANDLE hDrive);
|
||||||
extern BOOL CreateProgress(void);
|
extern BOOL CreateProgress(void);
|
||||||
extern BOOL SetAutorun(const char* path);
|
extern BOOL SetAutorun(const char* path);
|
||||||
extern char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_desc);
|
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)
|
__inline static BOOL UnlockDrive(HANDLE hDrive)
|
||||||
{
|
{
|
||||||
|
|
14
src/rufus.rc
14
src/rufus.rc
|
@ -33,12 +33,12 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
|
||||||
IDD_DIALOG DIALOGEX 12, 12, 206, 289
|
IDD_DIALOG DIALOGEX 12, 12, 206, 289
|
||||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
EXSTYLE WS_EX_APPWINDOW
|
EXSTYLE WS_EX_APPWINDOW
|
||||||
CAPTION "Rufus v1.1.4.147"
|
CAPTION "Rufus v1.1.4.148"
|
||||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||||
BEGIN
|
BEGIN
|
||||||
DEFPUSHBUTTON "Start",IDC_START,94,248,50,14
|
DEFPUSHBUTTON "Start",IDC_START,94,248,50,14
|
||||||
PUSHBUTTON "Close",IDCANCEL,148,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
|
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
|
COMBOBOX IDC_FILESYSTEM,8,75,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
|
||||||
LTEXT "File system",IDC_STATIC,9,64,51,10
|
LTEXT "File system",IDC_STATIC,9,64,51,10
|
||||||
|
@ -73,7 +73,7 @@ BEGIN
|
||||||
DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP
|
DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP
|
||||||
CONTROL "<a href=""http://rufus.akeo.ie"">http://rufus.akeo.ie</a>",IDC_ABOUT_RUFUS_URL,
|
CONTROL "<a href=""http://rufus.akeo.ie"">http://rufus.akeo.ie</a>",IDC_ABOUT_RUFUS_URL,
|
||||||
"SysLink",WS_TABSTOP,46,47,114,9
|
"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
|
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
|
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
|
LTEXT "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8
|
||||||
|
@ -223,8 +223,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,1,4,147
|
FILEVERSION 1,1,4,148
|
||||||
PRODUCTVERSION 1,1,4,147
|
PRODUCTVERSION 1,1,4,148
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -241,13 +241,13 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "akeo.ie"
|
VALUE "CompanyName", "akeo.ie"
|
||||||
VALUE "FileDescription", "Rufus"
|
VALUE "FileDescription", "Rufus"
|
||||||
VALUE "FileVersion", "1.1.4.147"
|
VALUE "FileVersion", "1.1.4.148"
|
||||||
VALUE "InternalName", "Rufus"
|
VALUE "InternalName", "Rufus"
|
||||||
VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)"
|
VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)"
|
||||||
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
|
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
|
||||||
VALUE "OriginalFilename", "rufus.exe"
|
VALUE "OriginalFilename", "rufus.exe"
|
||||||
VALUE "ProductName", "Rufus"
|
VALUE "ProductName", "Rufus"
|
||||||
VALUE "ProductVersion", "1.1.4.147"
|
VALUE "ProductVersion", "1.1.4.148"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
26
src/stdlg.c
26
src/stdlg.c
|
@ -806,3 +806,29 @@ void DestroyAllTooltips(void)
|
||||||
safe_free(ttlist[i].wstring);
|
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;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue