mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
[core] add a cheat mode (Alt-P) to toggle GPT ESP to Basic Data
* Windows 10 or later *ONLY* * Also don't report a GPT partition name if it's empty
This commit is contained in:
parent
22fb8febc5
commit
23057f6124
6 changed files with 205 additions and 16 deletions
174
src/drive.c
174
src/drive.c
|
@ -34,6 +34,7 @@
|
||||||
#include "rufus.h"
|
#include "rufus.h"
|
||||||
#include "missing.h"
|
#include "missing.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
#include "settings.h"
|
||||||
#include "msapi_utf8.h"
|
#include "msapi_utf8.h"
|
||||||
#include "localization.h"
|
#include "localization.h"
|
||||||
|
|
||||||
|
@ -917,7 +918,7 @@ UINT GetDriveTypeFromIndex(DWORD DriveIndex)
|
||||||
char GetUnusedDriveLetter(void)
|
char GetUnusedDriveLetter(void)
|
||||||
{
|
{
|
||||||
DWORD size;
|
DWORD size;
|
||||||
char drive_letter = 'Z'+1, *drive, drives[26*4 + 1]; /* "D:\", "E:\", etc., plus one NUL */
|
char drive_letter, *drive, drives[26*4 + 1]; /* "D:\", "E:\", etc., plus one NUL */
|
||||||
|
|
||||||
size = GetLogicalDriveStringsA(sizeof(drives), drives);
|
size = GetLogicalDriveStringsA(sizeof(drives), drives);
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
|
@ -944,6 +945,29 @@ out:
|
||||||
return (drive_letter > 'Z') ? 0 : drive_letter;
|
return (drive_letter > 'Z') ? 0 : drive_letter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL IsDriveLetterInUse(const char drive_letter)
|
||||||
|
{
|
||||||
|
DWORD size;
|
||||||
|
char *drive, drives[26 * 4 + 1];
|
||||||
|
|
||||||
|
size = GetLogicalDriveStringsA(sizeof(drives), drives);
|
||||||
|
if (size == 0) {
|
||||||
|
uprintf("GetLogicalDriveStrings failed: %s", WindowsErrorString());
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
if (size > sizeof(drives)) {
|
||||||
|
uprintf("GetLogicalDriveStrings: Buffer too small (required %d vs. %d)", size, sizeof(drives));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (drive = drives; *drive; drive += safe_strlen(drive) + 1) {
|
||||||
|
if (drive_letter == (char)toupper((int)*drive))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the drive letter and volume label
|
* Return the drive letter and volume label
|
||||||
* If the drive doesn't have a volume assigned, space is returned for the letter
|
* If the drive doesn't have a volume assigned, space is returned for the letter
|
||||||
|
@ -1130,6 +1154,142 @@ BOOL AnalyzePBR(HANDLE hLogicalVolume)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL StoreEspInfo(GUID* guid)
|
||||||
|
{
|
||||||
|
uint8_t j;
|
||||||
|
char key_name[2][16], *str;
|
||||||
|
// Look for an empty slot and use that if available
|
||||||
|
for (j = 1; j <= MAX_ESP_TOGGLE; j++) {
|
||||||
|
static_sprintf(key_name[0], "ToggleEsp%02u", j);
|
||||||
|
str = ReadSettingStr(key_name[0]);
|
||||||
|
if ((str == NULL) || (str[0] == 0))
|
||||||
|
return WriteSettingStr(key_name[0], GuidToString(guid));
|
||||||
|
}
|
||||||
|
// All slots are used => Move every key down and add to last slot
|
||||||
|
// NB: No, we don't care that the slot we remove may not be the oldest.
|
||||||
|
for (j = 1; j < MAX_ESP_TOGGLE; j++) {
|
||||||
|
static_sprintf(key_name[0], "ToggleEsp%02u", j);
|
||||||
|
static_sprintf(key_name[1], "ToggleEsp%02u", j + 1);
|
||||||
|
WriteSettingStr(key_name[0], ReadSettingStr(key_name[1]));
|
||||||
|
}
|
||||||
|
return WriteSettingStr(key_name[1], GuidToString(guid));
|
||||||
|
}
|
||||||
|
|
||||||
|
static GUID* GetEspGuid(uint8_t index)
|
||||||
|
{
|
||||||
|
char key_name[16];
|
||||||
|
|
||||||
|
static_sprintf(key_name, "ToggleEsp%02u", index);
|
||||||
|
return StringToGuid(ReadSettingStr(key_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL ClearEspInfo(uint8_t index)
|
||||||
|
{
|
||||||
|
char key_name[16];
|
||||||
|
static_sprintf(key_name, "ToggleEsp%02u", index);
|
||||||
|
return WriteSettingStr(key_name, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This calls changes the type of a GPT ESP back and forth to Basic Data.
|
||||||
|
* Needed because Windows 10 doesn't mount ESPs by default, and also
|
||||||
|
* doesn't let usermode apps (such as File Explorer) access mounted ESPs.
|
||||||
|
*/
|
||||||
|
BOOL ToggleEsp(DWORD DriveIndex)
|
||||||
|
{
|
||||||
|
char *volume_name, mount_point[] = DEFAULT_ESP_MOUNT_POINT;
|
||||||
|
BOOL r, ret = FALSE, found = FALSE;
|
||||||
|
HANDLE hPhysical;
|
||||||
|
DWORD size, i, j, esp_index = 0;
|
||||||
|
BYTE layout[4096] = { 0 };
|
||||||
|
GUID* guid;
|
||||||
|
PDRIVE_LAYOUT_INFORMATION_EX DriveLayout = (PDRIVE_LAYOUT_INFORMATION_EX)(void*)layout;
|
||||||
|
|
||||||
|
if (nWindowsVersion < WINDOWS_10) {
|
||||||
|
uprintf("ESP toggling is only available for Windows 10 or later");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
hPhysical = GetPhysicalHandle(DriveIndex, FALSE, TRUE, TRUE);
|
||||||
|
if (hPhysical == INVALID_HANDLE_VALUE)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
r = DeviceIoControl(hPhysical, IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
|
||||||
|
NULL, 0, layout, sizeof(layout), &size, NULL);
|
||||||
|
if (!r || size <= 0) {
|
||||||
|
uprintf("Could not get layout for drive 0x%02x: %s", DriveIndex, WindowsErrorString());
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (DriveLayout->PartitionStyle != PARTITION_STYLE_GPT) {
|
||||||
|
uprintf("ESP toggling is only available for GPT drives");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if the current drive contains an ESP
|
||||||
|
for (i = 0, j = 0; i < DriveLayout->PartitionCount; i++) {
|
||||||
|
if (CompareGUID(&DriveLayout->PartitionEntry[i].Gpt.PartitionType, &PARTITION_GENERIC_ESP)) {
|
||||||
|
esp_index = i;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j > 1) {
|
||||||
|
uprintf("ESP toggling is not available for drives with more than one ESP");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (j == 1) {
|
||||||
|
// ESP -> Basic Data
|
||||||
|
i = esp_index;
|
||||||
|
uprintf("ESP name: '%S'", DriveLayout->PartitionEntry[i].Gpt.Name);
|
||||||
|
if (!StoreEspInfo(&DriveLayout->PartitionEntry[i].Gpt.PartitionId)) {
|
||||||
|
uprintf("ESP toggling data could not be stored");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
DriveLayout->PartitionEntry[i].Gpt.PartitionType = PARTITION_MICROSOFT_DATA;
|
||||||
|
} else {
|
||||||
|
// Basic Data -> ESP
|
||||||
|
for (j = 1; j <= MAX_ESP_TOGGLE; j++) {
|
||||||
|
guid = GetEspGuid((uint8_t)j);
|
||||||
|
if (guid != NULL) {
|
||||||
|
for (i = 0; i < DriveLayout->PartitionCount; i++) {
|
||||||
|
if (CompareGUID(guid, &DriveLayout->PartitionEntry[i].Gpt.PartitionId)) {
|
||||||
|
uprintf("BD name: '%S'", DriveLayout->PartitionEntry[i].Gpt.Name);
|
||||||
|
found = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j > MAX_ESP_TOGGLE)
|
||||||
|
goto out;
|
||||||
|
DriveLayout->PartitionEntry[i].Gpt.PartitionType = PARTITION_GENERIC_ESP;
|
||||||
|
}
|
||||||
|
|
||||||
|
DriveLayout->PartitionEntry[i].RewritePartition = TRUE; // Just in case
|
||||||
|
r = DeviceIoControl(hPhysical, IOCTL_DISK_SET_DRIVE_LAYOUT_EX, (BYTE*)DriveLayout, size, NULL, 0, &size, NULL);
|
||||||
|
if (!r) {
|
||||||
|
uprintf("Could not set drive layout: %s", WindowsErrorString());
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
RefreshDriveLayout(hPhysical);
|
||||||
|
if (CompareGUID(&DriveLayout->PartitionEntry[i].Gpt.PartitionType, &PARTITION_GENERIC_ESP)) {
|
||||||
|
// We successfully reverted ESP from Basic Data -> Delete stored ESP info
|
||||||
|
ClearEspInfo((uint8_t)j);
|
||||||
|
} else if (!IsDriveLetterInUse(*mount_point)) {
|
||||||
|
// We succesfully switched ESP to Basic Data -> Try to mount it
|
||||||
|
volume_name = GetLogicalName(DriveIndex, DriveLayout->PartitionEntry[i].StartingOffset.QuadPart, TRUE, FALSE);
|
||||||
|
MountVolume(mount_point, volume_name);
|
||||||
|
free(volume_name);
|
||||||
|
}
|
||||||
|
ret = TRUE;
|
||||||
|
|
||||||
|
out:
|
||||||
|
safe_closehandle(hPhysical);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fill the drive properties (size, FS, etc)
|
* Fill the drive properties (size, FS, etc)
|
||||||
* Returns TRUE if the drive has a partition that can be mounted in Windows, FALSE otherwise
|
* Returns TRUE if the drive has a partition that can be mounted in Windows, FALSE otherwise
|
||||||
|
@ -1162,14 +1322,14 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
|
||||||
|
|
||||||
hPhysical = GetPhysicalHandle(DriveIndex, FALSE, FALSE, TRUE);
|
hPhysical = GetPhysicalHandle(DriveIndex, FALSE, FALSE, TRUE);
|
||||||
if (hPhysical == INVALID_HANDLE_VALUE)
|
if (hPhysical == INVALID_HANDLE_VALUE)
|
||||||
return 0;
|
return FALSE;
|
||||||
|
|
||||||
r = DeviceIoControl(hPhysical, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
|
r = DeviceIoControl(hPhysical, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
|
||||||
NULL, 0, geometry, sizeof(geometry), &size, NULL);
|
NULL, 0, geometry, sizeof(geometry), &size, NULL);
|
||||||
if (!r || size <= 0) {
|
if (!r || size <= 0) {
|
||||||
suprintf("Could not get geometry for drive 0x%02x: %s", DriveIndex, WindowsErrorString());
|
suprintf("Could not get geometry for drive 0x%02x: %s", DriveIndex, WindowsErrorString());
|
||||||
safe_closehandle(hPhysical);
|
safe_closehandle(hPhysical);
|
||||||
return 0;
|
return FALSE;
|
||||||
}
|
}
|
||||||
SelectedDrive.DiskSize = DiskGeometry->DiskSize.QuadPart;
|
SelectedDrive.DiskSize = DiskGeometry->DiskSize.QuadPart;
|
||||||
SelectedDrive.SectorSize = DiskGeometry->Geometry.BytesPerSector;
|
SelectedDrive.SectorSize = DiskGeometry->Geometry.BytesPerSector;
|
||||||
|
@ -1192,7 +1352,7 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
|
||||||
if (!r || size <= 0) {
|
if (!r || size <= 0) {
|
||||||
suprintf("Could not get layout for drive 0x%02x: %s", DriveIndex, WindowsErrorString());
|
suprintf("Could not get layout for drive 0x%02x: %s", DriveIndex, WindowsErrorString());
|
||||||
safe_closehandle(hPhysical);
|
safe_closehandle(hPhysical);
|
||||||
return 0;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
|
@ -1282,8 +1442,10 @@ BOOL GetDrivePartitionData(DWORD DriveIndex, char* FileSystemName, DWORD FileSys
|
||||||
}
|
}
|
||||||
SelectedDrive.nPartitions++;
|
SelectedDrive.nPartitions++;
|
||||||
isUefiNtfs = (wcscmp(DriveLayout->PartitionEntry[i].Gpt.Name, L"UEFI:NTFS") == 0);
|
isUefiNtfs = (wcscmp(DriveLayout->PartitionEntry[i].Gpt.Name, L"UEFI:NTFS") == 0);
|
||||||
suprintf("Partition %d%s:\r\n Type: %s\r\n Name: '%S'", i+1, isUefiNtfs ? " (UEFI:NTFS)" : "",
|
suprintf("Partition %d%s:\r\n Type: %s", i+1, isUefiNtfs ? " (UEFI:NTFS)" : "",
|
||||||
GetGPTPartitionType(&DriveLayout->PartitionEntry[i].Gpt.PartitionType), DriveLayout->PartitionEntry[i].Gpt.Name);
|
GetGPTPartitionType(&DriveLayout->PartitionEntry[i].Gpt.PartitionType));
|
||||||
|
if (DriveLayout->PartitionEntry[i].Gpt.Name[0] != 0)
|
||||||
|
suprintf(" Name: '%S'", DriveLayout->PartitionEntry[i].Gpt.Name);
|
||||||
suprintf(" ID: %s\r\n Size: %s (%" PRIi64 " bytes)\r\n Start Sector: %" PRIi64 ", Attributes: 0x%016" PRIX64,
|
suprintf(" ID: %s\r\n Size: %s (%" PRIi64 " bytes)\r\n Start Sector: %" PRIi64 ", Attributes: 0x%016" PRIX64,
|
||||||
GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionId),
|
GuidToString(&DriveLayout->PartitionEntry[i].Gpt.PartitionId),
|
||||||
SizeToHumanReadable(DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, TRUE, FALSE),
|
SizeToHumanReadable(DriveLayout->PartitionEntry[i].PartitionLength.QuadPart, TRUE, FALSE),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Rufus: The Reliable USB Formatting Utility
|
* Rufus: The Reliable USB Formatting Utility
|
||||||
* Drive access function calls
|
* Drive access function calls
|
||||||
* Copyright © 2011-2019 Pete Batard <pete@akeo.ie>
|
* Copyright © 2011-2020 Pete Batard <pete@akeo.ie>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -377,6 +377,7 @@ int GetDriveNumber(HANDLE hDrive, char* path);
|
||||||
BOOL GetDriveLetters(DWORD DriveIndex, char* drive_letters);
|
BOOL GetDriveLetters(DWORD DriveIndex, char* drive_letters);
|
||||||
UINT GetDriveTypeFromIndex(DWORD DriveIndex);
|
UINT GetDriveTypeFromIndex(DWORD DriveIndex);
|
||||||
char GetUnusedDriveLetter(void);
|
char GetUnusedDriveLetter(void);
|
||||||
|
BOOL IsDriveLetterInUse(const char drive_letter);
|
||||||
BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label);
|
BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label);
|
||||||
uint64_t GetDriveSize(DWORD DriveIndex);
|
uint64_t GetDriveSize(DWORD DriveIndex);
|
||||||
BOOL IsMediaPresent(DWORD DriveIndex);
|
BOOL IsMediaPresent(DWORD DriveIndex);
|
||||||
|
@ -399,3 +400,4 @@ BOOL CyclePort(int index);
|
||||||
int CycleDevice(int index);
|
int CycleDevice(int index);
|
||||||
BOOL RefreshLayout(DWORD DriveIndex);
|
BOOL RefreshLayout(DWORD DriveIndex);
|
||||||
BOOL GetOpticalMedia(IMG_SAVE* img_save);
|
BOOL GetOpticalMedia(IMG_SAVE* img_save);
|
||||||
|
BOOL ToggleEsp(DWORD DriveIndex);
|
||||||
|
|
10
src/rufus.c
10
src/rufus.c
|
@ -3286,7 +3286,7 @@ relaunch:
|
||||||
while(GetMessage(&msg, NULL, 0, 0)) {
|
while(GetMessage(&msg, NULL, 0, 0)) {
|
||||||
static BOOL ctrl_without_focus = FALSE;
|
static BOOL ctrl_without_focus = FALSE;
|
||||||
BOOL no_focus = (msg.message == WM_SYSKEYDOWN) && !(msg.lParam & 0x20000000);
|
BOOL no_focus = (msg.message == WM_SYSKEYDOWN) && !(msg.lParam & 0x20000000);
|
||||||
// ** ****** **** ** **********
|
// ** ****** **** *************
|
||||||
// .,ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
// .,ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||||
|
|
||||||
// Sigh... The things one need to do to detect standalone use of the 'Alt' key.
|
// Sigh... The things one need to do to detect standalone use of the 'Alt' key.
|
||||||
|
@ -3452,6 +3452,14 @@ relaunch:
|
||||||
SaveISO();
|
SaveISO();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
// Alt-P => Toggle GPT ESP to and from Basic Data type (Windows 10 or later)
|
||||||
|
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'P')) {
|
||||||
|
int index = ComboBox_GetCurSel(hDeviceList);
|
||||||
|
DWORD DeviceNum = (DWORD)ComboBox_GetItemData(hDeviceList, index);
|
||||||
|
if (ToggleEsp(DeviceNum))
|
||||||
|
CyclePort(index);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// Alt-Q => Enable file indexing (for file systems that support it)
|
// Alt-Q => Enable file indexing (for file systems that support it)
|
||||||
// For multiple reasons, file indexing is disabled by default
|
// For multiple reasons, file indexing is disabled by default
|
||||||
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'Q')) {
|
if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'Q')) {
|
||||||
|
|
|
@ -71,6 +71,7 @@
|
||||||
#define MAX_REFRESH 25 // How long we should wait to refresh UI elements (in ms)
|
#define MAX_REFRESH 25 // How long we should wait to refresh UI elements (in ms)
|
||||||
#define MAX_GUID_STRING_LENGTH 40
|
#define MAX_GUID_STRING_LENGTH 40
|
||||||
#define MAX_PARTITIONS 16 // Maximum number of partitions we handle
|
#define MAX_PARTITIONS 16 // Maximum number of partitions we handle
|
||||||
|
#define MAX_ESP_TOGGLE 8 // Maximum number of entries we record to toggle GPT ESP back and forth
|
||||||
#define MAX_SECTORS_TO_CLEAR 128 // nb sectors to zap when clearing the MBR/GPT (must be >34)
|
#define MAX_SECTORS_TO_CLEAR 128 // nb sectors to zap when clearing the MBR/GPT (must be >34)
|
||||||
#define MAX_WININST 4 // Max number of install[.wim|.esd] we can handle on an image
|
#define MAX_WININST 4 // Max number of install[.wim|.esd] we can handle on an image
|
||||||
#define MBR_UEFI_MARKER 0x49464555 // 'U', 'E', 'F', 'I', as a 32 bit little endian longword
|
#define MBR_UEFI_MARKER 0x49464555 // 'U', 'E', 'F', 'I', as a 32 bit little endian longword
|
||||||
|
@ -111,6 +112,7 @@
|
||||||
#define WPPRECORDER_MORE_INFO_URL "https://github.com/pbatard/rufus/wiki/FAQ#BSODs_with_Windows_To_Go_drives_created_from_Windows_10_1809_ISOs"
|
#define WPPRECORDER_MORE_INFO_URL "https://github.com/pbatard/rufus/wiki/FAQ#BSODs_with_Windows_To_Go_drives_created_from_Windows_10_1809_ISOs"
|
||||||
#define SEVENZIP_URL "https://www.7-zip.org"
|
#define SEVENZIP_URL "https://www.7-zip.org"
|
||||||
#define FILES_DIR "rufus_files"
|
#define FILES_DIR "rufus_files"
|
||||||
|
#define DEFAULT_ESP_MOUNT_POINT "S:\\"
|
||||||
#define IS_POWER_OF_2(x) ((x != 0) && (((x) & ((x) - 1)) == 0))
|
#define IS_POWER_OF_2(x) ((x != 0) && (((x) & ((x) - 1)) == 0))
|
||||||
#define IGNORE_RETVAL(expr) do { (void)(expr); } while(0)
|
#define IGNORE_RETVAL(expr) do { (void)(expr); } while(0)
|
||||||
#ifndef ARRAYSIZE
|
#ifndef ARRAYSIZE
|
||||||
|
@ -485,6 +487,7 @@ extern void UpdateProgressWithInfo(int op, int msg, uint64_t processed, uint64_t
|
||||||
#define UpdateProgressWithInfoInit(hProgressDialog, bNoAltMode) UpdateProgressWithInfo(OP_INIT, (int)bNoAltMode, (uint64_t)(uintptr_t)hProgressDialog, 0);
|
#define UpdateProgressWithInfoInit(hProgressDialog, bNoAltMode) UpdateProgressWithInfo(OP_INIT, (int)bNoAltMode, (uint64_t)(uintptr_t)hProgressDialog, 0);
|
||||||
extern const char* StrError(DWORD error_code, BOOL use_default_locale);
|
extern const char* StrError(DWORD error_code, BOOL use_default_locale);
|
||||||
extern char* GuidToString(const GUID* guid);
|
extern char* GuidToString(const GUID* guid);
|
||||||
|
extern GUID* StringToGuid(const char* str);
|
||||||
extern char* SizeToHumanReadable(uint64_t size, BOOL copy_to_log, BOOL fake_units);
|
extern char* SizeToHumanReadable(uint64_t size, BOOL copy_to_log, BOOL fake_units);
|
||||||
extern char* TimestampToHumanReadable(uint64_t ts);
|
extern char* TimestampToHumanReadable(uint64_t ts);
|
||||||
extern HWND MyCreateDialog(HINSTANCE hInstance, int Dialog_ID, HWND hWndParent, DLGPROC lpDialogFunc);
|
extern HWND MyCreateDialog(HINSTANCE hInstance, int Dialog_ID, HWND hWndParent, DLGPROC lpDialogFunc);
|
||||||
|
|
10
src/rufus.rc
10
src/rufus.rc
|
@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||||
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
IDD_DIALOG DIALOGEX 12, 12, 232, 326
|
||||||
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_ACCEPTFILES
|
EXSTYLE WS_EX_ACCEPTFILES
|
||||||
CAPTION "Rufus 3.11.1667"
|
CAPTION "Rufus 3.11.1668"
|
||||||
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
|
||||||
BEGIN
|
BEGIN
|
||||||
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
|
||||||
|
@ -395,8 +395,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 3,11,1667,0
|
FILEVERSION 3,11,1668,0
|
||||||
PRODUCTVERSION 3,11,1667,0
|
PRODUCTVERSION 3,11,1668,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -414,13 +414,13 @@ BEGIN
|
||||||
VALUE "Comments", "https://rufus.ie"
|
VALUE "Comments", "https://rufus.ie"
|
||||||
VALUE "CompanyName", "Akeo Consulting"
|
VALUE "CompanyName", "Akeo Consulting"
|
||||||
VALUE "FileDescription", "Rufus"
|
VALUE "FileDescription", "Rufus"
|
||||||
VALUE "FileVersion", "3.11.1667"
|
VALUE "FileVersion", "3.11.1668"
|
||||||
VALUE "InternalName", "Rufus"
|
VALUE "InternalName", "Rufus"
|
||||||
VALUE "LegalCopyright", "© 2011-2020 Pete Batard (GPL v3)"
|
VALUE "LegalCopyright", "© 2011-2020 Pete Batard (GPL v3)"
|
||||||
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
VALUE "LegalTrademarks", "https://www.gnu.org/licenses/gpl-3.0.html"
|
||||||
VALUE "OriginalFilename", "rufus-3.11.exe"
|
VALUE "OriginalFilename", "rufus-3.11.exe"
|
||||||
VALUE "ProductName", "Rufus"
|
VALUE "ProductName", "Rufus"
|
||||||
VALUE "ProductVersion", "3.11.1667"
|
VALUE "ProductVersion", "3.11.1668"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
16
src/stdio.c
16
src/stdio.c
|
@ -674,12 +674,26 @@ char* GuidToString(const GUID* guid)
|
||||||
|
|
||||||
if (guid == NULL) return NULL;
|
if (guid == NULL) return NULL;
|
||||||
sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
|
sprintf(guid_string, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
|
||||||
(unsigned int)guid->Data1, guid->Data2, guid->Data3,
|
(uint32_t)guid->Data1, guid->Data2, guid->Data3,
|
||||||
guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
|
guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
|
||||||
guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
|
guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
|
||||||
return guid_string;
|
return guid_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GUID* StringToGuid(const char* str)
|
||||||
|
{
|
||||||
|
static GUID guid;
|
||||||
|
|
||||||
|
if (str == NULL) return NULL;
|
||||||
|
if (sscanf(str, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
|
||||||
|
(uint32_t*)&guid.Data1, (uint32_t*)&guid.Data2, (uint32_t*)&guid.Data3,
|
||||||
|
(uint32_t*)&guid.Data4[0], (uint32_t*)&guid.Data4[1], (uint32_t*)&guid.Data4[2],
|
||||||
|
(uint32_t*)&guid.Data4[3], (uint32_t*)&guid.Data4[4], (uint32_t*)&guid.Data4[5],
|
||||||
|
(uint32_t*)&guid.Data4[6], (uint32_t*)&guid.Data4[7]) != 11)
|
||||||
|
return NULL;
|
||||||
|
return &guid;
|
||||||
|
}
|
||||||
|
|
||||||
// Find upper power of 2
|
// Find upper power of 2
|
||||||
static __inline uint16_t upo2(uint16_t v)
|
static __inline uint16_t upo2(uint16_t v)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue