[togo] enable selection of Windows version

* Closes #847
* Also set rufus-next to 2.12
This commit is contained in:
Pete Batard 2016-12-13 14:21:51 +00:00
parent 5113be0a39
commit 7d302d340f
15 changed files with 349 additions and 78 deletions

20
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for rufus 2.11.
# Generated by GNU Autoconf 2.69 for rufus 2.12.
#
# Report bugs to <https://github.com/pbatard/rufus/issues>.
#
@ -580,8 +580,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='rufus'
PACKAGE_TARNAME='rufus'
PACKAGE_VERSION='2.11'
PACKAGE_STRING='rufus 2.11'
PACKAGE_VERSION='2.12'
PACKAGE_STRING='rufus 2.12'
PACKAGE_BUGREPORT='https://github.com/pbatard/rufus/issues'
PACKAGE_URL='http://rufus.akeo.ie'
@ -1228,7 +1228,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures rufus 2.11 to adapt to many kinds of systems.
\`configure' configures rufus 2.12 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1294,7 +1294,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of rufus 2.11:";;
short | recursive ) echo "Configuration of rufus 2.12:";;
esac
cat <<\_ACEOF
@ -1385,7 +1385,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
rufus configure 2.11
rufus configure 2.12
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@ -1440,7 +1440,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by rufus $as_me 2.11, which was
It was created by rufus $as_me 2.12, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@ -2303,7 +2303,7 @@ fi
# Define the identity of the package.
PACKAGE='rufus'
VERSION='2.11'
VERSION='2.12'
cat >>confdefs.h <<_ACEOF
@ -4482,7 +4482,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by rufus $as_me 2.11, which was
This file was extended by rufus $as_me 2.12, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -4536,7 +4536,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
rufus config.status 2.11
rufus config.status 2.12
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

View File

@ -1,4 +1,4 @@
AC_INIT([rufus], [2.11], [https://github.com/pbatard/rufus/issues], [rufus], [http://rufus.akeo.ie])
AC_INIT([rufus], [2.12], [https://github.com/pbatard/rufus/issues], [rufus], [http://rufus.akeo.ie])
AM_INIT_AUTOMAKE([-Wno-portability foreign no-dist no-dependencies])
AC_CONFIG_SRCDIR([src/rufus.c])
AC_CONFIG_MACRO_DIR([m4])

View File

@ -553,6 +553,8 @@ t MSG_287 "Detection of non-USB removable drives"
t MSG_288 "Missing elevated privileges"
t MSG_289 "This application can only run with elevated privileges"
t MSG_290 "File Indexing"
t MSG_291 "Version selection"
t MSG_292 "Please select the version of Windows you want to install:"
################################################################################
############################# TRANSLATOR END COPY ##############################

View File

@ -313,7 +313,7 @@ BOOL GetDevices(DWORD devnum)
StrArrayClear(&DriveLabel);
StrArrayCreate(&dev_if_path, 128);
// Add a dummy for string index zero, as this is what non matching hashes will point to
StrArrayAdd(&dev_if_path, "");
StrArrayAdd(&dev_if_path, "", TRUE);
device_id = (char*)malloc(MAX_PATH);
if (device_id == NULL)
@ -340,7 +340,7 @@ BOOL GetDevices(DWORD devnum)
// Find the Device IDs for all the children of this hub
if (CM_Get_Child(&device_inst, dev_info_data.DevInst, 0) == CR_SUCCESS) {
device_id[0] = 0;
s = StrArrayAdd(&dev_if_path, devint_detail_data->DevicePath);
s = StrArrayAdd(&dev_if_path, devint_detail_data->DevicePath, TRUE);
uuprintf(" Hub[%d] = '%s'", s, devint_detail_data->DevicePath);
if ((s>= 0) && (CM_Get_Device_IDA(device_inst, device_id, MAX_PATH, 0) == CR_SUCCESS)) {
if ((k = htab_hash(device_id, &htab_devid)) != 0) {
@ -741,8 +741,8 @@ BOOL GetDevices(DWORD devnum)
}
// Must ensure that the combo box is UNSORTED for indexes to be the same
StrArrayAdd(&DriveID, buffer);
StrArrayAdd(&DriveLabel, label);
StrArrayAdd(&DriveID, buffer, TRUE);
StrArrayAdd(&DriveLabel, label, TRUE);
IGNORE_RETVAL(ComboBox_SetItemData(hDeviceList, ComboBox_AddStringU(hDeviceList, entry), drive_index));
maxwidth = max(maxwidth, GetEntryWidth(hDeviceList, entry));

View File

@ -1277,8 +1277,11 @@ static BOOL SetupWinToGo(const char* drive_name, BOOL use_ms_efi)
static char san_policy_path[] = "?:\\san_policy.xml";
#endif
static char unattend_path[] = "?:\\Windows\\System32\\sysprep\\unattend.xml";
StrArray version_name, version_index;
char *mounted_iso, *ms_efi = NULL, image[128], cmd[MAX_PATH];
char tmp_path[MAX_PATH] = "", xml_file[MAX_PATH] = "";
unsigned char *buffer;
int i, index;
wchar_t wVolumeName[] = L"?:";
DWORD bufsize;
ULONG cluster_size;
@ -1305,11 +1308,50 @@ static BOOL SetupWinToGo(const char* drive_name, BOOL use_ms_efi)
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_EXTRACT);
return FALSE;
}
static_sprintf(image, "%s%s", mounted_iso, &img_report.install_wim_path[2]);
uprintf("Mounted ISO as '%s'", mounted_iso);
// Then we need to take a look at the XML file in install.wim to allow users
// to select the version they want to extract
if ((GetTempPathU(sizeof(tmp_path), tmp_path) == 0)
|| (GetTempFileNameU(tmp_path, APPLICATION_NAME, 0, xml_file) == 0)
|| (xml_file[0] == 0)) {
// Last ditch effort to get a loc file - just extract it to the current directory
safe_strcpy(xml_file, sizeof(xml_file), ".\\RufVXml.tmp");
}
// GetTempFileName() may leave a file behind
DeleteFileU(xml_file);
// Must use the Windows WIM API as 7z messes up the XML
if (!WimExtractFile_API(image, 0, "[1].xml", xml_file)) {
uprintf("Failed to acquire WIM index");
}
StrArrayCreate(&version_name, 16);
StrArrayCreate(&version_index, 16);
for (i = 0; (StrArrayAdd(&version_name, get_token_data_file_indexed("DISPLAYNAME", xml_file, i+1), FALSE) >= 0) &&
(StrArrayAdd(&version_index, get_token_data_file_indexed("IMAGE INDEX", xml_file, i+1), FALSE) >= 0); i++);
DeleteFileU(xml_file);
if (i > 1)
i = Selection(lmprintf(MSG_291), lmprintf(MSG_292), version_name.String, i);
if (i <= 0) {
uprintf("Cancelled by user");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANCELLED;
UnMountISO();
StrArrayDestroy(&version_name);
StrArrayDestroy(&version_index);
return FALSE;
} else if (i == 0) {
index = 1;
} else {
index = atoi(version_index.String[i - 1]);
}
uprintf("Selected: '%s' (index %s)", version_name.String[i - 1], version_index.String[i - 1]);
StrArrayDestroy(&version_name);
StrArrayDestroy(&version_index);
// Now we use the WIM API to apply that image
static_sprintf(image, "%s%s", mounted_iso, &img_report.install_wim_path[2]);
if (!WimApplyImage(image, 1, drive_name)) {
if (!WimApplyImage(image, index, drive_name)) {
uprintf("Failed to apply Windows To Go image");
if (!IS_ERROR(FormatStatus))
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_EXTRACT);

View File

@ -226,12 +226,12 @@ static BOOL check_iso_props(const char* psz_dirname, int64_t i_file_length, cons
if (props->is_syslinux_cfg) {
// Maintain a list of all the isolinux/syslinux configs identified so far
StrArrayAdd(&config_path, psz_fullpath);
StrArrayAdd(&config_path, psz_fullpath, TRUE);
}
for (i=0; i<ARRAYSIZE(isolinux_bin); i++) {
if (safe_stricmp(psz_basename, isolinux_bin[i]) == 0) {
// Maintain a list of all the isolinux.bin files found
StrArrayAdd(&isolinux_path, psz_fullpath);
StrArrayAdd(&isolinux_path, psz_fullpath, TRUE);
}
}

View File

@ -96,6 +96,20 @@ const loc_control_id control_id[] = {
LOC_CTRL(IDC_SELECTION_LINE),
LOC_CTRL(IDC_SELECTION_CHOICE1),
LOC_CTRL(IDC_SELECTION_CHOICE2),
LOC_CTRL(IDC_SELECTION_CHOICE3),
LOC_CTRL(IDC_SELECTION_CHOICE4),
LOC_CTRL(IDC_SELECTION_CHOICE5),
LOC_CTRL(IDC_SELECTION_CHOICE6),
LOC_CTRL(IDC_SELECTION_CHOICE7),
LOC_CTRL(IDC_SELECTION_CHOICE8),
LOC_CTRL(IDC_SELECTION_CHOICE9),
LOC_CTRL(IDC_SELECTION_CHOICE10),
LOC_CTRL(IDC_SELECTION_CHOICE11),
LOC_CTRL(IDC_SELECTION_CHOICE12),
LOC_CTRL(IDC_SELECTION_CHOICE13),
LOC_CTRL(IDC_SELECTION_CHOICE14),
LOC_CTRL(IDC_SELECTION_CHOICE15),
LOC_CTRL(IDC_SELECTION_CHOICEMAX),
LOC_CTRL(IDS_DEVICE_TXT),
LOC_CTRL(IDS_PARTITION_TYPE_TXT),
LOC_CTRL(IDS_FILESYSTEM_TXT),

View File

@ -571,20 +571,24 @@ out:
/*
* Parse a line of UTF-16 text and return the data if it matches the 'token'
* The parsed line is of the form: [ ]token[ ]=[ ]["]data["][ ] and is
* The parsed line is of the form: [ ][<][ ]token[ ][=|>][ ]["]data["][ ][<] and is
* modified by the parser
*/
static wchar_t* get_token_data_line(const wchar_t* wtoken, wchar_t* wline)
{
size_t i, r;
BOOLEAN quoteth = FALSE;
BOOLEAN xml = FALSE;
if ((wtoken == NULL) || (wline == NULL) || (wline[0] == 0))
return NULL;
i = 0;
// Skip leading spaces
// Skip leading spaces and opening '<'
i += wcsspn(&wline[i], wspace);
if (wline[i] == L'<')
i++;
i += wcsspn(&wline[i], wspace);
// Our token should begin a line
@ -597,12 +601,14 @@ static wchar_t* get_token_data_line(const wchar_t* wtoken, wchar_t* wline)
// Skip spaces
i += wcsspn(&wline[i], wspace);
// Check for an equal sign
if (wline[i] != L'=')
// Check for '=' or '>' sign
if (wline[i] == L'>')
xml = TRUE;
else if (wline[i] != L'=')
return NULL;
i++;
// Skip spaces after equal sign
// Skip spaces
i += wcsspn(&wline[i], wspace);
// eliminate leading quote, if it exists
@ -615,7 +621,7 @@ static wchar_t* get_token_data_line(const wchar_t* wtoken, wchar_t* wline)
r = i;
// locate end of string or quote
while ( (wline[i] != 0) && ((wline[i] != L'"') || ((wline[i] == L'"') && (!quoteth))) )
while ( (wline[i] != 0) && (((wline[i] != L'"') && (wline[i] != L'<')) || ((wline[i] == L'"') && (!quoteth)) || ((wline[i] == L'<') && (!xml))) )
i++;
wline[i--] = 0;
@ -627,11 +633,12 @@ static wchar_t* get_token_data_line(const wchar_t* wtoken, wchar_t* wline)
}
/*
* Parse a file (ANSI or UTF-8 or UTF-16) and return the data for the first occurrence of 'token'
* Parse a file (ANSI or UTF-8 or UTF-16) and return the data for the 'index'th occurrence of 'token'
* The returned string is UTF-8 and MUST be freed by the caller
*/
char* get_token_data_file(const char* token, const char* filename)
char* get_token_data_file_indexed(const char* token, const char* filename, int index)
{
int i = 0;
wchar_t *wtoken = NULL, *wdata= NULL, *wfilename = NULL;
wchar_t buf[1024];
FILE* fd = NULL;
@ -659,7 +666,7 @@ char* get_token_data_file(const char* token, const char* filename)
// Ideally, we'd check that our buffer fits the line
while (fgetws(buf, ARRAYSIZE(buf), fd) != NULL) {
wdata = get_token_data_line(wtoken, buf);
if (wdata != NULL) {
if ((wdata != NULL) && (++i == index)) {
ret = wchar_to_utf8(wdata);
break;
}

View File

@ -134,6 +134,20 @@
#define IDC_SELECTION_LINE 1076
#define IDC_SELECTION_CHOICE1 1077
#define IDC_SELECTION_CHOICE2 1078
#define IDC_SELECTION_CHOICE3 1079
#define IDC_SELECTION_CHOICE4 1080
#define IDC_SELECTION_CHOICE5 1081
#define IDC_SELECTION_CHOICE6 1082
#define IDC_SELECTION_CHOICE7 1083
#define IDC_SELECTION_CHOICE8 1084
#define IDC_SELECTION_CHOICE9 1085
#define IDC_SELECTION_CHOICE10 1086
#define IDC_SELECTION_CHOICE11 1087
#define IDC_SELECTION_CHOICE12 1088
#define IDC_SELECTION_CHOICE13 1089
#define IDC_SELECTION_CHOICE14 1090
#define IDC_SELECTION_CHOICE15 1091
#define IDC_SELECTION_CHOICEMAX 1092
#define IDS_DEVICE_TXT 2000
#define IDS_PARTITION_TYPE_TXT 2001
#define IDS_FILESYSTEM_TXT 2002

View File

@ -2108,6 +2108,10 @@ void SaveISO(void)
}
}
#ifdef RUFUS_TEST
extern int SelectionDyn(char* title, char* message, char** szChoice, int nChoices);
#endif
/*
* Main dialog callback
*/
@ -2140,6 +2144,8 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
case WM_COMMAND:
#ifdef RUFUS_TEST
if (LOWORD(wParam) == IDC_TEST) {
char* choices[] = { "Choice 1", "Choice 2", "Choice 3" };
SelectionDyn("Test Choice", "Unused", choices, ARRAYSIZE(choices));
break;
}
#endif
@ -2438,8 +2444,9 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
(ComboBox_GetItemData(hBootType, ComboBox_GetCurSel(hBootType)) == BT_ISO)) {
char* iso_image = lmprintf(MSG_036);
char* dd_image = lmprintf(MSG_095);
char* choices[2] = { lmprintf(MSG_276, iso_image), lmprintf(MSG_277, dd_image) };
i = Selection(lmprintf(MSG_274), lmprintf(MSG_275, iso_image, dd_image, iso_image, dd_image),
lmprintf(MSG_276, iso_image), lmprintf(MSG_277, dd_image));
choices, 2);
if (i < 0) { // Cancel
format_op_in_progress = FALSE;
PROCESS_QUEUED_EVENTS;

View File

@ -422,7 +422,7 @@ extern BOOL CreateTooltip(HWND hControl, const char* message, int duration);
extern void DestroyTooltip(HWND hWnd);
extern void DestroyAllTooltips(void);
extern BOOL Notification(int type, const notification_info* more_info, char* title, char* format, ...);
extern int Selection(char* title, char* message, char* selection1, char* selection2);
extern int Selection(char* title, char* message, char** choices, int size);
extern SIZE GetTextSize(HWND hCtrl);
extern BOOL ExtractDOS(const char* path);
extern BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan);
@ -450,7 +450,8 @@ extern BOOL SetUpdateCheck(void);
extern BOOL CheckForUpdates(BOOL force);
extern void DownloadNewVersion(void);
extern BOOL IsShown(HWND hDlg);
extern char* get_token_data_file(const char* token, const char* filename);
extern char* get_token_data_file_indexed(const char* token, const char* filename, int index);
#define get_token_data_file(token, filename) get_token_data_file_indexed(token, filename, 1)
extern char* set_token_data_file(const char* token, const char* data, const char* filename);
extern char* get_token_data_buffer(const char* token, unsigned int n, const char* buffer, size_t buffer_size);
extern char* insert_section_data(const char* filename, const char* section, const char* data, BOOL dos2unix);
@ -459,6 +460,8 @@ extern char* replace_char(const char* src, const char c, const char* rep);
extern void parse_update(char* buf, size_t len);
extern uint8_t WimExtractCheck(void);
extern BOOL WimExtractFile(const char* wim_image, int index, const char* src, const char* dst);
extern BOOL WimExtractFile_API(const char* image, int index, const char* src, const char* dst);
extern BOOL WimExtractFile_7z(const char* image, int index, const char* src, const char* dst);
extern BOOL WimApplyImage(const char* image, int index, const char* dst);
extern BOOL IsBootableImage(const char* path);
extern BOOL AppendVHDFooter(const char* vhd_path);
@ -507,7 +510,7 @@ typedef struct {
uint32_t Max; // Maximum array size
} StrArray;
extern void StrArrayCreate(StrArray* arr, uint32_t initial_size);
extern int32_t StrArrayAdd(StrArray* arr, const char* str);
extern int32_t StrArrayAdd(StrArray* arr, const char* str, BOOL );
extern void StrArrayClear(StrArray* arr);
extern void StrArrayDestroy(StrArray* arr);
#define IsStrArrayEmpty(arr) (arr.Index == 0)

View File

@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 242, 376
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES
CAPTION "Rufus 2.11.1007"
CAPTION "Rufus 2.12.1008"
FONT 8, "Segoe UI Symbol", 400, 0, 0x0
BEGIN
LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8
@ -144,10 +144,24 @@ BEGIN
LTEXT "",IDC_STATIC,0,0,312,46
ICON IDI_ICON,IDC_SELECTION_ICON,6,6,20,20,0,WS_EX_TRANSPARENT
LTEXT "Message",IDC_SELECTION_TEXT,35,5,269,8
DEFPUSHBUTTON "Cancel",IDCANCEL,254,52,50,14
PUSHBUTTON "OK",IDOK,196,52,50,14
CONTROL "Choice 1",IDC_SELECTION_CHOICE1,"Button",BS_AUTORADIOBUTTON,35,18,269,10,WS_EX_TRANSPARENT
DEFPUSHBUTTON "OK",IDOK,196,52,50,14
PUSHBUTTON "Cancel",IDCANCEL,254,52,50,14
CONTROL "Choice 1",IDC_SELECTION_CHOICE1,"Button",BS_AUTORADIOBUTTON | WS_GROUP,35,18,269,10,WS_EX_TRANSPARENT
CONTROL "Choice 2",IDC_SELECTION_CHOICE2,"Button",BS_AUTORADIOBUTTON,35,31,269,10,WS_EX_TRANSPARENT
CONTROL "Choice 3",IDC_SELECTION_CHOICE3,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,44,269,10,WS_EX_TRANSPARENT
CONTROL "Choice 4",IDC_SELECTION_CHOICE4,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,57,269,10,WS_EX_TRANSPARENT
CONTROL "Choice 5",IDC_SELECTION_CHOICE5,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,70,269,10,WS_EX_TRANSPARENT
CONTROL "Choice 6",IDC_SELECTION_CHOICE6,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,83,269,10,WS_EX_TRANSPARENT
CONTROL "Choice 7",IDC_SELECTION_CHOICE7,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,96,269,10,WS_EX_TRANSPARENT
CONTROL "Choice 8",IDC_SELECTION_CHOICE8,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,109,269,10,WS_EX_TRANSPARENT
CONTROL "Choice 9",IDC_SELECTION_CHOICE9,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,122,269,10,WS_EX_TRANSPARENT
CONTROL "Choice 10",IDC_SELECTION_CHOICE10,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,135,269,10,WS_EX_TRANSPARENT
CONTROL "Choice 11",IDC_SELECTION_CHOICE11,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,148,269,10,WS_EX_TRANSPARENT
CONTROL "Choice 12",IDC_SELECTION_CHOICE12,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,161,269,10,WS_EX_TRANSPARENT
CONTROL "Choice 13",IDC_SELECTION_CHOICE13,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,174,269,10,WS_EX_TRANSPARENT
CONTROL "Choice 14",IDC_SELECTION_CHOICE14,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,187,269,10,WS_EX_TRANSPARENT
CONTROL "Choice 15",IDC_SELECTION_CHOICE15,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,200,269,10,WS_EX_TRANSPARENT
CONTROL "Choice 16",IDC_SELECTION_CHOICEMAX,"Button",BS_AUTORADIOBUTTON | NOT WS_VISIBLE,35,21,269,10,WS_EX_TRANSPARENT
END
IDD_UPDATE_POLICY DIALOGEX 0, 0, 287, 198
@ -320,8 +334,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,11,1007,0
PRODUCTVERSION 2,11,1007,0
FILEVERSION 2,12,1008,0
PRODUCTVERSION 2,12,1008,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -338,13 +352,13 @@ BEGIN
BEGIN
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "2.11.1007"
VALUE "FileVersion", "2.12.1008"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2016 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "2.11.1007"
VALUE "ProductVersion", "2.12.1008"
END
END
BLOCK "VarFileInfo"

View File

@ -348,10 +348,10 @@ void StrArrayCreate(StrArray* arr, uint32_t initial_size)
uprintf("Could not allocate string array\n");
}
int32_t StrArrayAdd(StrArray* arr, const char* str)
int32_t StrArrayAdd(StrArray* arr, const char* str, BOOL duplicate)
{
char** old_table;
if ((arr == NULL) || (arr->String == NULL))
if ((arr == NULL) || (arr->String == NULL) || (str == NULL))
return -1;
if (arr->Index == arr->Max) {
arr->Max *= 2;
@ -363,7 +363,7 @@ int32_t StrArrayAdd(StrArray* arr, const char* str)
return -1;
}
}
arr->String[arr->Index] = safe_strdup(str);
arr->String[arr->Index] = (duplicate)?safe_strdup(str):(char*)str;
if (arr->String[arr->Index] == NULL) {
uprintf("Could not store string in array\n");
return -1;

View File

@ -54,7 +54,8 @@ PF_TYPE_DECL(WINAPI, LPITEMIDLIST, SHSimpleIDListFromPath, (PCWSTR pszPath));
static HICON hMessageIcon = (HICON)INVALID_HANDLE_VALUE;
static char* szMessageText = NULL;
static char* szMessageTitle = NULL;
static char *szChoice1, *szChoice2;
static char **szChoice;
static int nChoices;
static HWND hBrowseEdit;
extern HWND hUpdatesDlg;
static WNDPROC pOrgBrowseWndproc;
@ -68,6 +69,14 @@ static char *fp_title_str = "Microsoft Windows", *fp_button_str = "Format disk";
extern loc_cmd* selected_locale;
/*
* https://blogs.msdn.microsoft.com/oldnewthing/20040802-00/?p=38283/
*/
void SetDialogFocus(HWND hDlg, HWND hCtrl)
{
SendMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)hCtrl, TRUE);
}
/*
* We need a sub-callback to read the content of the edit box on exit and update
* our path, else if what the user typed does match the selection, it is discarded.
@ -99,7 +108,7 @@ INT CALLBACK BrowseInfoCallback(HWND hDlg, UINT message, LPARAM lParam, LPARAM p
// Get a handle to the edit control to fix that
hBrowseEdit = FindWindowExA(hDlg, NULL, "Edit", NULL);
SetWindowTextU(hBrowseEdit, szFolderPath);
SetFocus(hBrowseEdit);
SetDialogFocus(hDlg, hBrowseEdit);
// On XP, BFFM_SETSELECTION can't be used with a Unicode Path in SendMessageW
// or a pidl (at least with MinGW) => must use SendMessageA
if (nWindowsVersion <= WINDOWS_XP) {
@ -849,6 +858,13 @@ INT_PTR CALLBACK SelectionCallback(HWND hDlg, UINT message, WPARAM wParam, LPARA
switch (message) {
case WM_INITDIALOG:
// Don't overflow our max radio button
if (nChoices > (IDC_SELECTION_CHOICEMAX - IDC_SELECTION_CHOICE1)) {
uprintf("WARNING: Too many options requested for Selection (%d vs %d)",
nChoices, IDC_SELECTION_CHOICEMAX - IDC_SELECTION_CHOICE1);
nChoices = IDC_SELECTION_CHOICEMAX - IDC_SELECTION_CHOICE1;
}
// TODO: This shouldn't be needed when using DS_SHELLFONT
// Get the system message box font. See http://stackoverflow.com/a/6057761
ncm.cbSize = sizeof(ncm);
// If we're compiling with the Vista SDK or later, the NONCLIENTMETRICS struct
@ -865,8 +881,8 @@ INT_PTR CALLBACK SelectionCallback(HWND hDlg, UINT message, WPARAM wParam, LPARA
// Set the dialog to use the system message box font
SendMessage(hDlg, WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0));
SendMessage(GetDlgItem(hDlg, IDC_SELECTION_TEXT), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0));
SendMessage(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0));
SendMessage(GetDlgItem(hDlg, IDC_SELECTION_CHOICE2), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0));
for (i = 0; i < nChoices; i++)
SendMessage(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1 + i), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0));
SendMessage(GetDlgItem(hDlg, IDYES), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0));
SendMessage(GetDlgItem(hDlg, IDNO), WM_SETFONT, (WPARAM)hDlgFont, MAKELPARAM(TRUE, 0));
@ -880,9 +896,10 @@ INT_PTR CALLBACK SelectionCallback(HWND hDlg, UINT message, WPARAM wParam, LPARA
SetWindowTextU(hDlg, szMessageTitle);
SetWindowTextU(GetDlgItem(hDlg, IDCANCEL), lmprintf(MSG_007));
SetWindowTextU(GetDlgItem(hDlg, IDC_SELECTION_TEXT), szMessageText);
SetWindowTextU(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1), szChoice1);
SetWindowTextU(GetDlgItem(hDlg, IDC_SELECTION_CHOICE2), szChoice2);
for (i = 0; i < nChoices; i++) {
SetWindowTextU(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1 + i), szChoice[i]);
ShowWindow(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1 + i), SW_SHOW);
}
// Move/Resize the controls as needed to fit our text
hCtrl = GetDlgItem(hDlg, IDC_SELECTION_TEXT);
hDC = GetDC(hCtrl);
@ -893,13 +910,16 @@ INT_PTR CALLBACK SelectionCallback(HWND hDlg, UINT message, WPARAM wParam, LPARA
dh = rect.bottom - rect.top - dh;
if (hDC != NULL)
ReleaseDC(hCtrl, hDC);
ResizeMoveCtrl(hDlg, hCtrl, 0, 0, 0, dh, 1.0f);
for (i = 0; i < nChoices; i++)
ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDC_SELECTION_CHOICE1 + i), 0, dh, 0, 0, 1.0f);
if (nChoices > 2) {
GetWindowRect(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1), &rect);
dh += (nChoices - 1) * (rect.bottom - rect.top) - 5;
}
ResizeMoveCtrl(hDlg, hDlg, 0, 0, 0, dh, 1.0f);
ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, -1), 0, 0, 0, dh, 1.0f); // IDC_STATIC = -1
ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDC_SELECTION_LINE), 0, dh, 0, 0, 1.0f);
ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDC_SELECTION_CHOICE1), 0, dh, 0, 0, 1.0f);
ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDC_SELECTION_CHOICE2), 0, dh, 0, 0, 1.0f);
ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDOK), 0, dh, 0, 0, 1.0f);
ResizeMoveCtrl(hDlg, GetDlgItem(hDlg, IDCANCEL), 0, dh, 0, 0, 1.0f);
@ -926,10 +946,10 @@ INT_PTR CALLBACK SelectionCallback(HWND hDlg, UINT message, WPARAM wParam, LPARA
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
if (Button_GetCheck(GetDlgItem(hDlg, IDC_SELECTION_CHOICE2)) == BST_CHECKED)
r = 2;
else
r = 1;
for (i = 0; (i < nChoices) &&
(Button_GetCheck(GetDlgItem(hDlg, IDC_SELECTION_CHOICE1 + i)) != BST_CHECKED); i++);
if (i < nChoices)
r = i + 1;
// Fall through
case IDNO:
case IDCANCEL:
@ -944,15 +964,15 @@ INT_PTR CALLBACK SelectionCallback(HWND hDlg, UINT message, WPARAM wParam, LPARA
/*
* Display a selection question
*/
int Selection(char* title, char* message, char* choice1, char* choice2)
int Selection(char* title, char* message, char** choices, int size)
{
int ret;
dialog_showing++;
szMessageTitle = title;
szMessageText = message;
szChoice1 = choice1;
szChoice2 = choice2;
szChoice = choices;
nChoices = size;
ret = (int)MyDialogBox(hMainInstance, IDD_SELECTION, hMainDialog, SelectionCallback);
dialog_showing--;
@ -1819,3 +1839,134 @@ void ClrFormatPromptHook(void) {
UnhookWinEvent(fp_weh);
fp_weh = NULL;
}
#ifdef RUFUS_TEST
static inline LPWORD lpwAlign(LPWORD addr)
{
return (LPWORD)((((uintptr_t)addr) + 3) & (~3));
}
INT_PTR CALLBACK SelectionDynCallback(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
int r = -1;
switch (message) {
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
r = 0;
case IDCANCEL:
EndDialog(hwndDlg, r);
return (INT_PTR)TRUE;
}
}
return FALSE;
}
int SelectionDyn(char* title, char* message, char** szChoice, int nChoices)
{
#define ID_RADIO 12345
LPCWSTR lpwszTypeFace = L"MS Shell Dlg";
LPDLGTEMPLATEA lpdt;
LPDLGITEMTEMPLATEA lpdit;
LPCWSTR lpwszCaption;
LPWORD lpw;
LPWSTR lpwsz;
int i, ret, nchar;
lpdt = (LPDLGTEMPLATE)calloc(512 + nChoices * 256, 1);
// Set up a dialog window
lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION | DS_MODALFRAME | DS_CENTER | DS_SHELLFONT;
lpdt->cdit = 2 + nChoices;
lpdt->x = 10;
lpdt->y = 10;
lpdt->cx = 300;
lpdt->cy = 100;
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms645394.aspx:
// In a standard template for a dialog box, the DLGTEMPLATE structure is always immediately followed by
// three variable-length arrays that specify the menu, class, and title for the dialog box.
// When the DS_SETFONT style is specified, these arrays are also followed by a 16-bit value specifying
// point size and another variable-length array specifying a typeface name. Each array consists of one
// or more 16-bit elements. The menu, class, title, and font arrays must be aligned on WORD boundaries.
lpw = (LPWORD)(&lpdt[1]);
*lpw++ = 0; // No menu
*lpw++ = 0; // Default dialog class
lpwsz = (LPWSTR)lpw;
nchar = MultiByteToWideChar(CP_UTF8, 0, title, -1, lpwsz, 50);
lpw += nchar;
// Set point size and typeface name if required
if (lpdt->style & (DS_SETFONT | DS_SHELLFONT)) {
*lpw++ = 8;
for (lpwsz = (LPWSTR)lpw, lpwszCaption = lpwszTypeFace; (*lpwsz++ = *lpwszCaption++) != 0; );
lpw = (LPWORD)lpwsz;
}
// Add an OK button
lpw = lpwAlign(lpw);
lpdit = (LPDLGITEMTEMPLATE)lpw;
lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON;
lpdit->x = 10;
lpdit->y = 70;
lpdit->cx = 50;
lpdit->cy = 14;
lpdit->id = IDOK;
lpw = (LPWORD)(&lpdit[1]);
*lpw++ = 0xFFFF;
*lpw++ = 0x0080; // Button class
lpwsz = (LPWSTR)lpw;
nchar = MultiByteToWideChar(CP_UTF8, 0, "OK", -1, lpwsz, 50);
lpw += nchar;
*lpw++ = 0; // No creation data
// Add a Cancel button
lpw = lpwAlign(lpw);
lpdit = (LPDLGITEMTEMPLATE)lpw;
lpdit->x = 90;
lpdit->y = 70;
lpdit->cx = 50;
lpdit->cy = 14;
lpdit->id = IDCANCEL;
lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON;
lpw = (LPWORD)(&lpdit[1]);
*lpw++ = 0xFFFF;
*lpw++ = 0x0080;
lpwsz = (LPWSTR)lpw;
nchar = MultiByteToWideChar(CP_UTF8, 0, lmprintf(MSG_007), -1, lpwsz, 50);
lpw += nchar;
*lpw++ = 0;
// Add radio buttons
for (i = 0; i < nChoices; i++) {
lpw = lpwAlign(lpw);
lpdit = (LPDLGITEMTEMPLATE)lpw;
lpdit->x = 10;
lpdit->y = 10 + 15 * i;
lpdit->cx = 40;
lpdit->cy = 20;
lpdit->id = ID_RADIO;
lpdit->style = WS_CHILD | WS_VISIBLE | BS_AUTORADIOBUTTON | (i == 0 ? WS_GROUP : 0);
lpw = (LPWORD)(&lpdit[1]);
*lpw++ = 0xFFFF;
*lpw++ = 0x0080;
lpwsz = (LPWSTR)lpw;
nchar = MultiByteToWideChar(CP_UTF8, 0, szChoice[i], -1, lpwsz, 150);
lpw += nchar;
*lpw++ = 0;
}
ret = (int)DialogBoxIndirect(hMainInstance, (LPDLGTEMPLATE)lpdt, hMainDialog, (DLGPROC)SelectionDynCallback);
free(lpdt);
return ret;
}
#endif

View File

@ -93,6 +93,7 @@ PF_TYPE_DECL(WINAPI, BOOL, WIMSetTemporaryPath, (HANDLE, PWSTR));
PF_TYPE_DECL(WINAPI, HANDLE, WIMLoadImage, (HANDLE, DWORD));
PF_TYPE_DECL(WINAPI, BOOL, WIMApplyImage, (HANDLE, PCWSTR, DWORD));
PF_TYPE_DECL(WINAPI, BOOL, WIMExtractImagePath, (HANDLE, PWSTR, PWSTR, DWORD));
PF_TYPE_DECL(WINAPI, BOOL, WIMGetImageInformation, (HANDLE, PVOID, PDWORD));
PF_TYPE_DECL(WINAPI, BOOL, WIMCloseHandle, (HANDLE));
PF_TYPE_DECL(WINAPI, DWORD, WIMRegisterMessageCallback, (HANDLE, FARPROC, PVOID));
PF_TYPE_DECL(WINAPI, DWORD, WIMUnregisterMessageCallback, (HANDLE, FARPROC));
@ -345,6 +346,7 @@ uint8_t WimExtractCheck(void)
PF_INIT(WIMLoadImage, Wimgapi);
PF_INIT(WIMApplyImage, Wimgapi);
PF_INIT(WIMExtractImagePath, Wimgapi);
PF_INIT(WIMGetImageInformation, Wimgapi);
PF_INIT(WIMRegisterMessageCallback, Wimgapi);
PF_INIT(WIMUnregisterMessageCallback, Wimgapi);
PF_INIT(WIMCloseHandle, Wimgapi);
@ -368,16 +370,19 @@ uint8_t WimExtractCheck(void)
// Extract a file from a WIM image using wimgapi.dll (Windows 7 or later)
// NB: if you want progress from a WIM callback, you must run the WIM API call in its own thread
// (which we don't do here) as it won't work otherwise. Thanks go to Erwan for figuring this out!
static BOOL WimExtractFile_API(const char* image, int index, const char* src, const char* dst)
BOOL WimExtractFile_API(const char* image, int index, const char* src, const char* dst)
{
static char* index_name = "[1].xml";
BOOL r = FALSE;
DWORD dw = 0;
HANDLE hWim = NULL;
HANDLE hImage = NULL;
HANDLE hFile = NULL;
wchar_t wtemp[MAX_PATH] = {0};
wchar_t* wimage = utf8_to_wchar(image);
wchar_t* wsrc = utf8_to_wchar(src);
wchar_t* wdst = utf8_to_wchar(dst);
char* wim_info;
PF_INIT_OR_OUT(WIMCreateFile, Wimgapi);
PF_INIT_OR_OUT(WIMSetTemporaryPath, Wimgapi);
@ -402,19 +407,30 @@ static BOOL WimExtractFile_API(const char* image, int index, const char* src, co
goto out;
}
hImage = pfWIMLoadImage(hWim, (DWORD)index);
if (hImage == NULL) {
uprintf(" Could not set index: %s", WindowsErrorString());
goto out;
}
uprintf("Extracting: %s (From %s)", dst, src);
if (!pfWIMExtractImagePath(hImage, wsrc, wdst, 0)) {
uprintf(" Could not extract file: %s", WindowsErrorString());
goto out;
if (safe_strcmp(src, index_name) == 0) {
if (!pfWIMGetImageInformation(hWim, &wim_info, &dw)) {
uprintf(" Could not access WIM info: %s", WindowsErrorString());
goto out;
}
hFile = CreateFileW(wdst, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if ((hFile == INVALID_HANDLE_VALUE) || (!WriteFile(hFile, wim_info, dw, &dw, NULL))) {
uprintf(" Could not extract file: %s", WindowsErrorString());
goto out;
}
} else {
hImage = pfWIMLoadImage(hWim, (DWORD)index);
if (hImage == NULL) {
uprintf(" Could not set index: %s", WindowsErrorString());
goto out;
}
if (!pfWIMExtractImagePath(hImage, wsrc, wdst, 0)) {
uprintf(" Could not extract file: %s", WindowsErrorString());
goto out;
}
}
r = TRUE;
UpdateProgress(OP_FINALIZE, -1.0f);
out:
if ((hImage != NULL) || (hWim != NULL)) {
@ -422,6 +438,7 @@ out:
if (hImage != NULL) pfWIMCloseHandle(hImage);
if (hWim != NULL) pfWIMCloseHandle(hWim);
}
safe_closehandle(hFile);
safe_free(wimage);
safe_free(wsrc);
safe_free(wdst);
@ -429,7 +446,7 @@ out:
}
// Extract a file from a WIM image using 7-Zip
static BOOL WimExtractFile_7z(const char* image, int index, const char* src, const char* dst)
BOOL WimExtractFile_7z(const char* image, int index, const char* src, const char* dst)
{
int n;
size_t i;
@ -455,10 +472,7 @@ static BOOL WimExtractFile_7z(const char* image, int index, const char* src, con
// to issue 2 passes. See github issue #680.
for (n = 0; n < 2; n++) {
safe_strcpy(tmpdst, sizeof(tmpdst), dst);
for (i = strlen(tmpdst) - 1; i > 0; i--) {
if (tmpdst[i] == '\\')
break;
}
for (i = strlen(tmpdst) - 1; (i > 0) && (tmpdst[i] != '\\') && (tmpdst[i] != '/'); i--);
tmpdst[i] = 0;
safe_sprintf(cmdline, sizeof(cmdline), "\"%s\" -y e \"%s\" %s%s", sevenzip_path,
@ -468,7 +482,10 @@ static BOOL WimExtractFile_7z(const char* image, int index, const char* src, con
return FALSE;
}
safe_strcat(tmpdst, sizeof(tmpdst), "\\bootmgfw.efi");
for (i = safe_strlen(src); (i > 0) && (src[i] != '\\') && (src[i] != '/'); i--);
if (i == 0)
safe_strcat(tmpdst, sizeof(tmpdst), "\\");
safe_strcat(tmpdst, sizeof(tmpdst), &src[i]);
if (_access(tmpdst, 0) == 0)
// File was extracted => move on
break;
@ -481,7 +498,7 @@ static BOOL WimExtractFile_7z(const char* image, int index, const char* src, con
// coverity[toctou]
if (rename(tmpdst, dst) != 0) {
uprintf(" Could not rename %s to %s", tmpdst, dst);
uprintf(" Could not rename %s to %s: errno %d", tmpdst, dst, errno);
return FALSE;
}