mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[misc] cleanup and refactoring + fix WIM 7z minor issue
* remove hardcoded path from WimExtractFile_7z * move some drive related functions to drive.c * cleanup
This commit is contained in:
parent
8ff8b41273
commit
c8acf1b84a
8 changed files with 209 additions and 202 deletions
|
@ -1,3 +1,7 @@
|
||||||
|
o Version 1.3.2 BETA (2012.01.20)
|
||||||
|
Re-Fix support for newer ArchLinux ISOs, that was removed in 1.3.1
|
||||||
|
Add support for UEFI boot, as well as GPT - This means Rufus can now produce UEFI
|
||||||
|
bootable UFDs from EFI compatible ISOs (Windows 7 x64, Windows 8, ArchLinux...)
|
||||||
o Version 1.3.1 (2013.01.09)
|
o Version 1.3.1 (2013.01.09)
|
||||||
Fix Windows XP ISO support, that was broken in 1.3.0
|
Fix Windows XP ISO support, that was broken in 1.3.0
|
||||||
Drop support for newer ArchLinux ISOs - this will be fixed in 1.3.2
|
Drop support for newer ArchLinux ISOs - this will be fixed in 1.3.2
|
||||||
|
|
163
src/drive.c
163
src/drive.c
|
@ -29,6 +29,7 @@
|
||||||
#include "msapi_utf8.h"
|
#include "msapi_utf8.h"
|
||||||
#include "rufus.h"
|
#include "rufus.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
#include "sys_types.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Globals
|
* Globals
|
||||||
|
@ -199,3 +200,165 @@ BOOL UnmountDrive(HANDLE hDrive)
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* MinGW is unhappy about accessing partitions beside the first unless we redef */
|
||||||
|
typedef struct _DRIVE_LAYOUT_INFORMATION_EX4 {
|
||||||
|
DWORD PartitionStyle;
|
||||||
|
DWORD PartitionCount;
|
||||||
|
union {
|
||||||
|
DRIVE_LAYOUT_INFORMATION_MBR Mbr;
|
||||||
|
DRIVE_LAYOUT_INFORMATION_GPT Gpt;
|
||||||
|
} Type;
|
||||||
|
PARTITION_INFORMATION_EX PartitionEntry[4];
|
||||||
|
} DRIVE_LAYOUT_INFORMATION_EX4,*PDRIVE_LAYOUT_INFORMATION_EX4;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a partition table
|
||||||
|
*/
|
||||||
|
// See http://technet.microsoft.com/en-us/library/cc739412.aspx for some background info
|
||||||
|
#if !defined(PARTITION_BASIC_DATA_GUID)
|
||||||
|
const GUID PARTITION_BASIC_DATA_GUID = { 0xebd0a0a2, 0xb9e5, 0x4433, {0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7} };
|
||||||
|
#endif
|
||||||
|
BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system)
|
||||||
|
{
|
||||||
|
const char* PartitionTypeName[2] = { "MBR", "GPT" };
|
||||||
|
CREATE_DISK CreateDisk = {PARTITION_STYLE_RAW, {{0}}};
|
||||||
|
DRIVE_LAYOUT_INFORMATION_EX4 DriveLayoutEx = {0};
|
||||||
|
BOOL r;
|
||||||
|
DWORD size;
|
||||||
|
LONGLONG size_in_sectors;
|
||||||
|
|
||||||
|
PrintStatus(0, TRUE, "Partitioning (%s)...", PartitionTypeName[partition_style]);
|
||||||
|
|
||||||
|
if ((partition_style == PARTITION_STYLE_GPT) || (!IsChecked(IDC_EXTRA_PARTITION))) {
|
||||||
|
// Go with the MS 1 MB wastage at the beginning...
|
||||||
|
DriveLayoutEx.PartitionEntry[0].StartingOffset.QuadPart = 1024*1024;
|
||||||
|
} else {
|
||||||
|
// Align on Cylinder
|
||||||
|
DriveLayoutEx.PartitionEntry[0].StartingOffset.QuadPart =
|
||||||
|
SelectedDrive.Geometry.BytesPerSector * SelectedDrive.Geometry.SectorsPerTrack;
|
||||||
|
}
|
||||||
|
size_in_sectors = (SelectedDrive.DiskSize - DriveLayoutEx.PartitionEntry[0].StartingOffset.QuadPart) / SelectedDrive.Geometry.BytesPerSector;
|
||||||
|
|
||||||
|
switch (partition_style) {
|
||||||
|
case PARTITION_STYLE_MBR:
|
||||||
|
CreateDisk.PartitionStyle = PARTITION_STYLE_MBR;
|
||||||
|
CreateDisk.Mbr.Signature = GetTickCount();
|
||||||
|
|
||||||
|
DriveLayoutEx.PartitionStyle = PARTITION_STYLE_MBR;
|
||||||
|
DriveLayoutEx.PartitionCount = 4; // Must be multiple of 4 for MBR
|
||||||
|
DriveLayoutEx.Type.Mbr.Signature = CreateDisk.Mbr.Signature;
|
||||||
|
DriveLayoutEx.PartitionEntry[0].PartitionStyle = PARTITION_STYLE_MBR;
|
||||||
|
// TODO: CHS fixup (32 sectors/track) through a cheat mode, if requested
|
||||||
|
// NB: disk geometry is computed by BIOS & co. by finding a match between LBA and CHS value of first partition
|
||||||
|
// ms-sys's write_partition_number_of_heads() and write_partition_start_sector_number() can be used if needed
|
||||||
|
|
||||||
|
// Align on sector boundary if the extra part option is checked
|
||||||
|
if (IsChecked(IDC_EXTRA_PARTITION)) {
|
||||||
|
size_in_sectors = ((size_in_sectors / SelectedDrive.Geometry.SectorsPerTrack)-1) * SelectedDrive.Geometry.SectorsPerTrack;
|
||||||
|
if (size_in_sectors <= 0)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PARTITION_STYLE_GPT:
|
||||||
|
CreateDisk.PartitionStyle = PARTITION_STYLE_GPT;
|
||||||
|
IGNORE_RETVAL(CoCreateGuid(&CreateDisk.Gpt.DiskId));
|
||||||
|
CreateDisk.Gpt.MaxPartitionCount = MAX_GPT_PARTITIONS;
|
||||||
|
|
||||||
|
DriveLayoutEx.PartitionStyle = PARTITION_STYLE_GPT;
|
||||||
|
DriveLayoutEx.PartitionCount = 1;
|
||||||
|
// At the very least, a GPT disk has atv least 34 reserved (512 bytes) blocks at the beginning
|
||||||
|
// and 33 at the end.
|
||||||
|
DriveLayoutEx.Type.Gpt.StartingUsableOffset.QuadPart = 34*512;
|
||||||
|
DriveLayoutEx.Type.Gpt.UsableLength.QuadPart = SelectedDrive.DiskSize - (34+33)*512;
|
||||||
|
DriveLayoutEx.Type.Gpt.MaxPartitionCount = MAX_GPT_PARTITIONS;
|
||||||
|
DriveLayoutEx.Type.Gpt.DiskId = CreateDisk.Gpt.DiskId;
|
||||||
|
DriveLayoutEx.PartitionEntry[0].PartitionStyle = PARTITION_STYLE_GPT;
|
||||||
|
|
||||||
|
size_in_sectors -= 33; // Need 33 sectors at the end for secondary GPT
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DriveLayoutEx.PartitionEntry[0].PartitionLength.QuadPart = size_in_sectors * SelectedDrive.Geometry.BytesPerSector;
|
||||||
|
DriveLayoutEx.PartitionEntry[0].PartitionNumber = 1;
|
||||||
|
DriveLayoutEx.PartitionEntry[0].RewritePartition = TRUE;
|
||||||
|
|
||||||
|
switch (partition_style) {
|
||||||
|
case PARTITION_STYLE_MBR:
|
||||||
|
DriveLayoutEx.PartitionEntry[0].Mbr.HiddenSectors = SelectedDrive.Geometry.SectorsPerTrack;
|
||||||
|
switch (file_system) {
|
||||||
|
case FS_FAT16:
|
||||||
|
DriveLayoutEx.PartitionEntry[0].Mbr.PartitionType = 0x0e; // FAT16 LBA
|
||||||
|
break;
|
||||||
|
case FS_NTFS:
|
||||||
|
case FS_EXFAT:
|
||||||
|
DriveLayoutEx.PartitionEntry[0].Mbr.PartitionType = 0x07; // NTFS
|
||||||
|
break;
|
||||||
|
case FS_FAT32:
|
||||||
|
DriveLayoutEx.PartitionEntry[0].Mbr.PartitionType = 0x0c; // FAT32 LBA
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
uprintf("Unsupported file system\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
// Create an extra partition on request - can improve BIOS detection as HDD for older BIOSes
|
||||||
|
if (IsChecked(IDC_EXTRA_PARTITION)) {
|
||||||
|
DriveLayoutEx.PartitionEntry[1].PartitionStyle = PARTITION_STYLE_MBR;
|
||||||
|
// Should end on a sector boundary
|
||||||
|
DriveLayoutEx.PartitionEntry[1].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[0].StartingOffset.QuadPart +
|
||||||
|
DriveLayoutEx.PartitionEntry[0].PartitionLength.QuadPart;
|
||||||
|
DriveLayoutEx.PartitionEntry[1].PartitionLength.QuadPart = SelectedDrive.Geometry.SectorsPerTrack*SelectedDrive.Geometry.BytesPerSector;
|
||||||
|
DriveLayoutEx.PartitionEntry[1].PartitionNumber = 2;
|
||||||
|
DriveLayoutEx.PartitionEntry[1].RewritePartition = TRUE;
|
||||||
|
DriveLayoutEx.PartitionEntry[1].Mbr.HiddenSectors = SelectedDrive.Geometry.SectorsPerTrack*SelectedDrive.Geometry.BytesPerSector;
|
||||||
|
DriveLayoutEx.PartitionEntry[1].Mbr.PartitionType = DriveLayoutEx.PartitionEntry[0].Mbr.PartitionType + 0x10; // Hidden whatever
|
||||||
|
}
|
||||||
|
// For the remaining partitions, PartitionStyle & PartitionType have already
|
||||||
|
// been zeroed => already set to MBR/unused
|
||||||
|
break;
|
||||||
|
case PARTITION_STYLE_GPT:
|
||||||
|
DriveLayoutEx.PartitionEntry[0].Gpt.PartitionType = PARTITION_BASIC_DATA_GUID;
|
||||||
|
wcscpy(DriveLayoutEx.PartitionEntry[0].Gpt.Name, L"Microsoft Basic Data");
|
||||||
|
IGNORE_RETVAL(CoCreateGuid(&DriveLayoutEx.PartitionEntry[0].Gpt.PartitionId));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If you don't call IOCTL_DISK_CREATE_DISK, the next call will fail
|
||||||
|
size = sizeof(CreateDisk);
|
||||||
|
r = DeviceIoControl(hDrive, IOCTL_DISK_CREATE_DISK,
|
||||||
|
(BYTE*)&CreateDisk, size, NULL, 0, &size, NULL );
|
||||||
|
if (!r) {
|
||||||
|
uprintf("IOCTL_DISK_CREATE_DISK failed: %s\n", WindowsErrorString());
|
||||||
|
safe_closehandle(hDrive);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = sizeof(DriveLayoutEx) - ((partition_style == PARTITION_STYLE_GPT)?(3*sizeof(PARTITION_INFORMATION_EX)):0);
|
||||||
|
r = DeviceIoControl(hDrive, IOCTL_DISK_SET_DRIVE_LAYOUT_EX,
|
||||||
|
(BYTE*)&DriveLayoutEx, size, NULL, 0, &size, NULL );
|
||||||
|
if (!r) {
|
||||||
|
uprintf("IOCTL_DISK_SET_DRIVE_LAYOUT_EX failed: %s\n", WindowsErrorString());
|
||||||
|
safe_closehandle(hDrive);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert a partition type to its human readable form using
|
||||||
|
* (slightly modified) entries from GNU fdisk
|
||||||
|
*/
|
||||||
|
const char* GetPartitionType(BYTE Type)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i=0; i<ARRAYSIZE(msdos_systypes); i++) {
|
||||||
|
if (msdos_systypes[i].type == Type)
|
||||||
|
return msdos_systypes[i].name;
|
||||||
|
}
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
|
@ -1221,7 +1221,7 @@ DWORD WINAPI FormatThread(LPVOID param)
|
||||||
}
|
}
|
||||||
UpdateProgress(OP_ZERO_MBR, -1.0f);
|
UpdateProgress(OP_ZERO_MBR, -1.0f);
|
||||||
|
|
||||||
if (!CreatePartition(hPhysicalDrive)) {
|
if (!CreatePartition(hPhysicalDrive, pt, fs)) {
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_PARTITION_FAILURE;
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_PARTITION_FAILURE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
203
src/rufus.c
203
src/rufus.c
|
@ -37,7 +37,6 @@
|
||||||
#include "msapi_utf8.h"
|
#include "msapi_utf8.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "rufus.h"
|
#include "rufus.h"
|
||||||
#include "sys_types.h"
|
|
||||||
#include "registry.h"
|
#include "registry.h"
|
||||||
|
|
||||||
/* Redefinitions for the WDK */
|
/* Redefinitions for the WDK */
|
||||||
|
@ -86,8 +85,8 @@ static const char* FileSystemLabel[FS_MAX] = { "FAT", "FAT32", "NTFS", "exFAT" }
|
||||||
static const char* ClusterSizeLabel[] = { "512 bytes", "1024 bytes","2048 bytes","4096 bytes","8192 bytes",
|
static const char* ClusterSizeLabel[] = { "512 bytes", "1024 bytes","2048 bytes","4096 bytes","8192 bytes",
|
||||||
"16 kilobytes", "32 kilobytes", "64 kilobytes", "128 kilobytes", "256 kilobytes", "512 kilobytes",
|
"16 kilobytes", "32 kilobytes", "64 kilobytes", "128 kilobytes", "256 kilobytes", "512 kilobytes",
|
||||||
"1024 kilobytes","2048 kilobytes","4096 kilobytes","8192 kilobytes","16 megabytes","32 megabytes" };
|
"1024 kilobytes","2048 kilobytes","4096 kilobytes","8192 kilobytes","16 megabytes","32 megabytes" };
|
||||||
static const char* BiosTypeName[BT_MAX] = { "BIOS", "UEFI" };
|
static const char* BiosTypeLabel[BT_MAX] = { "BIOS", "UEFI" };
|
||||||
static const char* PartitionTypeName[2] = { "MBR", "GPT" };
|
static const char* PartitionTypeLabel[2] = { "MBR", "GPT" };
|
||||||
static BOOL existing_key = FALSE; // For LGP set/restore
|
static BOOL existing_key = FALSE; // For LGP set/restore
|
||||||
static BOOL iso_size_check = TRUE;
|
static BOOL iso_size_check = TRUE;
|
||||||
static BOOL log_displayed = FALSE;
|
static BOOL log_displayed = FALSE;
|
||||||
|
@ -132,20 +131,6 @@ static int nb_slots[OP_MAX];
|
||||||
static float slot_end[OP_MAX+1]; // shifted +1 so that we can substract 1 to OP indexes
|
static float slot_end[OP_MAX+1]; // shifted +1 so that we can substract 1 to OP indexes
|
||||||
static float previous_end;
|
static float previous_end;
|
||||||
|
|
||||||
/*
|
|
||||||
* Convert a partition type to its human readable form using
|
|
||||||
* (slightly modified) entries from GNU fdisk
|
|
||||||
*/
|
|
||||||
static const char* GetPartitionType(BYTE Type)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i=0; i<ARRAYSIZE(msdos_systypes); i++) {
|
|
||||||
if (msdos_systypes[i].type == Type)
|
|
||||||
return msdos_systypes[i].name;
|
|
||||||
}
|
|
||||||
return "Unknown";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#define KB 1024LL
|
#define KB 1024LL
|
||||||
#define MB 1048576LL
|
#define MB 1048576LL
|
||||||
|
@ -329,29 +314,10 @@ static BOOL SetClusterSizes(int FSType)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert a file size to human readable
|
|
||||||
static __inline char* size_to_hr(LARGE_INTEGER size)
|
|
||||||
{
|
|
||||||
int suffix = 0;
|
|
||||||
static char str_size[24];
|
|
||||||
const char* sizes[] = { "", "KB", "MB", "GB", "TB" };
|
|
||||||
double hr_size = (double)size.QuadPart;
|
|
||||||
while ((suffix < ARRAYSIZE(sizes)) && (hr_size >= 1024.0)) {
|
|
||||||
hr_size /= 1024.0;
|
|
||||||
suffix++;
|
|
||||||
}
|
|
||||||
if (suffix == 0) {
|
|
||||||
safe_sprintf(str_size, sizeof(str_size), "%d bytes", (int)hr_size);
|
|
||||||
} else {
|
|
||||||
safe_sprintf(str_size, sizeof(str_size), "%0.1f %s", hr_size, sizes[suffix]);
|
|
||||||
}
|
|
||||||
return str_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fill the drive properties (size, FS, etc)
|
* Fill the drive properties (size, FS, etc)
|
||||||
*/
|
*/
|
||||||
static BOOL GetDriveInfo(DWORD DeviceNumber)
|
static BOOL GetDriveInfo(int ComboIndex)
|
||||||
{
|
{
|
||||||
BOOL r;
|
BOOL r;
|
||||||
HANDLE hDrive;
|
HANDLE hDrive;
|
||||||
|
@ -365,7 +331,7 @@ static BOOL GetDriveInfo(DWORD DeviceNumber)
|
||||||
DWORD i, nb_partitions = 0;
|
DWORD i, nb_partitions = 0;
|
||||||
|
|
||||||
memset(&SelectedDrive, 0, sizeof(SelectedDrive));
|
memset(&SelectedDrive, 0, sizeof(SelectedDrive));
|
||||||
SelectedDrive.DeviceNumber = DeviceNumber;
|
SelectedDrive.DeviceNumber = (DWORD)ComboBox_GetItemData(hDeviceList, ComboIndex);
|
||||||
|
|
||||||
hDrive = GetDriveHandle(SelectedDrive.DeviceNumber, DrivePath, FALSE, FALSE);
|
hDrive = GetDriveHandle(SelectedDrive.DeviceNumber, DrivePath, FALSE, FALSE);
|
||||||
if (hDrive == INVALID_HANDLE_VALUE)
|
if (hDrive == INVALID_HANDLE_VALUE)
|
||||||
|
@ -404,7 +370,7 @@ static BOOL GetDriveInfo(DWORD DeviceNumber)
|
||||||
uprintf("Partition %d:\n", DriveLayout->PartitionEntry[i].PartitionNumber);
|
uprintf("Partition %d:\n", DriveLayout->PartitionEntry[i].PartitionNumber);
|
||||||
part_type = DriveLayout->PartitionEntry[i].Mbr.PartitionType;
|
part_type = DriveLayout->PartitionEntry[i].Mbr.PartitionType;
|
||||||
uprintf(" Type: %s (0x%02x)\r\n Size: %s (%lld bytes)\r\n Start Sector: %d, Boot: %s, Recognized: %s\n",
|
uprintf(" Type: %s (0x%02x)\r\n Size: %s (%lld bytes)\r\n Start Sector: %d, Boot: %s, Recognized: %s\n",
|
||||||
GetPartitionType(part_type), part_type, size_to_hr(DriveLayout->PartitionEntry[i].PartitionLength),
|
GetPartitionType(part_type), part_type, SizeToHumanReadable(DriveLayout->PartitionEntry[i].PartitionLength),
|
||||||
DriveLayout->PartitionEntry[i].PartitionLength, DriveLayout->PartitionEntry[i].Mbr.HiddenSectors,
|
DriveLayout->PartitionEntry[i].PartitionLength, DriveLayout->PartitionEntry[i].Mbr.HiddenSectors,
|
||||||
DriveLayout->PartitionEntry[i].Mbr.BootIndicator?"Yes":"No",
|
DriveLayout->PartitionEntry[i].Mbr.BootIndicator?"Yes":"No",
|
||||||
DriveLayout->PartitionEntry[i].Mbr.RecognizedPartition?"Yes":"No");
|
DriveLayout->PartitionEntry[i].Mbr.RecognizedPartition?"Yes":"No");
|
||||||
|
@ -426,7 +392,7 @@ static BOOL GetDriveInfo(DWORD DeviceNumber)
|
||||||
uprintf("Partition %d:\r\n Type: %s\r\n Name: '%s'\n", DriveLayout->PartitionEntry[i].PartitionNumber,
|
uprintf("Partition %d:\r\n Type: %s\r\n Name: '%s'\n", DriveLayout->PartitionEntry[i].PartitionNumber,
|
||||||
GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionType), tmp);
|
GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionType), tmp);
|
||||||
uprintf(" ID: %s\r\n Size: %s (%lld bytes)\r\n Start Sector: %lld, Attributes: 0x%016llX\n",
|
uprintf(" ID: %s\r\n Size: %s (%lld bytes)\r\n Start Sector: %lld, Attributes: 0x%016llX\n",
|
||||||
GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionId), size_to_hr(DriveLayout->PartitionEntry[i].PartitionLength),
|
GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionId), SizeToHumanReadable(DriveLayout->PartitionEntry[i].PartitionLength),
|
||||||
DriveLayout->PartitionEntry[i].PartitionLength, DriveLayout->PartitionEntry[i].StartingOffset.QuadPart / DiskGeometry->Geometry.BytesPerSector,
|
DriveLayout->PartitionEntry[i].PartitionLength, DriveLayout->PartitionEntry[i].StartingOffset.QuadPart / DiskGeometry->Geometry.BytesPerSector,
|
||||||
DriveLayout->PartitionEntry[i].Gpt.Attributes);
|
DriveLayout->PartitionEntry[i].Gpt.Attributes);
|
||||||
}
|
}
|
||||||
|
@ -566,7 +532,7 @@ static BOOL PopulateProperties(int ComboIndex)
|
||||||
if (ComboIndex < 0)
|
if (ComboIndex < 0)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
if (!GetDriveInfo((DWORD)ComboBox_GetItemData(hDeviceList, ComboIndex))) // This also populates FS
|
if (!GetDriveInfo(ComboIndex)) // This also populates FS
|
||||||
return FALSE;
|
return FALSE;
|
||||||
SetFSFromISO();
|
SetFSFromISO();
|
||||||
fs = (int)ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem));
|
fs = (int)ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem));
|
||||||
|
@ -577,14 +543,14 @@ static BOOL PopulateProperties(int ComboIndex)
|
||||||
HumanReadableSize /= 1024.0;
|
HumanReadableSize /= 1024.0;
|
||||||
if (HumanReadableSize < 512.0) {
|
if (HumanReadableSize < 512.0) {
|
||||||
for (j=0; j<3; j++) {
|
for (j=0; j<3; j++) {
|
||||||
// Populate BIOS/MBR, UEFI/MBR and UEFI/GPT targets, with an exception
|
// Populate MBR/BIOS, MBR/UEFI and GPT/UEFI targets, with an exception
|
||||||
// for XP, as it doesn't support GPT at all
|
// for XP, as it doesn't support GPT at all
|
||||||
if ((j == 2) && (nWindowsVersion <= WINDOWS_XP))
|
if ((j == 2) && (nWindowsVersion <= WINDOWS_XP))
|
||||||
continue;
|
continue;
|
||||||
bt = (j==0)?BT_BIOS:BT_UEFI;
|
bt = (j==0)?BT_BIOS:BT_UEFI;
|
||||||
pt = (j==2)?PARTITION_STYLE_GPT:PARTITION_STYLE_MBR;
|
pt = (j==2)?PARTITION_STYLE_GPT:PARTITION_STYLE_MBR;
|
||||||
safe_sprintf(capacity, sizeof(capacity), "%s/%s (1 Partition of %0.2f %s)",
|
safe_sprintf(capacity, sizeof(capacity), "%s/%s (1 Partition of %0.2f %s)",
|
||||||
PartitionTypeName[pt], BiosTypeName[bt], HumanReadableSize, suffix[i]);
|
PartitionTypeLabel[pt], BiosTypeLabel[bt], HumanReadableSize, suffix[i]);
|
||||||
IGNORE_RETVAL(ComboBox_SetItemData(hPartitionScheme, ComboBox_AddStringU(hPartitionScheme, capacity), (bt<<16)|pt));
|
IGNORE_RETVAL(ComboBox_SetItemData(hPartitionScheme, ComboBox_AddStringU(hPartitionScheme, capacity), (bt<<16)|pt));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -600,7 +566,8 @@ static BOOL PopulateProperties(int ComboIndex)
|
||||||
j = 0;
|
j = 0;
|
||||||
}
|
}
|
||||||
IGNORE_RETVAL(ComboBox_SetCurSel(hPartitionScheme, j));
|
IGNORE_RETVAL(ComboBox_SetCurSel(hPartitionScheme, j));
|
||||||
// TODO: create a tooltip for hPartitionScheme
|
CreateTooltip(hPartitionScheme, "When using an EFI bootable image, and if your target system is UEFI based "
|
||||||
|
"(most post 2011 PCs), you should try to select an UEFI option here.", 15000);
|
||||||
CreateTooltip(hDeviceList, DriveID.Table[ComboIndex], -1);
|
CreateTooltip(hDeviceList, DriveID.Table[ComboIndex], -1);
|
||||||
|
|
||||||
// Set a proposed label according to the size (eg: "256MB", "8GB")
|
// Set a proposed label according to the size (eg: "256MB", "8GB")
|
||||||
|
@ -631,154 +598,6 @@ static BOOL PopulateProperties(int ComboIndex)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* MinGW is unhappy about accessing partitions beside the first unless we redef */
|
|
||||||
typedef struct _DRIVE_LAYOUT_INFORMATION_EX4 {
|
|
||||||
DWORD PartitionStyle;
|
|
||||||
DWORD PartitionCount;
|
|
||||||
union {
|
|
||||||
DRIVE_LAYOUT_INFORMATION_MBR Mbr;
|
|
||||||
DRIVE_LAYOUT_INFORMATION_GPT Gpt;
|
|
||||||
} Type;
|
|
||||||
PARTITION_INFORMATION_EX PartitionEntry[4];
|
|
||||||
} DRIVE_LAYOUT_INFORMATION_EX4,*PDRIVE_LAYOUT_INFORMATION_EX4;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create a partition table
|
|
||||||
*/
|
|
||||||
// See http://technet.microsoft.com/en-us/library/cc739412.aspx for some background info
|
|
||||||
#if !defined(PARTITION_BASIC_DATA_GUID)
|
|
||||||
const GUID PARTITION_BASIC_DATA_GUID = { 0xebd0a0a2, 0xb9e5, 0x4433, {0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7} };
|
|
||||||
#endif
|
|
||||||
BOOL CreatePartition(HANDLE hDrive)
|
|
||||||
{
|
|
||||||
CREATE_DISK CreateDisk = {PARTITION_STYLE_RAW, {{0}}};
|
|
||||||
DRIVE_LAYOUT_INFORMATION_EX4 DriveLayoutEx = {0};
|
|
||||||
BOOL r;
|
|
||||||
DWORD size;
|
|
||||||
LONGLONG size_in_sectors;
|
|
||||||
int pt = GETPARTTYPE((int)ComboBox_GetItemData(hPartitionScheme, ComboBox_GetCurSel(hPartitionScheme)));
|
|
||||||
|
|
||||||
PrintStatus(0, TRUE, "Partitioning (%s)...", PartitionTypeName[pt]);
|
|
||||||
|
|
||||||
if ((pt == PARTITION_STYLE_GPT) || (!IsChecked(IDC_EXTRA_PARTITION))) {
|
|
||||||
// Go with the MS 1 MB wastage at the beginning...
|
|
||||||
DriveLayoutEx.PartitionEntry[0].StartingOffset.QuadPart = 1024*1024;
|
|
||||||
} else {
|
|
||||||
// Align on Cylinder
|
|
||||||
DriveLayoutEx.PartitionEntry[0].StartingOffset.QuadPart =
|
|
||||||
SelectedDrive.Geometry.BytesPerSector * SelectedDrive.Geometry.SectorsPerTrack;
|
|
||||||
}
|
|
||||||
size_in_sectors = (SelectedDrive.DiskSize - DriveLayoutEx.PartitionEntry[0].StartingOffset.QuadPart) / SelectedDrive.Geometry.BytesPerSector;
|
|
||||||
|
|
||||||
switch (pt) {
|
|
||||||
case PARTITION_STYLE_MBR:
|
|
||||||
CreateDisk.PartitionStyle = PARTITION_STYLE_MBR;
|
|
||||||
CreateDisk.Mbr.Signature = GetTickCount();
|
|
||||||
|
|
||||||
DriveLayoutEx.PartitionStyle = PARTITION_STYLE_MBR;
|
|
||||||
DriveLayoutEx.PartitionCount = 4; // Must be multiple of 4 for MBR
|
|
||||||
DriveLayoutEx.Type.Mbr.Signature = CreateDisk.Mbr.Signature;
|
|
||||||
DriveLayoutEx.PartitionEntry[0].PartitionStyle = PARTITION_STYLE_MBR;
|
|
||||||
// TODO: CHS fixup (32 sectors/track) through a cheat mode, if requested
|
|
||||||
// NB: disk geometry is computed by BIOS & co. by finding a match between LBA and CHS value of first partition
|
|
||||||
// ms-sys's write_partition_number_of_heads() and write_partition_start_sector_number() can be used if needed
|
|
||||||
|
|
||||||
// Align on sector boundary if the extra part option is checked
|
|
||||||
if (IsChecked(IDC_EXTRA_PARTITION)) {
|
|
||||||
size_in_sectors = ((size_in_sectors / SelectedDrive.Geometry.SectorsPerTrack)-1) * SelectedDrive.Geometry.SectorsPerTrack;
|
|
||||||
if (size_in_sectors <= 0)
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PARTITION_STYLE_GPT:
|
|
||||||
CreateDisk.PartitionStyle = PARTITION_STYLE_GPT;
|
|
||||||
IGNORE_RETVAL(CoCreateGuid(&CreateDisk.Gpt.DiskId));
|
|
||||||
CreateDisk.Gpt.MaxPartitionCount = MAX_GPT_PARTITIONS;
|
|
||||||
|
|
||||||
DriveLayoutEx.PartitionStyle = PARTITION_STYLE_GPT;
|
|
||||||
DriveLayoutEx.PartitionCount = 1;
|
|
||||||
// At the very least, a GPT disk has atv least 34 reserved (512 bytes) blocks at the beginning
|
|
||||||
// and 33 at the end.
|
|
||||||
DriveLayoutEx.Type.Gpt.StartingUsableOffset.QuadPart = 34*512;
|
|
||||||
DriveLayoutEx.Type.Gpt.UsableLength.QuadPart = SelectedDrive.DiskSize - (34+33)*512;
|
|
||||||
DriveLayoutEx.Type.Gpt.MaxPartitionCount = MAX_GPT_PARTITIONS;
|
|
||||||
DriveLayoutEx.Type.Gpt.DiskId = CreateDisk.Gpt.DiskId;
|
|
||||||
DriveLayoutEx.PartitionEntry[0].PartitionStyle = PARTITION_STYLE_GPT;
|
|
||||||
|
|
||||||
size_in_sectors -= 33; // Need 33 sectors at the end for secondary GPT
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
DriveLayoutEx.PartitionEntry[0].PartitionLength.QuadPart = size_in_sectors * SelectedDrive.Geometry.BytesPerSector;
|
|
||||||
DriveLayoutEx.PartitionEntry[0].PartitionNumber = 1;
|
|
||||||
DriveLayoutEx.PartitionEntry[0].RewritePartition = TRUE;
|
|
||||||
|
|
||||||
switch (pt) {
|
|
||||||
case PARTITION_STYLE_MBR:
|
|
||||||
DriveLayoutEx.PartitionEntry[0].Mbr.HiddenSectors = SelectedDrive.Geometry.SectorsPerTrack;
|
|
||||||
switch (ComboBox_GetItemData(hFileSystem, ComboBox_GetCurSel(hFileSystem))) {
|
|
||||||
case FS_FAT16:
|
|
||||||
DriveLayoutEx.PartitionEntry[0].Mbr.PartitionType = 0x0e; // FAT16 LBA
|
|
||||||
break;
|
|
||||||
case FS_NTFS:
|
|
||||||
case FS_EXFAT:
|
|
||||||
DriveLayoutEx.PartitionEntry[0].Mbr.PartitionType = 0x07; // NTFS
|
|
||||||
break;
|
|
||||||
case FS_FAT32:
|
|
||||||
DriveLayoutEx.PartitionEntry[0].Mbr.PartitionType = 0x0c; // FAT32 LBA
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
uprintf("Unsupported file system\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
// Create an extra partition on request - can improve BIOS detection as HDD for older BIOSes
|
|
||||||
if (IsChecked(IDC_EXTRA_PARTITION)) {
|
|
||||||
DriveLayoutEx.PartitionEntry[1].PartitionStyle = PARTITION_STYLE_MBR;
|
|
||||||
// Should end on a sector boundary
|
|
||||||
DriveLayoutEx.PartitionEntry[1].StartingOffset.QuadPart = DriveLayoutEx.PartitionEntry[0].StartingOffset.QuadPart +
|
|
||||||
DriveLayoutEx.PartitionEntry[0].PartitionLength.QuadPart;
|
|
||||||
DriveLayoutEx.PartitionEntry[1].PartitionLength.QuadPart = SelectedDrive.Geometry.SectorsPerTrack*SelectedDrive.Geometry.BytesPerSector;
|
|
||||||
DriveLayoutEx.PartitionEntry[1].PartitionNumber = 2;
|
|
||||||
DriveLayoutEx.PartitionEntry[1].RewritePartition = TRUE;
|
|
||||||
DriveLayoutEx.PartitionEntry[1].Mbr.HiddenSectors = SelectedDrive.Geometry.SectorsPerTrack*SelectedDrive.Geometry.BytesPerSector;
|
|
||||||
DriveLayoutEx.PartitionEntry[1].Mbr.PartitionType = DriveLayoutEx.PartitionEntry[0].Mbr.PartitionType + 0x10; // Hidden whatever
|
|
||||||
}
|
|
||||||
// For the remaining partitions, PartitionStyle & PartitionType have already
|
|
||||||
// been zeroed => already set to MBR/unused
|
|
||||||
break;
|
|
||||||
case PARTITION_STYLE_GPT:
|
|
||||||
DriveLayoutEx.PartitionEntry[0].Gpt.PartitionType = PARTITION_BASIC_DATA_GUID;
|
|
||||||
wcscpy(DriveLayoutEx.PartitionEntry[0].Gpt.Name, L"Microsoft Basic Data");
|
|
||||||
IGNORE_RETVAL(CoCreateGuid(&DriveLayoutEx.PartitionEntry[0].Gpt.PartitionId));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If you don't call IOCTL_DISK_CREATE_DISK, the next call will fail
|
|
||||||
size = sizeof(CreateDisk);
|
|
||||||
r = DeviceIoControl(hDrive, IOCTL_DISK_CREATE_DISK,
|
|
||||||
(BYTE*)&CreateDisk, size, NULL, 0, &size, NULL );
|
|
||||||
if (!r) {
|
|
||||||
uprintf("IOCTL_DISK_CREATE_DISK failed: %s\n", WindowsErrorString());
|
|
||||||
safe_closehandle(hDrive);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
size = sizeof(DriveLayoutEx) - ((pt == PARTITION_STYLE_GPT)?(3*sizeof(PARTITION_INFORMATION_EX)):0);
|
|
||||||
r = DeviceIoControl(hDrive, IOCTL_DISK_SET_DRIVE_LAYOUT_EX,
|
|
||||||
(BYTE*)&DriveLayoutEx, size, NULL, 0, &size, NULL );
|
|
||||||
if (!r) {
|
|
||||||
uprintf("IOCTL_DISK_SET_DRIVE_LAYOUT_EX failed: %s\n", WindowsErrorString());
|
|
||||||
safe_closehandle(hDrive);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Refresh the list of USB devices
|
* Refresh the list of USB devices
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -265,6 +265,7 @@ extern void PrintStatus(unsigned int duration, BOOL debug, const char *format, .
|
||||||
extern void UpdateProgress(int op, float percent);
|
extern void UpdateProgress(int op, float percent);
|
||||||
extern const char* StrError(DWORD error_code);
|
extern const char* StrError(DWORD error_code);
|
||||||
extern char* GuidToString(const GUID* guid);
|
extern char* GuidToString(const GUID* guid);
|
||||||
|
extern char* SizeToHumanReadable(LARGE_INTEGER size);
|
||||||
extern void CenterDialog(HWND hDlg);
|
extern void CenterDialog(HWND hDlg);
|
||||||
extern void CreateStatusBar(void);
|
extern void CreateStatusBar(void);
|
||||||
extern void SetTitleBarIcon(HWND hDlg);
|
extern void SetTitleBarIcon(HWND hDlg);
|
||||||
|
@ -282,7 +283,8 @@ extern BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan);
|
||||||
extern BOOL ExtractISOFile(const char* iso, const char* iso_file, const char* dest_file);
|
extern BOOL ExtractISOFile(const char* iso, const char* iso_file, const char* dest_file);
|
||||||
extern BOOL InstallSyslinux(DWORD num, const char* drive_name);
|
extern BOOL InstallSyslinux(DWORD num, const char* drive_name);
|
||||||
DWORD WINAPI FormatThread(void* param);
|
DWORD WINAPI FormatThread(void* param);
|
||||||
extern BOOL CreatePartition(HANDLE hDrive);
|
extern BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system);
|
||||||
|
extern const char* GetPartitionType(BYTE Type);
|
||||||
extern HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BOOL bLockDrive);
|
extern HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BOOL bLockDrive);
|
||||||
extern BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label);
|
extern BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label);
|
||||||
extern BOOL UnmountDrive(HANDLE hDrive);
|
extern BOOL UnmountDrive(HANDLE hDrive);
|
||||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -30,7 +30,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
|
||||||
IDD_DIALOG DIALOGEX 12, 12, 206, 316
|
IDD_DIALOG DIALOGEX 12, 12, 206, 316
|
||||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
EXSTYLE WS_EX_APPWINDOW
|
EXSTYLE WS_EX_APPWINDOW
|
||||||
CAPTION "Rufus v1.3.2.226"
|
CAPTION "Rufus v1.3.2.227"
|
||||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||||
BEGIN
|
BEGIN
|
||||||
DEFPUSHBUTTON "Start",IDC_START,94,278,50,14
|
DEFPUSHBUTTON "Start",IDC_START,94,278,50,14
|
||||||
|
@ -274,8 +274,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,3,2,226
|
FILEVERSION 1,3,2,227
|
||||||
PRODUCTVERSION 1,3,2,226
|
PRODUCTVERSION 1,3,2,227
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -292,13 +292,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", "1.3.2.226"
|
VALUE "FileVersion", "1.3.2.227"
|
||||||
VALUE "InternalName", "Rufus"
|
VALUE "InternalName", "Rufus"
|
||||||
VALUE "LegalCopyright", "(c) 2011-2012 Pete Batard (GPL v3)"
|
VALUE "LegalCopyright", "(c) 2011-2012 Pete Batard (GPL v3)"
|
||||||
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
|
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
|
||||||
VALUE "OriginalFilename", "rufus.exe"
|
VALUE "OriginalFilename", "rufus.exe"
|
||||||
VALUE "ProductName", "Rufus"
|
VALUE "ProductName", "Rufus"
|
||||||
VALUE "ProductVersion", "1.3.2.226"
|
VALUE "ProductVersion", "1.3.2.227"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
19
src/stdio.c
19
src/stdio.c
|
@ -189,6 +189,25 @@ char* GuidToString(const GUID* guid)
|
||||||
return guid_string;
|
return guid_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert a file size to human readable
|
||||||
|
char* SizeToHumanReadable(LARGE_INTEGER size)
|
||||||
|
{
|
||||||
|
int suffix = 0;
|
||||||
|
static char str_size[24];
|
||||||
|
const char* sizes[] = { "", "KB", "MB", "GB", "TB" };
|
||||||
|
double hr_size = (double)size.QuadPart;
|
||||||
|
while ((suffix < ARRAYSIZE(sizes)) && (hr_size >= 1024.0)) {
|
||||||
|
hr_size /= 1024.0;
|
||||||
|
suffix++;
|
||||||
|
}
|
||||||
|
if (suffix == 0) {
|
||||||
|
safe_sprintf(str_size, sizeof(str_size), "%d bytes", (int)hr_size);
|
||||||
|
} else {
|
||||||
|
safe_sprintf(str_size, sizeof(str_size), "%0.1f %s", hr_size, sizes[suffix]);
|
||||||
|
}
|
||||||
|
return str_size;
|
||||||
|
}
|
||||||
|
|
||||||
const char* StrError(DWORD error_code)
|
const char* StrError(DWORD error_code)
|
||||||
{
|
{
|
||||||
if ( (!IS_ERROR(error_code)) || (SCODE_CODE(error_code) == ERROR_SUCCESS)) {
|
if ( (!IS_ERROR(error_code)) || (SCODE_CODE(error_code) == ERROR_SUCCESS)) {
|
||||||
|
|
|
@ -131,7 +131,7 @@ static BOOL WimExtractFile_API(const char* image, int index, const char* src, co
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
uprintf("Extracting: %s (From \\%s)\n", dst, src);
|
uprintf("Extracting: %s (From %s)\n", dst, src);
|
||||||
if (!pfWIMExtractImagePath(hImage, wsrc, wdst, 0)) {
|
if (!pfWIMExtractImagePath(hImage, wsrc, wdst, 0)) {
|
||||||
uprintf(" Could not extract file: %s\n", WindowsErrorString());
|
uprintf(" Could not extract file: %s\n", WindowsErrorString());
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -181,8 +181,8 @@ static BOOL WimExtractFile_7z(const char* image, int index, const char* src, con
|
||||||
tmpdst[i] = 0;
|
tmpdst[i] = 0;
|
||||||
|
|
||||||
si.cb = sizeof(si);
|
si.cb = sizeof(si);
|
||||||
safe_sprintf(cmdline, sizeof(cmdline), "7z -y e \"%s\" %d\\Windows\\Boot\\EFI\\bootmgfw.efi", image, index);
|
safe_sprintf(cmdline, sizeof(cmdline), "7z -y e \"%s\" %d\\%s", image, index, src);
|
||||||
uprintf("Extracting: %s (From \\%s)\n", dst, src);
|
uprintf("Extracting: %s (From %s)\n", dst, src);
|
||||||
if (!CreateProcessU(sevenzip_path, cmdline, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, tmpdst, &si, &pi)) {
|
if (!CreateProcessU(sevenzip_path, cmdline, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, tmpdst, &si, &pi)) {
|
||||||
uprintf(" Could not launch 7z.exe: %s\n", WindowsErrorString());
|
uprintf(" Could not launch 7z.exe: %s\n", WindowsErrorString());
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
Loading…
Reference in a new issue