Merge branch 'master' into localization

This commit is contained in:
Pete Batard 2013-06-28 02:20:56 +01:00
commit 9426be0bc1
11 changed files with 305 additions and 134 deletions

View File

@ -2,9 +2,10 @@ SUBDIRS = src
TARGET = rufus
# This step produces the UPX compressed and signed releases that are made available for public download
# NB: UPX v3.09 or later is needed for LZMA compression (http://upx.sourceforge.net/)
release: all
@mv src/$(TARGET)$(EXEEXT) .
@$(STRIP) $(TARGET)$(EXEEXT)
@upx $(TARGET)$(EXEEXT)
@upx --lzma $(TARGET)$(EXEEXT)
@mv $(TARGET)$(EXEEXT) $(TARGET)_v$(VERSION)$(EXEEXT)
@cmd.exe /k _sign.cmd $(TARGET)_v$(VERSION)$(EXEEXT)

View File

@ -443,10 +443,11 @@ uninstall-am:
# This step produces the UPX compressed and signed releases that are made available for public download
# NB: UPX v3.09 or later is needed for LZMA compression (http://upx.sourceforge.net/)
release: all
@mv src/$(TARGET)$(EXEEXT) .
@$(STRIP) $(TARGET)$(EXEEXT)
@upx $(TARGET)$(EXEEXT)
@upx --lzma $(TARGET)$(EXEEXT)
@mv $(TARGET)$(EXEEXT) $(TARGET)_v$(VERSION)$(EXEEXT)
@cmd.exe /k _sign.cmd $(TARGET)_v$(VERSION)$(EXEEXT)

View File

@ -19,7 +19,7 @@ TAGVER=`echo $VER`
# of a .amend file in the current directory will do
if [ -f ./.amend ]; then
TAGVER=`expr $TAGVER - 1`
git tag -d "#$TAGVER"
git tag -d "b$TAGVER"
rm ./.amend;
fi
echo "setting nano to $TAGVER"

View File

@ -56,6 +56,7 @@ extern BOOL enable_fixed_disks;
*/
static HANDLE GetHandle(char* Path, BOOL bWriteAccess, BOOL bLockDrive)
{
int i;
DWORD size;
HANDLE hDrive = INVALID_HANDLE_VALUE;
@ -72,10 +73,17 @@ static HANDLE GetHandle(char* Path, BOOL bWriteAccess, BOOL bLockDrive)
uprintf("Caution: Opened drive %s for write access\n", Path);
}
if ((bLockDrive) && (!DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL))) {
if (bLockDrive) {
for (i = 0; i < DRIVE_ACCESS_RETRIES; i++) {
if (DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL))
goto out;
if (IS_ERROR(FormatStatus)) // User cancel
break;
Sleep(DRIVE_ACCESS_TIMEOUT/DRIVE_ACCESS_RETRIES);
}
// If we reached this section, either we didn't manage to get a lock or the user cancelled
uprintf("Could not get exclusive access to device %s: %s\n", Path, WindowsErrorString());
safe_closehandle(hDrive);
goto out;
}
out:
@ -114,7 +122,8 @@ HANDLE GetPhysicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockDrive)
// See http://msdn.microsoft.com/en-us/library/cc542456.aspx
// The returned string is allocated and must be freed
// TODO: a drive may have multiple volumes - should we handle those?
char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash)
#define suprintf(...) if (!bSilent) uprintf(__VA_ARGS__)
char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent)
{
BOOL success = FALSE;
char volume_name[MAX_PATH];
@ -134,13 +143,13 @@ char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash)
if (i == 0) {
hVolume = FindFirstVolumeA(volume_name, sizeof(volume_name));
if (hVolume == INVALID_HANDLE_VALUE) {
uprintf("Could not access first GUID volume: %s\n", WindowsErrorString());
suprintf("Could not access first GUID volume: %s\n", WindowsErrorString());
goto out;
}
} else {
if (!FindNextVolumeA(hVolume, volume_name, sizeof(volume_name))) {
if (GetLastError() != ERROR_NO_MORE_FILES) {
uprintf("Could not access next GUID volume: %s\n", WindowsErrorString());
suprintf("Could not access next GUID volume: %s\n", WindowsErrorString());
}
goto out;
}
@ -149,7 +158,7 @@ char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash)
// Sanity checks
len = safe_strlen(volume_name);
if ((len <= 1) || (safe_strnicmp(volume_name, volume_start, 4) != 0) || (volume_name[len-1] != '\\')) {
uprintf("'%s' is not a GUID volume name\n", volume_name);
suprintf("'%s' is not a GUID volume name\n", volume_name);
continue;
}
@ -162,27 +171,27 @@ char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash)
volume_name[len-1] = 0;
if (QueryDosDeviceA(&volume_name[4], path, sizeof(path)) == 0) {
uprintf("Failed to get device path for GUID volume '%s': %s\n", volume_name, WindowsErrorString());
suprintf("Failed to get device path for GUID volume '%s': %s\n", volume_name, WindowsErrorString());
continue;
}
for (j=0; (j<ARRAYSIZE(ignore_device)) &&
(safe_strnicmp(path, ignore_device[j], safe_strlen(ignore_device[j])) != 0); j++);
if (j < ARRAYSIZE(ignore_device)) {
uprintf("Skipping GUID volume for '%s'\n", path);
suprintf("Skipping GUID volume for '%s'\n", path);
continue;
}
// If we can't have FILE_SHARE_WRITE, forget it
hDrive = CreateFileA(volume_name, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if (hDrive == INVALID_HANDLE_VALUE) {
uprintf("Could not open GUID volume '%s': %s\n", volume_name, WindowsErrorString());
suprintf("Could not open GUID volume '%s': %s\n", volume_name, WindowsErrorString());
continue;
}
if ((!DeviceIoControl(hDrive, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0,
&DiskExtents, sizeof(DiskExtents), &size, NULL)) || (size <= 0)) {
uprintf("Could not get Disk Extents: %s\n", WindowsErrorString());
suprintf("Could not get Disk Extents: %s\n", WindowsErrorString());
safe_closehandle(hDrive);
continue;
}
@ -201,13 +210,41 @@ out:
return (success)?safe_strdup(volume_name):NULL;
}
/* Wait for a logical drive to reappear - Used when a drive has just been repartitioned */
BOOL WaitForLogical(DWORD DriveIndex)
{
DWORD i;
char* LogicalPath = NULL;
for (i = 0; i < DRIVE_ACCESS_RETRIES; i++) {
LogicalPath = GetLogicalName(DriveIndex, FALSE, TRUE);
if (LogicalPath != NULL) {
free(LogicalPath);
return TRUE;
}
if (IS_ERROR(FormatStatus)) // User cancel
return FALSE;
Sleep(DRIVE_ACCESS_TIMEOUT/DRIVE_ACCESS_RETRIES);
}
uprintf("Timeout while waiting for logical drive\n");
return FALSE;
}
/*
* Return a handle to the first logical volume on the disk identified by DriveIndex
* Obtain a handle to the first logical volume on the disk identified by DriveIndex
* Returns INVALID_HANDLE_VALUE on error or NULL if no logical path exists (typical
* of unpartitioned drives)
*/
HANDLE GetLogicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockDrive)
{
HANDLE hLogical = INVALID_HANDLE_VALUE;
char* LogicalPath = GetLogicalName(DriveIndex, FALSE);
char* LogicalPath = GetLogicalName(DriveIndex, FALSE, FALSE);
if (LogicalPath == NULL) {
uprintf("No logical drive found (unpartitioned?)\n");
return NULL;
}
hLogical = GetHandle(LogicalPath, bWriteAccess, bLockDrive);
safe_free(LogicalPath);
return hLogical;
@ -451,7 +488,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
safe_closehandle(hPhysical);
// Populate the filesystem data
volume_name = GetLogicalName(DriveIndex, TRUE);
volume_name = GetLogicalName(DriveIndex, TRUE, FALSE);
if ((volume_name == NULL) || (!GetVolumeInformationA(volume_name, NULL, 0, NULL, NULL, NULL, FileSystemName, FileSystemNameSize))) {
uprintf("No volume information for disk 0x%02x\n", DriveIndex);
FileSystemName[0] = 0;
@ -490,8 +527,9 @@ typedef struct _DRIVE_LAYOUT_INFORMATION_EX4 {
* Create a partition table
* See http://technet.microsoft.com/en-us/library/cc739412.aspx for some background info
* NB: if you modify the MBR outside of using the Windows API, Windows still uses the cached
* copy it got from the last IOCTL, and ignore your changes until you replug the drive...
*/
* copy it got from the last IOCTL, and ignores your changes until you replug the drive
* or issue an IOCTL_DISK_UPDATE_PROPERTIES.
*/
#if !defined(PARTITION_BASIC_DATA_GUID)
const GUID PARTITION_BASIC_DATA_GUID = { 0xebd0a0a2, 0xb9e5, 0x4433, {0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7} };
#endif
@ -627,6 +665,41 @@ BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL m
safe_closehandle(hDrive);
return FALSE;
}
// Diskpart does call the following IOCTL this after updating the partition table, so we do too
r = DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &size, NULL );
if (!r) {
uprintf("Could not refresh drive layout: %s\n", WindowsErrorString());
safe_closehandle(hDrive);
return FALSE;
}
return TRUE;
}
/* Delete the disk partition table */
BOOL DeletePartitions(HANDLE hDrive)
{
BOOL r;
DWORD size;
PrintStatus(0, TRUE, "Erasing Partitions...");
r = DeviceIoControl(hDrive, IOCTL_DISK_DELETE_DRIVE_LAYOUT, NULL, 0, NULL, 0, &size, NULL );
if (!r) {
// Ignore GEN_FAILURE as this is what XP returns for unpartitioned
if (GetLastError() != ERROR_GEN_FAILURE) {
uprintf("Could not delete drive layout: %s\n", WindowsErrorString());
safe_closehandle(hDrive);
return FALSE;
}
}
r = DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &size, NULL );
if (!r) {
uprintf("Could not refresh drive layout: %s\n", WindowsErrorString());
safe_closehandle(hDrive);
return FALSE;
}
return TRUE;
}

View File

@ -328,7 +328,6 @@ static DWORD GetFATSizeSectors(DWORD DskSize, DWORD ReservedSecCnt, DWORD SecPer
* Large FAT32 volume formatting from fat32format by Tom Thornhill
* http://www.ridgecrop.demon.co.uk/index.htm?fat32format.htm
*/
// TODO: (v1.3.4) disable slow format for > 32 GB FAT32
static BOOL FormatFAT32(DWORD DriveIndex)
{
BOOL r = FALSE;
@ -369,15 +368,14 @@ static BOOL FormatFAT32(DWORD DriveIndex)
PrintStatus(0, TRUE, "Formatting (Large FAT32)...");
VolumeId = GetVolumeID();
// Open the drive (volume should already be locked)
hLogicalVolume = GetLogicalHandle(DriveIndex, TRUE, FALSE);
// Open the drive and lock it
hLogicalVolume = GetLogicalHandle(DriveIndex, TRUE, TRUE);
if (IS_ERROR(FormatStatus)) goto out;
if (hLogicalVolume == INVALID_HANDLE_VALUE)
die("Could not access logical volume\n", ERROR_OPEN_FAILED);
if ((hLogicalVolume == INVALID_HANDLE_VALUE) || (hLogicalVolume == NULL))
die("Invalid logical volume handle\n", ERROR_INVALID_HANDLE);
// Make sure we get exclusive access
if (!UnmountVolume(hLogicalVolume))
return r;
// Try to disappear the volume while we're formatting it
UnmountVolume(hLogicalVolume);
// Work out drive params
if (!DeviceIoControl (hLogicalVolume, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &dgDrive,
@ -581,7 +579,7 @@ static BOOL FormatFAT32(DWORD DriveIndex)
// Handle must be closed for SetVolumeLabel to work
safe_closehandle(hLogicalVolume);
PrintStatus(0, TRUE, "Setting Label (This may take while)...");
VolumeName = GetLogicalName(DriveIndex, TRUE);
VolumeName = GetLogicalName(DriveIndex, TRUE, TRUE);
wVolumeName = utf8_to_wchar(VolumeName);
if ((wVolumeName == NULL) || (!SetVolumeLabelW(wVolumeName, wLabel))) {
uprintf("Could not set label: %s\n", WindowsErrorString());
@ -620,7 +618,7 @@ static BOOL FormatDrive(DWORD DriveIndex)
GetWindowTextA(hFileSystem, FSType, ARRAYSIZE(FSType));
safe_sprintf(format_status, ARRAYSIZE(format_status), "Formatting (%s)...", FSType);
PrintStatus(0, TRUE, format_status);
VolumeName = GetLogicalName(DriveIndex, FALSE);
VolumeName = GetLogicalName(DriveIndex, FALSE, TRUE);
wVolumeName = utf8_to_wchar(VolumeName);
if (wVolumeName == NULL) {
uprintf("Could not read volume name\n");
@ -820,6 +818,7 @@ BOOL WriteRufusMBR(FILE *fp)
static BOOL WriteMBR(HANDLE hPhysicalDrive)
{
BOOL r = FALSE;
DWORD size;
int dt, fs;
unsigned char* buf = NULL;
size_t SecSize = SelectedDrive.Geometry.BytesPerSector;
@ -889,6 +888,9 @@ static BOOL WriteMBR(HANDLE hPhysicalDrive)
}
}
// Tell the system we've updated the disk properties
DeviceIoControl(hPhysicalDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &size, NULL );
out:
safe_free(buf);
return r;
@ -1088,19 +1090,46 @@ out:
return r;
}
/*
* Mount the volume identified by drive_guid to mountpoint drive_name
*/
static BOOL MountVolume(char* drive_name, char *drive_guid)
{
char mounted_guid[52]; // You need at least 51 characters on XP
if (!SetVolumeMountPointA(drive_name, drive_guid)) {
// If the OS was faster than us at remounting the drive, this operation can fail
// with ERROR_DIR_NOT_EMPTY. If that's the case, just check that mountpoints match
if (GetLastError() == ERROR_DIR_NOT_EMPTY) {
if (!GetVolumeNameForVolumeMountPointA(drive_name, mounted_guid, sizeof(mounted_guid))) {
uprintf("%s already mounted, but volume GUID could not be checked: %s\n",
drive_name, WindowsErrorString());
return FALSE;
}
if (safe_strcmp(drive_guid, mounted_guid) != 0) {
uprintf("%s already mounted, but volume GUID doesn't match:\r\n expected %s, got %s\n",
drive_name, drive_guid, mounted_guid);
return FALSE;
}
uprintf("%s was already mounted as %s\n", drive_guid, drive_name);
} else {
return FALSE;
}
}
return TRUE;
}
/*
* Issue a complete remount of the volume
*/
static BOOL RemountVolume(char drive_letter)
static BOOL RemountVolume(char* drive_name)
{
char drive_guid[50];
char drive_name[] = "?:\\";
char drive_guid[51];
drive_name[0] = drive_letter;
if (GetVolumeNameForVolumeMountPointA(drive_name, drive_guid, sizeof(drive_guid))) {
if (DeleteVolumeMountPointA(drive_name)) {
Sleep(200);
if (SetVolumeMountPointA(drive_name, drive_guid)) {
if (MountVolume(drive_name, drive_guid)) {
uprintf("Successfully remounted %s on %s\n", &drive_guid[4], drive_name);
} else {
uprintf("Failed to remount %s on %s\n", &drive_guid[4], drive_name);
@ -1170,6 +1199,7 @@ DWORD WINAPI CloseFormatPromptThread(LPVOID param) {
* Unlock the volume.
* Close the volume handle.
*/
#define CHECK_FOR_USER_CANCEL if (IS_ERROR(FormatStatus)) goto out
DWORD WINAPI FormatThread(LPVOID param)
{
int r, pt, bt, fs, dt;
@ -1212,26 +1242,41 @@ DWORD WINAPI FormatThread(LPVOID param)
uprintf("Failed to delete mountpoint %s: %s\n", drive_name, WindowsErrorString());
// Try to continue. We will bail out if this causes an issue.
}
uprintf("Will use '%c': as volume mountpoint\n", drive_name[0]);
uprintf("Will use '%c:' as volume mountpoint\n", drive_name[0]);
// ...but we need a lock to the logical drive to be able to write anything to it
hLogicalVolume = GetLogicalHandle(DriveIndex, FALSE, TRUE);
if (hLogicalVolume == INVALID_HANDLE_VALUE) {
uprintf("Could not lock volume\n");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
goto out;
} else if (hLogicalVolume == NULL) {
// NULL is returned for cases where the drive is not yet partitioned
uprintf("Drive does not appear to be partitioned\n");
} else if (!UnmountVolume(hLogicalVolume)) {
uprintf("Trying to continue regardless...\n");
}
UnmountVolume(hLogicalVolume);
if (FormatStatus) goto out; // Check for user cancel
CHECK_FOR_USER_CANCEL;
PrintStatus(0, TRUE, "Analyzing existing boot records...\n");
AnalyzeMBR(hPhysicalDrive);
AnalyzePBR(hLogicalVolume);
if (hLogicalVolume != NULL) {
AnalyzePBR(hLogicalVolume);
}
UpdateProgress(OP_ANALYZE_MBR, -1.0f);
// Zap any existing partitions. This should help to prevent access errors
// TODO: With this, we should be able to avoid having to deal with the logical volume above
if (!DeletePartitions(hPhysicalDrive)) {
uprintf("Could not reset partitions\n");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_PARTITION_FAILURE;
goto out;
}
if (IsChecked(IDC_BADBLOCKS)) {
do {
// create a log file for bad blocks report. Since %USERPROFILE% may
// have localised characters, we use the UTF-8 API.
// have localized characters, we use the UTF-8 API.
userdir = getenvU("USERPROFILE");
safe_strcpy(logfile, MAX_PATH, userdir);
safe_free(userdir);
@ -1251,9 +1296,8 @@ DWORD WINAPI FormatThread(LPVOID param)
if (!BadBlocks(hPhysicalDrive, SelectedDrive.DiskSize,
SelectedDrive.Geometry.BytesPerSector, ComboBox_GetCurSel(hNBPasses)+1, &report, log_fd)) {
uprintf("Bad blocks: Check failed.\n");
if (!FormatStatus)
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|
APPERR(ERROR_BADBLOCKS_FAILURE);
if (!IS_ERROR(FormatStatus))
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_BADBLOCKS_FAILURE);
ClearMBRGPT(hPhysicalDrive, SelectedDrive.DiskSize, SelectedDrive.Geometry.BytesPerSector);
fclose(log_fd);
_unlink(logfile);
@ -1288,13 +1332,14 @@ DWORD WINAPI FormatThread(LPVOID param)
goto out;
}
}
// Close the (unmounted) volume before formatting, but keep the lock
// According to MS this relinquishes the lock, so...
PrintStatus(0, TRUE, "Closing existing volume...\n");
if (!CloseHandle(hLogicalVolume)) {
uprintf("Could not close volume: %s\n", WindowsErrorString());
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_ACCESS_DENIED;
goto out;
// Close the (unmounted) volume before formatting
if (hLogicalVolume != NULL) {
PrintStatus(0, TRUE, "Closing existing volume...\n");
if (!CloseHandle(hLogicalVolume)) {
uprintf("Could not close volume: %s\n", WindowsErrorString());
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_ACCESS_DENIED;
goto out;
}
}
hLogicalVolume = INVALID_HANDLE_VALUE;
@ -1304,12 +1349,12 @@ DWORD WINAPI FormatThread(LPVOID param)
// before repartitioning. Else, all kind of bad things can happen.
if (!ClearMBRGPT(hPhysicalDrive, SelectedDrive.DiskSize, SelectedDrive.Geometry.BytesPerSector)) {
uprintf("unable to zero MBR/GPT\n");
if (!FormatStatus)
if (!IS_ERROR(FormatStatus))
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT;
goto out;
}
if (FormatStatus) goto out; // Check for user cancel
UpdateProgress(OP_ZERO_MBR, -1.0f);
CHECK_FOR_USER_CANCEL;
CreateThread(NULL, 0, CloseFormatPromptThread, NULL, 0, NULL);
if (!CreatePartition(hPhysicalDrive, pt, fs, (pt==PARTITION_STYLE_MBR)&&(bt==BT_UEFI))) {
@ -1318,8 +1363,11 @@ DWORD WINAPI FormatThread(LPVOID param)
}
UpdateProgress(OP_PARTITION, -1.0f);
// Add a small delay after partitioning to be safe
// Wait for the logical drive we just created to appear
uprintf("Waiting for logical drive to reappear...\n");
Sleep(200);
WaitForLogical(DriveIndex); // We try to continue even if this fails, just in case
CHECK_FOR_USER_CANCEL;
// If FAT32 is requested and we have a large drive (>32 GB) use
// large FAT32 format, else use MS's FormatEx.
@ -1331,7 +1379,22 @@ DWORD WINAPI FormatThread(LPVOID param)
goto out;
}
guid_volume = GetLogicalName(DriveIndex, TRUE);
// Thanks to Microsoft, we must fix the MBR AFTER the drive has been formatted
if (pt == PARTITION_STYLE_MBR) {
PrintStatus(0, TRUE, "Writing master boot record...");
if (!WriteMBR(hPhysicalDrive)) {
if (!IS_ERROR(FormatStatus))
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT;
goto out;
}
UpdateProgress(OP_FIX_MBR, -1.0f);
}
Sleep(200);
WaitForLogical(DriveIndex);
// Try to continue
CHECK_FOR_USER_CANCEL;
guid_volume = GetLogicalName(DriveIndex, TRUE, TRUE);
if (guid_volume == NULL) {
uprintf("Could not get GUID volume name\n");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NO_VOLUME_ID;
@ -1339,22 +1402,12 @@ DWORD WINAPI FormatThread(LPVOID param)
}
uprintf("Found volume GUID %s\n", guid_volume);
if (pt == PARTITION_STYLE_MBR) {
PrintStatus(0, TRUE, "Writing master boot record...");
if (!WriteMBR(hPhysicalDrive)) {
if (!FormatStatus)
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT;
goto out;
}
UpdateProgress(OP_FIX_MBR, -1.0f);
}
if (FormatStatus) goto out; // Check for user cancel
if (!SetVolumeMountPointA(drive_name, guid_volume)) {
if (!MountVolume(drive_name, guid_volume)) {
uprintf("Could not remount %s on %s: %s\n", guid_volume, drive_name, WindowsErrorString());
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_CANT_MOUNT_VOLUME);
goto out;
}
CHECK_FOR_USER_CANCEL;
if (IsChecked(IDC_BOOT)) {
if (bt == BT_UEFI) {
@ -1368,7 +1421,7 @@ DWORD WINAPI FormatThread(LPVOID param)
// We still have a lock, which we need to modify the volume boot record
// => no need to reacquire the lock...
hLogicalVolume = GetLogicalHandle(DriveIndex, TRUE, FALSE);
if (hLogicalVolume == INVALID_HANDLE_VALUE) {
if ((hLogicalVolume == INVALID_HANDLE_VALUE) || (hLogicalVolume == NULL)) {
uprintf("Could not re-mount volume for partition boot record access\n");
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
goto out;
@ -1377,7 +1430,7 @@ DWORD WINAPI FormatThread(LPVOID param)
// [0x00000456] The media in the drive may have changed
PrintStatus(0, TRUE, "Writing partition boot record...");
if (!WritePBR(hLogicalVolume)) {
if (!FormatStatus)
if (!IS_ERROR(FormatStatus))
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT;
goto out;
}
@ -1392,21 +1445,21 @@ DWORD WINAPI FormatThread(LPVOID param)
if (IsChecked(IDC_SET_ICON))
SetAutorun(drive_name);
}
if (FormatStatus) goto out; // Check for user cancel
CHECK_FOR_USER_CANCEL;
// We issue a complete remount of the filesystem at on account of:
// - Ensuring the file explorer properly detects that the volume was updated
// - Ensuring that an NTFS system will be reparsed so that it becomes bootable
if (!RemountVolume(drive_name[0]))
if (!RemountVolume(drive_name))
goto out;
if (FormatStatus) goto out; // Check for user cancel
CHECK_FOR_USER_CANCEL;
if (IsChecked(IDC_BOOT)) {
if ((dt == DT_WINME) || (dt == DT_FREEDOS)) {
UpdateProgress(OP_DOS, -1.0f);
PrintStatus(0, TRUE, "Copying DOS files...");
if (!ExtractDOS(drive_name)) {
if (!FormatStatus)
if (!IS_ERROR(FormatStatus))
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY;
goto out;
}
@ -1416,7 +1469,7 @@ DWORD WINAPI FormatThread(LPVOID param)
PrintStatus(0, TRUE, "Copying ISO files...");
drive_name[2] = 0;
if (!ExtractISO(iso_path, drive_name, FALSE)) {
if (!FormatStatus)
if (!IS_ERROR(FormatStatus))
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY;
goto out;
}
@ -1449,7 +1502,7 @@ DWORD WINAPI FormatThread(LPVOID param)
if (IsChecked(IDC_SET_ICON))
SetAutorun(drive_name);
// Issue another complete remount before we exit, to ensure we're clean
RemountVolume(drive_name[0]);
RemountVolume(drive_name);
// NTFS fixup (WinPE/AIK images don't seem to boot without an extra checkdisk)
if ((dt == DT_ISO) && (fs == FS_NTFS)) {
CheckDisk(drive_name[0]);

View File

@ -41,15 +41,15 @@ int64_t write_sectors(HANDLE hDrive, uint64_t SectorSize,
ptr.QuadPart = StartSector*SectorSize;
if(!SetFilePointerEx(hDrive, ptr, NULL, FILE_BEGIN))
{
uprintf("write_sectors: Could not access sector %d - %s\n", StartSector, WindowsErrorString());
uprintf("write_sectors: Could not access sector 0x%08llx - %s\n", StartSector, WindowsErrorString());
return -1;
}
if((!WriteFile(hDrive, pBuf, Size, &Size, NULL)) || (Size != nSectors*SectorSize))
{
uprintf("write_sectors: Write error - %s\n", WindowsErrorString());
uprintf(" Wrote: %d, Expected: %d\n", Size, nSectors*SectorSize);
uprintf(" StartSector:%0X, nSectors:%0X, SectorSize:%0X\n", StartSector, nSectors, SectorSize);
uprintf("write_sectors: Write error %s\n", (GetLastError()!=ERROR_SUCCESS)?WindowsErrorString():"");
uprintf(" Wrote: %d, Expected: %lld\n", Size, nSectors*SectorSize);
uprintf(" StartSector: 0x%08llx, nSectors: 0x%llx, SectorSize: 0x%llx\n", StartSector, nSectors, SectorSize);
return Size;
}
@ -74,15 +74,15 @@ int64_t read_sectors(HANDLE hDrive, uint64_t SectorSize,
ptr.QuadPart = StartSector*SectorSize;
if(!SetFilePointerEx(hDrive, ptr, NULL, FILE_BEGIN))
{
uprintf("read_sectors: Could not access sector %d - %s\n", StartSector, WindowsErrorString());
uprintf("read_sectors: Could not access sector 0x%08llx - %s\n", StartSector, WindowsErrorString());
return -1;
}
if((!ReadFile(hDrive, pBuf, Size, &Size, NULL)) || (Size != nSectors*SectorSize))
{
uprintf("read_sectors: Read error - %s\n", WindowsErrorString());
uprintf(" Read: %d, Expected: %d\n", Size, nSectors*SectorSize);
uprintf(" StartSector:%0X, nSectors:%0X, SectorSize:%0X\n", StartSector, nSectors, SectorSize);
uprintf("read_sectors: Read error %s\n", (GetLastError()!=ERROR_SUCCESS)?WindowsErrorString():"");
uprintf(" Read: %d, Expected: %lld\n", Size, nSectors*SectorSize);
uprintf(" StartSector: 0x%08llx, nSectors: 0x%llx, SectorSize: 0x%llx\n", StartSector, nSectors, SectorSize);
}
return (int64_t)Size;

View File

@ -625,7 +625,7 @@ static BOOL GetUSBDevices(DWORD devnum)
if(GetLastError() != ERROR_NO_MORE_ITEMS) {
uprintf("SetupDiEnumDeviceInterfaces failed: %s\n", WindowsErrorString());
} else {
uprintf("A device was eliminated because it didn't report itself as a disk\n");
uprintf("A device was eliminated because it didn't report itself as a removable disk\n");
}
break;
}
@ -1265,6 +1265,8 @@ void InitDialog(HWND hDlg)
HDC hDC;
int i, i16, s16;
char tmp[128], *token;
BOOL is_x64 = FALSE;
BOOL (__stdcall *pIsWow64Process)(HANDLE, PBOOL) = NULL;
#ifdef RUFUS_TEST
ShowWindow(GetDlgItem(hDlg, IDC_TEST), SW_SHOW);
@ -1310,6 +1312,18 @@ void InitDialog(HWND hDlg)
rufus_version[i] = (uint16_t)atoi(token);
uprintf(APPLICATION_NAME " version %d.%d.%d.%d\n", rufus_version[0], rufus_version[1], rufus_version[2], rufus_version[3]);
// Detect if we're running a 32 or 64 bit system
if (sizeof(uintptr_t) < 8) {
pIsWow64Process = (BOOL (__stdcall *)(HANDLE, PBOOL))
GetProcAddress(GetModuleHandleA("KERNEL32"), "IsWow64Process");
if (pIsWow64Process != NULL) {
(*pIsWow64Process)(GetCurrentProcess(), &is_x64);
}
} else {
is_x64 = TRUE;
}
uprintf("Windows version: %s %d-bit\n", PrintWindowsVersion(nWindowsVersion), is_x64?64:32);
// Prefer FreeDOS to MS-DOS
selection_default = DT_FREEDOS;
// Create the status line and initialize the taskbar icon for progress overlay
@ -1543,16 +1557,22 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
Point.x = min(DialogRect.right + GetSystemMetrics(SM_CXSIZEFRAME)+(int)(2.0f * fScale), DesktopRect.right - nWidth);
Point.y = max(DialogRect.top, DesktopRect.top - nHeight);
MoveWindow(hLogDlg, Point.x, Point.y, nWidth, nHeight, FALSE);
// The log may have been recentered to fit the screen, in which case, try to shift our main dialog left
nWidth = DialogRect.right - DialogRect.left;
nHeight = DialogRect.bottom - DialogRect.top;
MoveWindow(hDlg, max((DialogRect.left<0)?DialogRect.left:0,
Point.x - nWidth - GetSystemMetrics(SM_CXSIZEFRAME) - (int)(2.0f * fScale)), Point.y, nWidth, nHeight, TRUE);
first_log_display = FALSE;
}
// Display the log Window
log_displayed = !log_displayed;
ShowWindow(hLogDlg, log_displayed?SW_SHOW:SW_HIDE);
if (IsShown(hISOProgressDlg))
SetFocus(hISOProgressDlg);
// Set focus on the start button
SendMessage(hMainDialog, WM_NEXTDLGCTL, (WPARAM)FALSE, 0);
SendMessage(hMainDialog, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hMainDialog, IDC_START), TRUE);
// Must come last for the log window to get focus
ShowWindow(hLogDlg, log_displayed?SW_SHOW:SW_HIDE);
break;
#ifdef RUFUS_TEST
case IDC_TEST:
@ -1815,8 +1835,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
SendMessage(hProgress, PBM_SETSTATE, (WPARAM)PBST_ERROR, 0);
SetTaskbarProgressState(TASKBAR_ERROR);
PrintStatus(0, FALSE, "FAILED");
Notification(MSG_ERROR, NULL, "Error", "Error: %s.%s", StrError(FormatStatus),
(strchr(StrError(FormatStatus), '\n') != NULL)?"":"\nFor more information, please check the log.");
Notification(MSG_ERROR, NULL, "Error", "Error: %s", StrError(FormatStatus));
}
FormatStatus = 0;
format_op_in_progress = FALSE;
@ -1919,8 +1938,11 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
wait_for_mutex = 150; // Try to acquire the mutex for 15 seconds
}
while ((opt = getopt_long(argc, argv, "?hi:w:", long_options, &option_index)) != EOF)
while ((opt = getopt_long(argc, argv, "?fhi:w:", long_options, &option_index)) != EOF)
switch (opt) {
case 'f':
enable_fixed_disks = TRUE;
break;
case 'i':
if (_access(optarg, 0) != -1) {
iso_path = safe_strdup(optarg);

View File

@ -36,6 +36,8 @@
#define STR_NO_LABEL "NO_LABEL"
#define RUFUS_CANCELBOX_TITLE APPLICATION_NAME " - Cancellation"
#define RUFUS_BLOCKING_IO_TITLE APPLICATION_NAME " - Flushing buffers"
#define DRIVE_ACCESS_TIMEOUT 10000 // How long we should retry drive access (in ms)
#define DRIVE_ACCESS_RETRIES 20 // How many times we should retry
#define DRIVE_INDEX_MIN 0x00000080
#define DRIVE_INDEX_MAX 0x000000C0
#define MAX_DRIVES (DRIVE_INDEX_MAX - DRIVE_INDEX_MIN)
@ -60,7 +62,6 @@
#define IsChecked(CheckBox_ID) (IsDlgButtonChecked(hMainDialog, CheckBox_ID) == BST_CHECKED)
#define safe_free(p) do {free((void*)p); p = NULL;} while(0)
#define safe_closehandle(h) do {if (h != INVALID_HANDLE_VALUE) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
#define safe_min(a, b) min((size_t)(a), (size_t)(b))
#define safe_strcp(dst, dst_max, src, count) do {memcpy(dst, src, safe_min(count, dst_max)); \
((char*)dst)[safe_min(count, dst_max)-1] = 0;} while(0)
@ -71,8 +72,8 @@
#define safe_stricmp(str1, str2) _stricmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2))
#define safe_strncmp(str1, str2, count) strncmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2), count)
#define safe_strnicmp(str1, str2, count) _strnicmp(((str1==NULL)?"<NULL>":str1), ((str2==NULL)?"<NULL>":str2), count)
#define safe_closehandle(h) do {if (h != INVALID_HANDLE_VALUE) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
#define safe_unlockclose(h) do {if (h != INVALID_HANDLE_VALUE) {UnlockDrive(h); CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
#define safe_closehandle(h) do {if ((h != INVALID_HANDLE_VALUE) && (h != NULL)) {CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
#define safe_unlockclose(h) do {if ((h != INVALID_HANDLE_VALUE) && (h != NULL)) {UnlockDrive(h); CloseHandle(h); h = INVALID_HANDLE_VALUE;}} while(0)
#define safe_sprintf(dst, count, ...) do {_snprintf(dst, count, __VA_ARGS__); (dst)[(count)-1] = 0; } while(0)
#define safe_strlen(str) ((((char*)str)==NULL)?0:strlen(str))
#define safe_strdup _strdup
@ -241,14 +242,14 @@ typedef enum TASKBAR_PROGRESS_FLAGS
/* Windows versions */
enum WindowsVersion {
WINDOWS_UNDEFINED,
WINDOWS_UNDEFINED = 0,
WINDOWS_UNSUPPORTED,
WINDOWS_XP,
WINDOWS_2003,
WINDOWS_2003, // Also XP x64
WINDOWS_VISTA,
WINDOWS_7,
WINDOWS_8,
WINDOWS_9
WINDOWS_8_OR_LATER,
WINDOWS_MAX
};
/*
@ -276,6 +277,7 @@ extern int dialog_showing;
* Shared prototypes
*/
extern enum WindowsVersion DetectWindowsVersion(void);
extern const char* PrintWindowsVersion(enum WindowsVersion version);
extern const char *WindowsErrorString(void);
extern void DumpBufferHex(void *buf, size_t size);
extern void PrintStatus(unsigned int duration, BOOL debug, const char *format, ...);
@ -303,11 +305,13 @@ extern BOOL InstallSyslinux(DWORD drive_index, char drive_letter);
DWORD WINAPI FormatThread(void* param);
extern char* GetPhysicalName(DWORD DriveIndex);
extern HANDLE GetPhysicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockDrive);
extern char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash);
extern BOOL WaitForLogical(DWORD DriveIndex);
extern char* GetLogicalName(DWORD DriveIndex, BOOL bKeepTrailingBackslash, BOOL bSilent);
extern HANDLE GetLogicalHandle(DWORD DriveIndex, BOOL bWriteAccess, BOOL bLockDrive);
extern char GetDriveLetter(DWORD DriveIndex);
extern char GetUnusedDriveLetter(void);
extern BOOL CreatePartition(HANDLE hDrive, int partition_style, int file_system, BOOL mbr_uefi_marker);
extern BOOL DeletePartitions(HANDLE hDrive);
extern const char* GetPartitionType(BYTE Type);
extern BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSystemNameSize);
extern BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label);

View File

@ -30,7 +30,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 206, 329
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
CAPTION "Rufus v1.3.4.257"
CAPTION "Rufus v1.3.4.260"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "Start",IDC_START,94,291,50,14
@ -278,8 +278,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,3,4,257
PRODUCTVERSION 1,3,4,257
FILEVERSION 1,3,4,260
PRODUCTVERSION 1,3,4,260
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -296,13 +296,13 @@ BEGIN
BEGIN
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "1.3.4.257"
VALUE "FileVersion", "1.3.4.260"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2013 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "1.3.4.257"
VALUE "ProductVersion", "1.3.4.260"
END
END
BLOCK "VarFileInfo"

View File

@ -27,6 +27,17 @@
#include "msapi_utf8.h"
#include "rufus.h"
// Must be in the same order as enum WindowsVersion
static const char* WindowsVersionName[WINDOWS_MAX] = {
"Undefined",
"Windows 2000 or earlier (unsupported)",
"Windows XP",
"Windows 2003 (or XP x64)",
"Windows Vista",
"Windows 7",
"Windows 8 or later",
};
enum WindowsVersion nWindowsVersion = WINDOWS_UNDEFINED;
/*
@ -48,18 +59,23 @@ enum WindowsVersion DetectWindowsVersion(void)
if ((OSVersion.dwMajorVersion == 5) && (OSVersion.dwMinorVersion == 1))
return WINDOWS_XP;
if ((OSVersion.dwMajorVersion == 5) && (OSVersion.dwMinorVersion == 2))
return WINDOWS_2003;
return WINDOWS_2003;
if ((OSVersion.dwMajorVersion == 6) && (OSVersion.dwMinorVersion == 0))
return WINDOWS_VISTA;
return WINDOWS_VISTA;
if ((OSVersion.dwMajorVersion == 6) && (OSVersion.dwMinorVersion == 1))
return WINDOWS_7;
if ((OSVersion.dwMajorVersion == 6) && (OSVersion.dwMinorVersion == 2))
return WINDOWS_8;
if ((OSVersion.dwMajorVersion > 6) || ((OSVersion.dwMajorVersion == 6) && (OSVersion.dwMinorVersion >= 3)))
return WINDOWS_9;
return WINDOWS_7;
if ((OSVersion.dwMajorVersion > 6) || ((OSVersion.dwMajorVersion == 6) && (OSVersion.dwMinorVersion >= 2)))
return WINDOWS_8_OR_LATER;
return WINDOWS_UNSUPPORTED;
}
const char* PrintWindowsVersion(enum WindowsVersion version)
{
if ((version < 0) || (version >= WINDOWS_MAX))
version = WINDOWS_UNDEFINED;
return WindowsVersionName[version];
}
/*
* String array manipulation
*/

View File

@ -219,60 +219,61 @@ const char* StrError(DWORD error_code)
}
switch (SCODE_CODE(error_code)) {
case ERROR_GEN_FAILURE:
return "Undetermined error while formatting";
return "Undetermined error while formatting.";
case ERROR_INCOMPATIBLE_FS:
return "Cannot use the selected file system for this media";
return "Cannot use the selected file system for this media.";
case ERROR_ACCESS_DENIED:
return "Access to the media is denied";
return "Access to the device is denied.";
case ERROR_WRITE_PROTECT:
return "Media is write protected";
return "Media is write protected.";
case ERROR_DEVICE_IN_USE:
return "The device is in use by another process\n"
"Please close any other process that may be accessing the device";
return "The device is in use by another process. "
"Please close any other process that may be accessing the device.";
case ERROR_CANT_QUICK_FORMAT:
return "Quick format is not available for this device";
return "Quick format is not available for this device.";
case ERROR_LABEL_TOO_LONG:
return "The volume label is invalid";
return "The volume label is invalid.";
case ERROR_INVALID_HANDLE:
return "The device handle is invalid.";
case ERROR_INVALID_CLUSTER_SIZE:
return "The selected cluster size is not valid for this device";
return "The selected cluster size is not valid for this device.";
case ERROR_INVALID_VOLUME_SIZE:
return "The volume size is invalid";
return "The volume size is invalid.";
case ERROR_NO_MEDIA_IN_DRIVE:
return "Please insert a media in drive";
return "Please insert a media in drive.";
case ERROR_NOT_SUPPORTED:
return "An unsupported command was received";
return "An unsupported command was received.";
case ERROR_NOT_ENOUGH_MEMORY:
return "Memory allocation error";
return "Memory allocation error.";
case ERROR_READ_FAULT:
return "Read error";
return "Read error.";
case ERROR_WRITE_FAULT:
return "Write error";
return "Write error.";
case ERROR_OPEN_FAILED:
return "Could not open media. It may be in use by another process.\n"
"Please re-plug the media and try again";
return "Could not open media. It may be in use by another process. "
"Please re-plug the media and try again.";
case ERROR_PARTITION_FAILURE:
return "Error while partitioning drive";
return "Error while partitioning drive.";
case ERROR_CANNOT_COPY:
return "Could not copy files to target drive";
return "Could not copy files to target drive.";
case ERROR_CANCELLED:
return "Cancelled by user";
return "Cancelled by user.";
case ERROR_CANT_START_THREAD:
return "Unable to create formatting thread";
return "Unable to create formatting thread.";
case ERROR_BADBLOCKS_FAILURE:
return "Bad blocks check didn't complete";
return "Bad blocks check didn't complete.";
case ERROR_ISO_SCAN:
return "ISO image scan failure";
return "ISO image scan failure.";
case ERROR_ISO_EXTRACT:
return "ISO image extraction failure";
return "ISO image extraction failure.";
case ERROR_CANT_REMOUNT_VOLUME:
return "Unable to remount volume. You may have to use the\n"
"mountvol.exe command to make your device accessible again";
return "Unable to remount volume.";
case ERROR_CANT_PATCH:
return "Unable to patch/setup files for boot";
return "Unable to patch/setup files for boot.";
case ERROR_CANT_ASSIGN_LETTER:
return "Unable to assign a drive letter";
return "Unable to assign a drive letter.";
case ERROR_CANT_MOUNT_VOLUME:
return "Can't mount GUID volume";
return "Can't mount GUID volume.";
default:
uprintf("Unknown error: %08X\n", error_code);
SetLastError(error_code);