[togo] Add Windows To Go support - part 2

* Closes #126
* Only supported on Windows 8 or later for now
* Also fix MinGW and WDK compilation issues
This commit is contained in:
Pete Batard 2015-01-16 01:51:24 +00:00
parent 295650a8b4
commit 032d4413c8
17 changed files with 251 additions and 70 deletions

View File

@ -259,9 +259,16 @@ t MSG_093 "IMPORTANT: THIS DRIVE CONTAINS MULTIPLE PARTITIONS!!\n\n"
"Should you wish to proceed, you are responsible for any data loss on these partitions." "Should you wish to proceed, you are responsible for any data loss on these partitions."
t MSG_094 "Multiple partitions detected" t MSG_094 "Multiple partitions detected"
t MSG_095 "DD Image" t MSG_095 "DD Image"
t MSG_096 "Only FAT/FAT32 is supported for this type of ISO. Please select FAT/FAT32 as the File system." t MSG_096 "The file system currently selected can not be used with this type of ISO. "
t MSG_097 "Only 'bootmgr' or 'WinPE' based ISO images can currently be used with NTFS." "Please select a different file system or use a different ISO."
t MSG_098 "FAT/FAT32 can only be used for isolinux based ISO images or when the Target Type is UEFI." t MSG_097 "'Windows To Go' can only be applied if the file system is NTFS."
t MSG_098 "IMPORTANT: You are trying to install 'Windows To Go', but your USB drive doesn't "
"have the 'FIXED' attribute. Because of this Windows will most likely freeze during boot, "
"as Microsoft hasn't designed it to work with drives that are 'REMOVABLE'.\n\n"
"Do you still want to proceed?\n\n"
"Note: the 'FIXED/REMOVABLE' attribute is a hardware property that can only be changed "
"using custom tools from the drive manufacturer. However those tools are ALMOST NEVER "
"provided to the public..."
t MSG_099 "Filesystem limitation" t MSG_099 "Filesystem limitation"
t MSG_100 "This ISO image contains a file larger than 4GB, which is more than the " t MSG_100 "This ISO image contains a file larger than 4GB, which is more than the "
"maximum size allowed for a FAT or FAT32 file system." "maximum size allowed for a FAT or FAT32 file system."
@ -364,6 +371,7 @@ t MSG_186 "Rufus does not install or run background services, therefore update c
t MSG_187 "Invalid image for selected boot option" t MSG_187 "Invalid image for selected boot option"
t MSG_188 "The current image doesn't match the boot option selected. Please use a different image or choose a different boot option." t MSG_188 "The current image doesn't match the boot option selected. Please use a different image or choose a different boot option."
t MSG_189 "This ISO image is not compatible with the selected filesystem" t MSG_189 "This ISO image is not compatible with the selected filesystem"
t MSG_190 "Incompatible drive detected"
t MSG_191 "Write pass" t MSG_191 "Write pass"
t MSG_192 "Read pass" t MSG_192 "Read pass"
t MSG_193 "Downloaded %s" t MSG_193 "Downloaded %s"

11
res/togo/san_policy.xml Normal file
View File

@ -0,0 +1,11 @@
<?xml version='1.0' encoding='utf-8' standalone='yes'?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
<settings pass="offlineServicing">
<component name="Microsoft-Windows-PartitionManager" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SanPolicy>4</SanPolicy>
</component>
<component name="Microsoft-Windows-PartitionManager" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SanPolicy>4</SanPolicy>
</component>
</settings>
</unattend>

11
res/togo/unattend.xml Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend">
<settings pass="oobeSystem">
<component name="Microsoft-Windows-WinRE-RecoveryAgent" processorArchitecture="x86" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<UninstallWindowsRE>true</UninstallWindowsRE>
</component>
<component name="Microsoft-Windows-WinRE-RecoveryAgent" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<UninstallWindowsRE>true</UninstallWindowsRE>
</component>
</settings>
</unattend>

View File

@ -223,7 +223,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\..\res\down.ico" /> <None Include="..\..\res\down.ico" />
<None Include="..\..\res\localization\rufus.loc" />
<None Include="..\..\res\rufus.ico" /> <None Include="..\..\res\rufus.ico" />
<None Include="..\..\res\up.ico" /> <None Include="..\..\res\up.ico" />
</ItemGroup> </ItemGroup>

View File

@ -139,9 +139,6 @@
<None Include="..\..\res\down.ico"> <None Include="..\..\res\down.ico">
<Filter>Resource Files</Filter> <Filter>Resource Files</Filter>
</None> </None>
<None Include="..\..\res\localization\rufus.loc">
<Filter>Resource Files</Filter>
</None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Manifest Include="..\common_controls_and_elevation.manifest"> <Manifest Include="..\common_controls_and_elevation.manifest">

View File

@ -187,6 +187,11 @@ static inline ssize_t full_read(int fd, void *buf, size_t count) {
return rb; return rb;
} }
static inline struct tm *localtime_r(const time_t *timep, struct tm *result) {
result = localtime(timep);
return result;
}
#define full_write _write #define full_write _write
#define safe_read full_read #define safe_read full_read
#define lstat stat #define lstat stat
@ -197,11 +202,6 @@ static inline ssize_t full_read(int fd, void *buf, size_t count) {
#define mkdir(x, y) _mkdirU(x) #define mkdir(x, y) _mkdirU(x)
#if defined(_MSC_VER) #if defined(_MSC_VER)
static inline struct tm *localtime_r(const time_t *timep, struct tm *result) {
result = localtime(timep);
return result;
}
#define _S_IFBLK 0x3000 #define _S_IFBLK 0x3000
#define S_IFMT _S_IFMT #define S_IFMT _S_IFMT

View File

@ -751,7 +751,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
SelectedDrive.nPartitions++; SelectedDrive.nPartitions++;
tmp[0] = 0; tmp[0] = 0;
wchar_to_utf8_no_alloc(DriveLayout->PartitionEntry[i].Gpt.Name, tmp, sizeof(tmp)); wchar_to_utf8_no_alloc(DriveLayout->PartitionEntry[i].Gpt.Name, tmp, sizeof(tmp));
suprintf("Partition %d:\r\n Type: %s\r\n Name: '%s'\n", DriveLayout->PartitionEntry[i].PartitionNumber, suprintf("Partition %d:\r\n Type: %s\r\n Name: '%s'\n", i+1,
GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionType), tmp); GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionType), tmp);
suprintf(" ID: %s\r\n Size: %s (%lld bytes)\r\n Start Sector: %lld, Attributes: 0x%016llX\n", suprintf(" ID: %s\r\n Size: %s (%lld bytes)\r\n Start Sector: %lld, Attributes: 0x%016llX\n",
GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionId), SizeToHumanReadable(DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, TRUE, FALSE), GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionId), SizeToHumanReadable(DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, TRUE, FALSE),

View File

@ -1225,6 +1225,79 @@ out:
return r; return r;
} }
// http://technet.microsoft.com/en-ie/library/jj721578.aspx
static BOOL SetupWinToGo(const char* drive_name)
{
char san_policy_path[] = "?:\\san_policy.xml", unattend_path[] = "?:\\Windows\\System32\\sysprep\\unattend.xml";
char *mounted_iso, image[128], cmd[128];
unsigned char *buffer;
DWORD bufsize;
FILE* fd;
uprintf("Windows To Go mode selected");
// First, we need to access the install.wim image, that resides on the ISO
mounted_iso = MountISO(image_path);
if (mounted_iso == NULL) {
uprintf("Could not mount ISO for Windows To Go installation");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_EXTRACT);
return FALSE;
}
uprintf("Mounted ISO as '%s'", mounted_iso);
// Now we use the WIM API to apply that image
static_sprintf(image, "%s\\sources\\install.wim", mounted_iso);
if (!WimApplyImage(image, 1, 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);
UnMountISO();
return FALSE;
}
UnMountISO();
uprintf("Setting up boot for Windows To Go...");
static_sprintf(cmd, "%C:\\Windows\\System32\\bcdboot.exe %C:\\Windows /f ALL /s %C:",
drive_name[0], drive_name[0], drive_name[0]);
if (RunCommand(cmd, NULL, TRUE) != 0) {
// Fatal, as the UFD is unlikely to boot then
uprintf("Command '%s' failed to run", cmd);
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_EXTRACT);
return FALSE;
}
UpdateProgress(OP_DOS, 99.0f);
// The following are non fatal if they fail
buffer = GetResource(hMainInstance, MAKEINTRESOURCEA(IDR_TOGO_SAN_POLICY_XML),
_RT_RCDATA, "san_policy.xml", &bufsize, FALSE);
san_policy_path[0] = drive_name[0];
uprintf("Applying san_policy.xml...");
fd = fopenU(san_policy_path, "wb");
if ((fd == NULL) || (fwrite(buffer, 1, bufsize, fd) != bufsize)) {
uprintf("Could not write '%s'\n", san_policy_path);
if (fd)
fclose(fd);
} else {
fclose(fd);
static_sprintf(cmd, "dism /Image:%C:\\ /Apply-Unattend:%s", drive_name[0], san_policy_path);
if (RunCommand(cmd, NULL, TRUE) != 0)
uprintf("Command '%s' failed to run");
}
uprintf("Copying 'unattend.xml'");
buffer = GetResource(hMainInstance, MAKEINTRESOURCEA(IDR_TOGO_UNATTEND_XML),
_RT_RCDATA, "unattend.xml", &bufsize, FALSE);
unattend_path[0] = drive_name[0];
fd = fopenU(unattend_path, "wb");
if ((fd == NULL) || (fwrite(buffer, 1, bufsize, fd) != bufsize)) {
uprintf("Could not write '%s'\n", unattend_path);
}
fclose(fd);
UpdateProgress(OP_DOS, 100.0f);
return TRUE;
}
/* /*
* Detect if a Windows Format prompt is active, by enumerating the * Detect if a Windows Format prompt is active, by enumerating the
* whole Windows tree and looking for the relevant popup * whole Windows tree and looking for the relevant popup
@ -1305,10 +1378,10 @@ DWORD WINAPI FormatThread(void* param)
LARGE_INTEGER li; LARGE_INTEGER li;
uint64_t wb; uint64_t wb;
uint8_t *buffer = NULL, *aligned_buffer; uint8_t *buffer = NULL, *aligned_buffer;
char *bb_msg, *guid_volume = NULL, *mounted_iso; char *bb_msg, *guid_volume = NULL;
char drive_name[] = "?:\\"; char drive_name[] = "?:\\";
char drive_letters[27]; char drive_letters[27];
char logfile[MAX_PATH], image[128], *userdir; char logfile[MAX_PATH], *userdir;
char wim_image[] = "?:\\sources\\install.wim"; char wim_image[] = "?:\\sources\\install.wim";
char efi_dst[] = "?:\\efi\\boot\\bootx64.efi"; char efi_dst[] = "?:\\efi\\boot\\bootx64.efi";
char kolibri_dst[] = "?:\\MTLD_F32"; char kolibri_dst[] = "?:\\MTLD_F32";
@ -1693,28 +1766,24 @@ DWORD WINAPI FormatThread(void* param)
UpdateProgress(OP_DOS, 0.0f); UpdateProgress(OP_DOS, 0.0f);
PrintInfoDebug(0, MSG_231); PrintInfoDebug(0, MSG_231);
drive_name[2] = 0; drive_name[2] = 0;
// TODO: Check that we have apply-wim support
if (HAS_TOGO(iso_report) && (Button_GetCheck(GetDlgItem(hMainDialog, IDC_WINDOWS_TO_GO)) == BST_CHECKED)) { if (HAS_TOGO(iso_report) && (Button_GetCheck(GetDlgItem(hMainDialog, IDC_WINDOWS_TO_GO)) == BST_CHECKED)) {
uprintf("Windows To Go mode selected"); // Sanity checks
mounted_iso = MountISO(image_path); if (fs != FS_NTFS) {
if (mounted_iso == NULL) { FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_INCOMPATIBLE_FS);
uprintf("Could not mount ISO for Windows To Go installation");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_EXTRACT);
} else {
uprintf("Mounted ISO as '%s'", mounted_iso);
static_sprintf(image, "%s\\sources\\install.wim", mounted_iso);
if (!WimApplyImage(image, 1, drive_name)) {
uprintf("Failed to setup Windows To Go");
if (!IS_ERROR(FormatStatus))
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_EXTRACT);
}
UnMountISO();
}
if (IS_ERROR(FormatStatus))
goto out; goto out;
}
if ((nWindowsVersion < WINDOWS_8) || ((WimExtractCheck() & 4) == 0)) {
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_SUPPORTED;
goto out;
}
if (!SetupWinToGo(drive_name)) {
if (!IS_ERROR(FormatStatus))
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_ISO_EXTRACT;
goto out;
}
} else if (!ExtractISO(image_path, drive_name, FALSE)) { } else if (!ExtractISO(image_path, drive_name, FALSE)) {
if (!IS_ERROR(FormatStatus)) if (!IS_ERROR(FormatStatus))
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY; FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_ISO_EXTRACT;
goto out; goto out;
} }
if (iso_report.has_kolibrios) { if (iso_report.has_kolibrios) {

View File

@ -925,8 +925,8 @@ out:
/* /*
* The following is used for native ISO mounting in Windows 8 or later * The following is used for native ISO mounting in Windows 8 or later
*/ */
const GUID VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT = #define VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT \
{ 0xEC984AECL, 0xA0F9, 0x47e9, { 0x90, 0x1F, 0x71, 0x41, 0x5A, 0x66, 0x34, 0x5B } }; { 0xEC984AECL, 0xA0F9, 0x47e9, { 0x90, 0x1F, 0x71, 0x41, 0x5A, 0x66, 0x34, 0x5B } }
typedef enum _VIRTUAL_DISK_ACCESS_MASK { typedef enum _VIRTUAL_DISK_ACCESS_MASK {
VIRTUAL_DISK_ACCESS_NONE = 0x00000000, VIRTUAL_DISK_ACCESS_NONE = 0x00000000,
@ -1015,7 +1015,7 @@ static HANDLE mounted_handle = INVALID_HANDLE_VALUE;
char* MountISO(const char* path) char* MountISO(const char* path)
{ {
VIRTUAL_STORAGE_TYPE vtype = { 1, VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT }; VIRTUAL_STORAGE_TYPE vtype = { 1, VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT };
ATTACH_VIRTUAL_DISK_PARAMETERS vparams = { ATTACH_VIRTUAL_DISK_VERSION_1, 0 }; ATTACH_VIRTUAL_DISK_PARAMETERS vparams = {0};
DWORD r; DWORD r;
wchar_t wtmp[128]; wchar_t wtmp[128];
ULONG size = ARRAYSIZE(wtmp); ULONG size = ARRAYSIZE(wtmp);
@ -1037,6 +1037,7 @@ char* MountISO(const char* path)
goto out; goto out;
} }
vparams.Version = ATTACH_VIRTUAL_DISK_VERSION_1;
r = pfAttachVirtualDisk(mounted_handle, NULL, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY | r = pfAttachVirtualDisk(mounted_handle, NULL, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY |
ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER, 0, &vparams, NULL); ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER, 0, &vparams, NULL);
if (r != ERROR_SUCCESS) { if (r != ERROR_SUCCESS) {

View File

@ -407,11 +407,11 @@ char* lmprintf(int msg_id, ...)
#define MSG_INFO 1 #define MSG_INFO 1
#define MSG_LOW_PRI 0 #define MSG_LOW_PRI 0
#define MSG_HIGH_PRI 1 #define MSG_HIGH_PRI 1
char szMessage[2][2][MSG_LEN] = { 0 }; char szMessage[2][2][MSG_LEN] = { {"", ""}, {"", ""} };
char* szStatusMessage = szMessage[MSG_STATUS][MSG_HIGH_PRI]; char* szStatusMessage = szMessage[MSG_STATUS][MSG_HIGH_PRI];
static BOOL bStatusTimerArmed = FALSE; static BOOL bStatusTimerArmed = FALSE;
static __inline OutputMessage(BOOL info, char* msg) static void __inline OutputMessage(BOOL info, char* msg)
{ {
if (info) if (info)
SetWindowTextU(hInfo, msg); SetWindowTextU(hInfo, msg);

View File

@ -506,9 +506,9 @@ static __inline int SHDeleteDirectoryExU(HWND hwnd, const char* pszPath, FILEOP_
// which is always expected to be larger than our UTF-16 one, and add 2 chars for good measure. // which is always expected to be larger than our UTF-16 one, and add 2 chars for good measure.
size_t wpszPath_len = strlen(pszPath) + 2; size_t wpszPath_len = strlen(pszPath) + 2;
wchar_t* wpszPath = (wchar_t*)calloc(wpszPath_len, sizeof(wchar_t)); wchar_t* wpszPath = (wchar_t*)calloc(wpszPath_len, sizeof(wchar_t));
SHFILEOPSTRUCTW shfo = { hwnd, FO_DELETE, wpszPath, NULL, fFlags, FALSE, NULL, NULL };
utf8_to_wchar_no_alloc(pszPath, wpszPath, wpszPath_len); utf8_to_wchar_no_alloc(pszPath, wpszPath, wpszPath_len);
// FOF_SILENT | FOF_NOERRORUI | FOF_NOCONFIRMATION, // FOF_SILENT | FOF_NOERRORUI | FOF_NOCONFIRMATION,
SHFILEOPSTRUCTW shfo = { hwnd, FO_DELETE, wpszPath, NULL, fFlags, FALSE, NULL, NULL };
ret = SHFileOperationW(&shfo); ret = SHFileOperationW(&shfo);
wfree(pszPath); wfree(pszPath);
return ret; return ret;

View File

@ -70,6 +70,8 @@
#define IDR_LC_RUFUS_LOC 500 #define IDR_LC_RUFUS_LOC 500
#define IDR_XT_HOGGER 501 #define IDR_XT_HOGGER 501
#define IDR_UEFI_TOGO 502 #define IDR_UEFI_TOGO 502
#define IDR_TOGO_SAN_POLICY_XML 503
#define IDR_TOGO_UNATTEND_XML 504
#define IDC_DEVICE 1001 #define IDC_DEVICE 1001
#define IDC_FILESYSTEM 1002 #define IDC_FILESYSTEM 1002
#define IDC_START 1003 #define IDC_START 1003
@ -411,7 +413,7 @@
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS #ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1 #define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 502 #define _APS_NEXT_RESOURCE_VALUE 505
#define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1071 #define _APS_NEXT_CONTROL_VALUE 1071
#define _APS_NEXT_SYMED_VALUE 4000 #define _APS_NEXT_SYMED_VALUE 4000

View File

@ -933,8 +933,11 @@ static void DisplayISOProps(void)
uprintf(" Uses ReactOS: %s", YesNo(IS_REACTOS(iso_report))); uprintf(" Uses ReactOS: %s", YesNo(IS_REACTOS(iso_report)));
uprintf(" Uses WinPE: %s%s", YesNo(IS_WINPE(iso_report.winpe)), (iso_report.uses_minint) ? " (with /minint)" : ""); uprintf(" Uses WinPE: %s%s", YesNo(IS_WINPE(iso_report.winpe)), (iso_report.uses_minint) ? " (with /minint)" : "");
if ( ((!togo_mode) && (HAS_TOGO(iso_report))) || ((togo_mode) && (!HAS_TOGO(iso_report))) ) // We don't support ToGo on Windows 7 or earlier, for lack of ISO mount capabilities
ToggleToGo(); // TODO: add install.wim extraction workaround for Windows 7
if (nWindowsVersion >= WINDOWS_8)
if ( ((!togo_mode) && (HAS_TOGO(iso_report))) || ((togo_mode) && (!HAS_TOGO(iso_report))) )
ToggleToGo();
} }
// The scanning process can be blocking for message processing => use a thread // The scanning process can be blocking for message processing => use a thread
@ -1186,7 +1189,18 @@ static BOOL BootCheck(void)
} }
fs = (int)ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem)); fs = (int)ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem));
bt = GETBIOSTYPE((int)ComboBox_GetItemData(hPartitionScheme, ComboBox_GetCurSel(hPartitionScheme))); bt = GETBIOSTYPE((int)ComboBox_GetItemData(hPartitionScheme, ComboBox_GetCurSel(hPartitionScheme)));
if (bt == BT_UEFI) { if ((togo_mode) && (Button_GetCheck(GetDlgItem(hMainDialog, IDC_WINDOWS_TO_GO)) == BST_CHECKED)) {
if (fs != FS_NTFS) {
// Windows To Go only works for NTFS
MessageBoxU(hMainDialog, lmprintf(MSG_097), lmprintf(MSG_092), MB_OK|MB_ICONERROR|MB_IS_RTL);
return FALSE;
} else if (SelectedDrive.Geometry.MediaType != FixedMedia) {
// I never had any success with drives that have the REMOVABLE attribute set, no matter the
// method or tool I tried. If you manage to get this working, I'd like to hear from you!
if (MessageBoxU(hMainDialog, lmprintf(MSG_098), lmprintf(MSG_190), MB_YESNO|MB_ICONWARNING|MB_IS_RTL) != IDYES)
return FALSE;
}
} else if (bt == BT_UEFI) {
if (!iso_report.has_efi) { if (!iso_report.has_efi) {
// Unsupported ISO // Unsupported ISO
MessageBoxU(hMainDialog, lmprintf(MSG_091), lmprintf(MSG_090), MB_OK|MB_ICONERROR|MB_IS_RTL); MessageBoxU(hMainDialog, lmprintf(MSG_091), lmprintf(MSG_090), MB_OK|MB_ICONERROR|MB_IS_RTL);
@ -1198,24 +1212,16 @@ static BOOL BootCheck(void)
ShellExecuteA(hMainDialog, "open", SEVENZIP_URL, NULL, NULL, SW_SHOWNORMAL); ShellExecuteA(hMainDialog, "open", SEVENZIP_URL, NULL, NULL, SW_SHOWNORMAL);
return FALSE; return FALSE;
} }
} else if ((fs == FS_NTFS) && (!iso_report.has_bootmgr) && (!IS_WINPE(iso_report.winpe)) && (!IS_GRUB(iso_report))) { } else if ( ((fs == FS_NTFS) && (!iso_report.has_bootmgr) && (!IS_WINPE(iso_report.winpe)) && (!IS_GRUB(iso_report)))
if (HAS_SYSLINUX(iso_report)) { || (((fs == FS_FAT16)||(fs == FS_FAT32)) && (!HAS_SYSLINUX(iso_report)) && (!allow_dual_uefi_bios) &&
// Only FAT/FAT32 is supported for this type of ISO (!IS_REACTOS(iso_report)) && (!iso_report.has_kolibrios) && (!IS_GRUB(iso_report))) ) {
MessageBoxU(hMainDialog, lmprintf(MSG_096), lmprintf(MSG_092), MB_OK|MB_ICONERROR|MB_IS_RTL); // Incompatible FS and ISO
} else { MessageBoxU(hMainDialog, lmprintf(MSG_096), lmprintf(MSG_092), MB_OK|MB_ICONERROR|MB_IS_RTL);
// Only 'bootmgr' or 'WinPE' based ISO images can currently be used with NTFS
MessageBoxU(hMainDialog, lmprintf(MSG_097), lmprintf(MSG_090), MB_OK|MB_ICONERROR|MB_IS_RTL);
}
return FALSE; return FALSE;
} else if ((fs == FS_FAT16) && (iso_report.has_kolibrios)) { } else if ((fs == FS_FAT16) && (iso_report.has_kolibrios)) {
// KolibriOS doesn't support FAT16 // KolibriOS doesn't support FAT16
MessageBoxU(hMainDialog, lmprintf(MSG_189), lmprintf(MSG_099), MB_OK|MB_ICONERROR|MB_IS_RTL); MessageBoxU(hMainDialog, lmprintf(MSG_189), lmprintf(MSG_099), MB_OK|MB_ICONERROR|MB_IS_RTL);
return FALSE; return FALSE;
} else if (((fs == FS_FAT16)||(fs == FS_FAT32)) && (!HAS_SYSLINUX(iso_report)) && (!allow_dual_uefi_bios) &&
(!IS_REACTOS(iso_report)) && (!iso_report.has_kolibrios) && (!IS_GRUB(iso_report))) {
// FAT/FAT32 can only be used for isolinux based ISO images or when the Target Type is UEFI
MessageBoxU(hMainDialog, lmprintf(MSG_098), lmprintf(MSG_090), MB_OK|MB_ICONERROR|MB_IS_RTL);
return FALSE;
} }
if (((fs == FS_FAT16)||(fs == FS_FAT32)) && (iso_report.has_4GB_file)) { if (((fs == FS_FAT16)||(fs == FS_FAT32)) && (iso_report.has_4GB_file)) {
// This ISO image contains a file larger than 4GB file (FAT32) // This ISO image contains a file larger than 4GB file (FAT32)
@ -2153,6 +2159,16 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_START_THREAD); FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_START_THREAD);
} }
break; break;
case IDC_WINDOWS_TO_GO:
if (Button_GetCheck(GetDlgItem(hMainDialog, IDC_WINDOWS_TO_GO)) == BST_CHECKED) {
for (i=0; i<ComboBox_GetCount(hFileSystem); i++) {
if (ComboBox_GetItemData(hFileSystem, i) == FS_NTFS) {
IGNORE_RETVAL(ComboBox_SetCurSel(hFileSystem, i));
break;
}
}
}
break;
case IDC_RUFUS_MBR: case IDC_RUFUS_MBR:
if ((HIWORD(wParam)) == BN_CLICKED) if ((HIWORD(wParam)) == BN_CLICKED)
mbr_selected_by_user = IsChecked(IDC_RUFUS_MBR); mbr_selected_by_user = IsChecked(IDC_RUFUS_MBR);

View File

@ -395,6 +395,7 @@ extern char* FileDialog(BOOL save, char* path, const ext_t* ext, DWORD options);
extern BOOL FileIO(BOOL save, char* path, char** buffer, DWORD* size); extern BOOL FileIO(BOOL save, char* path, char** buffer, DWORD* size);
extern unsigned char* GetResource(HMODULE module, char* name, char* type, const char* desc, DWORD* len, BOOL duplicate); extern unsigned char* GetResource(HMODULE module, char* name, char* type, const char* desc, DWORD* len, BOOL duplicate);
extern DWORD GetResourceSize(HMODULE module, char* name, char* type, const char* desc); extern DWORD GetResourceSize(HMODULE module, char* name, char* type, const char* desc);
extern DWORD RunCommand(const char* cmdline, const char* dir, BOOL log);
extern BOOL GetUSBDevices(DWORD devnum); extern BOOL GetUSBDevices(DWORD devnum);
extern BOOL SetLGP(BOOL bRestore, BOOL* bExistingKey, const char* szPath, const char* szPolicy, DWORD dwValue); extern BOOL SetLGP(BOOL bRestore, BOOL* bExistingKey, const char* szPath, const char* szPolicy, DWORD dwValue);
extern LONG GetEntryWidth(HWND hDropDown, const char* entry); extern LONG GetEntryWidth(HWND hDropDown, const char* entry);

View File

@ -32,7 +32,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 242, 376 IDD_DIALOG DIALOGEX 12, 12, 242, 376
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Rufus 2.0.0.574" CAPTION "Rufus 2.0.0.575"
FONT 8, "Segoe UI", 400, 0, 0x1 FONT 8, "Segoe UI", 400, 0, 0x1
BEGIN BEGIN
DEFPUSHBUTTON "Start",IDC_START,127,339,50,14 DEFPUSHBUTTON "Start",IDC_START,127,339,50,14
@ -157,7 +157,7 @@ END
IDD_DIALOG_XP DIALOGEX 12, 12, 242, 376 IDD_DIALOG_XP DIALOGEX 12, 12, 242, 376
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Rufus 2.0.0.574" CAPTION "Rufus 2.0.0.575"
FONT 8, "MS Shell Dlg", 400, 0, 0x1 FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN BEGIN
DEFPUSHBUTTON "Start",IDC_START,127,339,50,14 DEFPUSHBUTTON "Start",IDC_START,127,339,50,14
@ -283,7 +283,7 @@ END
IDD_DIALOG_RTL DIALOGEX 12, 12, 242, 376 IDD_DIALOG_RTL DIALOGEX 12, 12, 242, 376
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL
CAPTION "Rufus 2.0.0.574" CAPTION "Rufus 2.0.0.575"
FONT 8, "Segoe UI", 400, 0, 0x1 FONT 8, "Segoe UI", 400, 0, 0x1
BEGIN BEGIN
DEFPUSHBUTTON "Start",IDC_START,127,339,50,14 DEFPUSHBUTTON "Start",IDC_START,127,339,50,14
@ -415,7 +415,7 @@ END
IDD_DIALOG_RTL_XP DIALOGEX 12, 12, 242, 376 IDD_DIALOG_RTL_XP DIALOGEX 12, 12, 242, 376
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL EXSTYLE WS_EX_RTLREADING | WS_EX_APPWINDOW | WS_EX_LAYOUTRTL
CAPTION "Rufus 2.0.0.574" CAPTION "Rufus 2.0.0.575"
FONT 8, "MS Shell Dlg", 400, 0, 0x1 FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN BEGIN
DEFPUSHBUTTON "Start",IDC_START,127,339,50,14 DEFPUSHBUTTON "Start",IDC_START,127,339,50,14
@ -612,6 +612,8 @@ BEGIN
"IDR_FD_EGA18_CPX RCDATA ""../res/freedos/ega18.cpx""\r\n" "IDR_FD_EGA18_CPX RCDATA ""../res/freedos/ega18.cpx""\r\n"
"IDR_XT_HOGGER RCDATA ""../res/hogger/hogger.exe""\r\n" "IDR_XT_HOGGER RCDATA ""../res/hogger/hogger.exe""\r\n"
"IDR_UEFI_TOGO RCDATA ""../res/uefi/uefi-togo.img""\r\n" "IDR_UEFI_TOGO RCDATA ""../res/uefi/uefi-togo.img""\r\n"
"IDR_TOGO_SAN_POLICY_XML RCDATA ""../res/togo/san_policy.xml""\r\n"
"IDR_TOGO_UNATTEND_XML RCDATA ""../res/togo/unattend.xml""\r\n"
"\r\n" "\r\n"
"// Must reference a manifest for visual styles and elevation\r\n" "// Must reference a manifest for visual styles and elevation\r\n"
"// Oh, and it must happen at the end, or MinGW will ignore it!\r\n" "// Oh, and it must happen at the end, or MinGW will ignore it!\r\n"
@ -669,8 +671,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,0,0,574 FILEVERSION 2,0,0,575
PRODUCTVERSION 2,0,0,574 PRODUCTVERSION 2,0,0,575
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -687,13 +689,13 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
VALUE "FileDescription", "Rufus" VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "2.0.0.574" VALUE "FileVersion", "2.0.0.575"
VALUE "InternalName", "Rufus" VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2015 Pete Batard (GPL v3)" VALUE "LegalCopyright", "© 2011-2015 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", "2.0.0.574" VALUE "ProductVersion", "2.0.0.575"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"
@ -765,6 +767,8 @@ IDR_FD_EGA17_CPX RCDATA "../res/freedos/ega17.cpx"
IDR_FD_EGA18_CPX RCDATA "../res/freedos/ega18.cpx" IDR_FD_EGA18_CPX RCDATA "../res/freedos/ega18.cpx"
IDR_XT_HOGGER RCDATA "../res/hogger/hogger.exe" IDR_XT_HOGGER RCDATA "../res/hogger/hogger.exe"
IDR_UEFI_TOGO RCDATA "../res/uefi/uefi-togo.img" IDR_UEFI_TOGO RCDATA "../res/uefi/uefi-togo.img"
IDR_TOGO_SAN_POLICY_XML RCDATA "../res/togo/san_policy.xml"
IDR_TOGO_UNATTEND_XML RCDATA "../res/togo/unattend.xml"
// Must reference a manifest for visual styles and elevation // Must reference a manifest for visual styles and elevation
// Oh, and it must happen at the end, or MinGW will ignore it! // Oh, and it must happen at the end, or MinGW will ignore it!

View File

@ -528,6 +528,68 @@ DWORD GetResourceSize(HMODULE module, char* name, char* type, const char* desc)
return (GetResource(module, name, type, desc, &len, FALSE) == NULL)?0:len; return (GetResource(module, name, type, desc, &len, FALSE) == NULL)?0:len;
} }
// Run a console command, with optional redirection of stdout and stderr to our log
DWORD RunCommand(const char* cmd, const char* dir, BOOL log)
{
DWORD ret, dwRead, dwAvail, dwMsg;
STARTUPINFOA si = {0};
PROCESS_INFORMATION pi = {0};
HANDLE hOutputRead = INVALID_HANDLE_VALUE, hOutputWrite = INVALID_HANDLE_VALUE;
HANDLE hDupOutputWrite = INVALID_HANDLE_VALUE;
char output[1024];
si.cb = sizeof(si);
if (log) {
if (!CreatePipe(&hOutputRead, &hOutputWrite, NULL, sizeof(output)-1)) {
ret = GetLastError();
uprintf("Could not set commandline pipe: %s", WindowsErrorString());
goto out;
}
// We need an inheritable pipe endpoint handle
DuplicateHandle(GetCurrentProcess(), hOutputWrite, GetCurrentProcess(), &hDupOutputWrite,
0L, TRUE, DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
si.hStdOutput = hDupOutputWrite;
si.hStdError = hDupOutputWrite;
}
if (!CreateProcessU(NULL, cmd, NULL, NULL, TRUE,
NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW, NULL, dir, &si, &pi)) {
ret = GetLastError();
uprintf("Unable to launch command '%s': %s", WindowsErrorString());
goto out;
}
if (log) {
while (1) {
if (PeekNamedPipe(hOutputRead, output, sizeof(output)-1, &dwRead, &dwAvail, &dwMsg)) {
// Don't care about possible multiple reads being needed
if ((dwAvail != 0) && (ReadFile(hOutputRead, output, dwAvail, &dwRead, NULL)) && (dwRead != 0)) {
// This seems to be needed. Won't overflow since we set our max sizes to sizeof(output)-1
output[dwAvail] = 0;
uprintf(output);
}
}
if (WaitForSingleObject(pi.hProcess, 0) == WAIT_OBJECT_0)
break;
Sleep(100);
};
} else {
WaitForSingleObject(pi.hProcess, INFINITE);
}
if (!GetExitCodeProcess(pi.hProcess, &ret))
ret = GetLastError();
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
out:
safe_closehandle(hDupOutputWrite);
safe_closehandle(hOutputRead);
return ret;
}
/* /*
* Set or restore a Local Group Policy DWORD key indexed by szPath/SzPolicy * Set or restore a Local Group Policy DWORD key indexed by szPath/SzPolicy
*/ */

View File

@ -430,6 +430,7 @@ static BOOL WimExtractFile_7z(const char* image, int index, const char* src, con
} }
tmpdst[i] = 0; tmpdst[i] = 0;
// TODO: use RunCommand
si.cb = sizeof(si); si.cb = sizeof(si);
safe_sprintf(cmdline, sizeof(cmdline), "7z -y e \"%s\" %d\\%s", image, index, src); safe_sprintf(cmdline, sizeof(cmdline), "7z -y e \"%s\" %d\\%s", image, index, src);
uprintf("Extracting: %s (From %s)", dst, src); uprintf("Extracting: %s (From %s)", dst, src);
@ -509,12 +510,11 @@ DWORD WINAPI WimProgressCallback(DWORD dwMsgId, WPARAM wParam, LPARAM lParam, PV
switch (dwMsgId) { switch (dwMsgId) {
case WIM_MSG_PROGRESS: case WIM_MSG_PROGRESS:
uprintf(" %d%% completed", (DWORD)wParam); uprintf(" %d%% completed", (DWORD)wParam);
UpdateProgress(OP_DOS, 1.0f*(DWORD)wParam); UpdateProgress(OP_DOS, 0.98f*(DWORD)wParam);
break; break;
case WIM_MSG_PROCESS: case WIM_MSG_PROCESS:
// The amount of files processed is a bit overwhelming, and displaying it all slows us down // The amount of files processed is a bit overwhelming, and displaying it all slows us down
//#define WIM_DISPLAY_INDIVIDUAL_FILES #if 0
#if WIM_DISPLAY_INDIVIDUAL_FILES
str = wchar_to_utf8((PWSTR)wParam); str = wchar_to_utf8((PWSTR)wParam);
uprintf("Applying: '%s'", str); uprintf("Applying: '%s'", str);
PrintStatus(0, MSG_000, str); // MSG_000 is "%s" PrintStatus(0, MSG_000, str); // MSG_000 is "%s"
@ -595,7 +595,7 @@ static DWORD WINAPI WimApplyImageThread(LPVOID param)
goto out; goto out;
} }
uprintf("Applying image..."); uprintf("Applying Windows image...");
if (!pfWIMApplyImage(hImage, wdst, 0)) { if (!pfWIMApplyImage(hImage, wdst, 0)) {
uprintf(" Could not apply image: %s", WindowsErrorString()); uprintf(" Could not apply image: %s", WindowsErrorString());
goto out; goto out;
@ -618,11 +618,11 @@ out:
BOOL WimApplyImage(const char* image, int index, const char* dst) BOOL WimApplyImage(const char* image, int index, const char* dst)
{ {
HANDLE handle;
DWORD dw = 0;
_image = image; _image = image;
_index = index; _index = index;
_dst = dst; _dst = dst;
HANDLE handle;
DWORD dw = 0;
handle = CreateThread(NULL, 0, WimApplyImageThread, NULL, 0, NULL); handle = CreateThread(NULL, 0, WimApplyImageThread, NULL, 0, NULL);
if (handle == NULL) { if (handle == NULL) {