mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[togo] enable selection of Windows version
* Closes #847 * Also set rufus-next to 2.12
This commit is contained in:
parent
5113be0a39
commit
7d302d340f
15 changed files with 349 additions and 78 deletions
20
configure
vendored
20
configure
vendored
|
@ -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\\"
|
||||
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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 ##############################
|
||||
|
|
|
@ -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));
|
||||
|
|
46
src/format.c
46
src/format.c
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
25
src/parser.c
25
src/parser.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
30
src/rufus.rc
30
src/rufus.rc
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
185
src/stdlg.c
185
src/stdlg.c
|
@ -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
|
||||
|
|
39
src/vhd.c
39
src/vhd.c
|
@ -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;
|
||||
}
|
||||
|
||||
uprintf("Extracting: %s (From %s)", dst, src);
|
||||
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;
|
||||
}
|
||||
|
||||
uprintf("Extracting: %s (From %s)", dst, src);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue