From 1f2b73dfac11202d2c4c6cd14543a69096a6f7c3 Mon Sep 17 00:00:00 2001 From: Pete Batard Date: Tue, 26 Jan 2016 18:00:20 +0000 Subject: [PATCH] [vhd] fix an issue when extracting WIM with 7z * 7z has a quirk in that one MUST specify the image index when a WIM has multiple images, but the same index MUST be omitted if there is only one. * Because of this, Windows 7 Enterprise images reported a (nonfatal) extraction error when trying 7z. * Closes #680 * Also fix a typo in registry.h --- src/registry.h | 2 +- src/rufus.rc | 10 +++++----- src/stdio.c | 2 +- src/vhd.c | 54 ++++++++++++++++++++++++++++++-------------------- 4 files changed, 40 insertions(+), 28 deletions(-) diff --git a/src/registry.h b/src/registry.h index c40e60d9..24df9244 100644 --- a/src/registry.h +++ b/src/registry.h @@ -94,7 +94,7 @@ static __inline BOOL _GetRegistryKey(HKEY key_root, const char* key_name, DWORD s = RegQueryValueExA(hApp, &key_name[i], NULL, &dwType, (LPBYTE)dest, &dwSize); // No key means default value of 0 or empty string - if ((s == ERROR_FILE_NOT_FOUND) || ((s == ERROR_SUCCESS) && (dwType = reg_type) && (dwSize > 0))) { + if ((s == ERROR_FILE_NOT_FOUND) || ((s == ERROR_SUCCESS) && (dwType == reg_type) && (dwSize > 0))) { r = TRUE; } out: diff --git a/src/rufus.rc b/src/rufus.rc index ca38c320..9391c02d 100644 --- a/src/rufus.rc +++ b/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.7.838" +CAPTION "Rufus 2.7.839" FONT 8, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8 @@ -320,8 +320,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,7,838,0 - PRODUCTVERSION 2,7,838,0 + FILEVERSION 2,7,839,0 + PRODUCTVERSION 2,7,839,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -338,13 +338,13 @@ BEGIN BEGIN VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "2.7.838" + VALUE "FileVersion", "2.7.839" 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.7.838" + VALUE "ProductVersion", "2.7.839" END END BLOCK "VarFileInfo" diff --git a/src/stdio.c b/src/stdio.c index eea19492..df8caf5b 100644 --- a/src/stdio.c +++ b/src/stdio.c @@ -1,7 +1,7 @@ /* * Rufus: The Reliable USB Formatting Utility * Standard User I/O Routines (logging, status, etc.) - * Copyright © 2011-2015 Pete Batard + * Copyright © 2011-2016 Pete Batard * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/vhd.c b/src/vhd.c index b73749a2..5a39aa49 100644 --- a/src/vhd.c +++ b/src/vhd.c @@ -439,42 +439,54 @@ 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) { + int n; size_t i; - STARTUPINFOA si = {0}; - PROCESS_INFORMATION pi = {0}; char cmdline[MAX_PATH]; char tmpdst[MAX_PATH]; + char index_prefix[] = "#\\"; uprintf("Opening: %s:[%d] (7-Zip)", image, index); if ((image == NULL) || (src == NULL) || (dst == NULL)) return FALSE; - safe_strcpy(tmpdst, sizeof(tmpdst), dst); - for (i=strlen(tmpdst)-1; i>0; i--) { - if (tmpdst[i] == '\\') + // If you shove more than 9 images in a WIM, don't come complaining + // that this breaks! + index_prefix[0] = '0' + index; + + uprintf("Extracting: %s (From %s)", dst, src); + + // 7z has a quirk where the image index MUST be specified if a + // WIM has multiple indexes, but it MUST be removed if there is + // only one image. Because of this (and because 7z will not + // return an error code if it can't extract the file), we need + // 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; + } + tmpdst[i] = 0; + + safe_sprintf(cmdline, sizeof(cmdline), "\"%s\" -y e \"%s\" %s%s", sevenzip_path, + image, (n == 0) ? index_prefix : "", src); + if (RunCommand(cmdline, tmpdst, FALSE) != 0) { + uprintf(" Could not launch 7z.exe: %s", WindowsErrorString()); + return FALSE; + } + + safe_strcat(tmpdst, sizeof(tmpdst), "\\bootmgfw.efi"); + if (_access(tmpdst, 0) == 0) + // File was extracted => move on break; } - tmpdst[i] = 0; - // TODO: use RunCommand - si.cb = sizeof(si); - safe_sprintf(cmdline, sizeof(cmdline), "7z -y e \"%s\" %d\\%s", image, index, src); - uprintf("Extracting: %s (From %s)", dst, src); - if (!CreateProcessU(sevenzip_path, cmdline, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, tmpdst, &si, &pi)) { - uprintf(" Could not launch 7z.exe: %s", WindowsErrorString()); - return FALSE; - } - WaitForSingleObject(pi.hProcess, INFINITE); - UpdateProgress(OP_FINALIZE, -1.0f); - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - - safe_strcat(tmpdst, sizeof(tmpdst), "\\bootmgfw.efi"); - if (_access(tmpdst, 0) == -1) { + if (n >= 2) { uprintf(" 7z.exe did not extract %s", tmpdst); return FALSE; } + // coverity[toctou] if (rename(tmpdst, dst) != 0) { uprintf(" Could not rename %s to %s", tmpdst, dst);