[misc] move drive related functions into their own source

This commit is contained in:
Pete Batard 2011-12-01 17:54:35 +00:00
parent 79f3e78ec3
commit 2390b305c8
10 changed files with 226 additions and 162 deletions

View File

@ -147,6 +147,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\br.c" />
<ClCompile Include="..\drive.c" />
<ClCompile Include="..\fat12.c" />
<ClCompile Include="..\fat16.c" />
<ClCompile Include="..\fat32.c" />

View File

@ -13,7 +13,7 @@
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
<Filter Include="Header Files\inc">
<Filter Include="Header Files\ms-sys inc">
<UniqueIdentifier>{ecff9fec-41c4-4ce8-b725-27ee39754cb7}</UniqueIdentifier>
</Filter>
</ItemGroup>
@ -48,6 +48,9 @@
<ClCompile Include="..\format.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\drive.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\rufus.h">
@ -66,88 +69,88 @@
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\br.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\br_fat12_0x0.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\br_fat12_0x3e.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\br_fat16_0x0.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\br_fat16_0x3e.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\br_fat16fd_0x3e.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\br_fat32_0x0.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\br_fat32_0x3f0.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\br_fat32_0x52.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\br_fat32fd_0x3f0.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\br_fat32fd_0x52.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\br_fat32nt_0x0.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\br_fat32nt_0x3f0.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\br_fat32nt_0x52.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\br_fat32nt_0x1800.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\fat12.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\fat16.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\fat32.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\file.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\label_11_char.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\mbr_95b.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\mbr_2000.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\mbr_dos.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\mbr_dos_f2.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\mbr_syslinux.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\mbr_vista.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\mbr_win7.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\inc\mbr_zero.h">
<Filter>Header Files\inc</Filter>
<Filter>Header Files\ms-sys inc</Filter>
</ClInclude>
<ClInclude Include="..\format.h">
<Filter>Header Files</Filter>

View File

@ -28,6 +28,7 @@ SOURCES=rufus.c \
stdio.c \
stdlg.c \
msdos.c \
drive.c \
file.c \
br.c \
fat12.c \

View File

@ -17,7 +17,7 @@
# along with this program; if not, see <http://www.gnu.org/licenses/>.
#
OBJECTS = fat12.o fat16.o fat32.o br.o file.o msdos.o format.o stdio.o stdlg.o rufus.o
OBJECTS = fat12.o fat16.o fat32.o br.o file.o drive.o msdos.o format.o stdio.o stdlg.o rufus.o
TARGET = rufus
CC = gcc

157
drive.c Normal file
View File

@ -0,0 +1,157 @@
/*
* Rufus: The Resourceful USB Formatting Utility
* Drive access function calls
* Copyright (c) 2011 Pete Batard <pete@akeo.ie>
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#endif
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "msapi_utf8.h"
#include "rufus.h"
#include "resource.h"
/*
* Globals
*/
RUFUS_DRIVE_INFO SelectedDrive;
/*
* Open a drive or volume with optional write and lock access
* Returns INVALID_HANDLE_VALUE (/!\ which is DIFFERENT from NULL /!\) on failure.
* This call is quite risky (left unchecked, inadvertently passing 0 as index would
* return a handle to C:, which we might then proceed to unknowingly repartition!),
* so we apply the following mitigation factors:
* - Valid indexes must belong to a specific range [DRIVE_INDEX_MIN; DRIVE_INDEX_MAX]
* - When opening for write access, we lock the volume. If that fails, which would
* typically be the case on C:\ or any other drive in use, we report failure
* - We report the full path of any drive that was successfully opened for write acces
*/
HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BOOL bLockDrive)
{
BOOL r;
DWORD size;
HANDLE hDrive = INVALID_HANDLE_VALUE;
STORAGE_DEVICE_NUMBER_REDEF device_number = {0};
char drives[26*4]; /* "D:\", "E:\", etc. */
char *drive = drives;
char logical_drive[] = "\\\\.\\#:";
char physical_drive[24];
if ((DriveIndex < DRIVE_INDEX_MIN) || (DriveIndex > DRIVE_INDEX_MAX)) {
uprintf("WARNING: Bad index value. Please check the code!\n");
}
DriveIndex -= DRIVE_INDEX_MIN;
// If no drive letter is requested, open a phyical drive
if (DriveLetter == NULL) {
safe_sprintf(physical_drive, sizeof(physical_drive), "\\\\.\\PHYSICALDRIVE%d", DriveIndex);
hDrive = CreateFileA(physical_drive, GENERIC_READ|(bWriteAccess?GENERIC_WRITE:0),
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if (hDrive == INVALID_HANDLE_VALUE) {
uprintf("Could not open drive %s: %s\n", physical_drive, WindowsErrorString());
goto out;
}
if (bWriteAccess) {
uprintf("Caution: Opened %s drive for write access\n", physical_drive);
}
} else {
*DriveLetter = ' ';
size = GetLogicalDriveStringsA(sizeof(drives), drives);
if (size == 0) {
uprintf("GetLogicalDriveStrings failed: %s\n", WindowsErrorString());
goto out;
}
if (size > sizeof(drives)) {
uprintf("GetLogicalDriveStrings: buffer too small (required %d vs %d)\n", size, sizeof(drives));
goto out;
}
hDrive = INVALID_HANDLE_VALUE;
for ( ;*drive; drive += safe_strlen(drive)+1) {
if (!isalpha(*drive))
continue;
*drive = (char)toupper((int)*drive);
if (*drive < 'C') {
continue;
}
safe_sprintf(logical_drive, sizeof(logical_drive), "\\\\.\\%c:", drive[0]);
hDrive = CreateFileA(logical_drive, GENERIC_READ|(bWriteAccess?GENERIC_WRITE:0),
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if (hDrive == INVALID_HANDLE_VALUE) {
uprintf("Warning: could not open drive %c: %s\n", drive[0], WindowsErrorString());
continue;
}
r = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL,
0, &device_number, sizeof(device_number), &size, NULL);
if ((!r) || (size <= 0)) {
uprintf("IOCTL_STORAGE_GET_DEVICE_NUMBER failed for device %s: %s\n",
logical_drive, WindowsErrorString());
} else if (device_number.DeviceNumber == DriveIndex) {
break;
}
safe_closehandle(hDrive);
}
if (hDrive == INVALID_HANDLE_VALUE) {
goto out;
}
if (bWriteAccess) {
uprintf("Caution: Opened %s drive for write access\n", logical_drive);
}
*DriveLetter = *drive?*drive:' ';
}
if ((bLockDrive) && (!DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL))) {
uprintf("Could not get exclusive access to %s: %s\n", logical_drive, WindowsErrorString());
safe_closehandle(hDrive);
goto out;
}
out:
return hDrive;
}
/*
* Return the drive letter and volume label
*/
BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label)
{
HANDLE hDrive;
char DrivePath[] = "#:\\";
static char volume_label[MAX_PATH+1];
*label = STR_NO_LABEL;
hDrive = GetDriveHandle(DriveIndex, DrivePath, FALSE, FALSE);
if (hDrive == INVALID_HANDLE_VALUE)
return FALSE;
safe_closehandle(hDrive);
*letter = DrivePath[0];
if (GetVolumeInformationA(DrivePath, volume_label, sizeof(volume_label),
NULL, NULL, NULL, NULL, 0) && *volume_label) {
*label = volume_label;
}
return TRUE;
}

View File

@ -27,7 +27,7 @@
#include <string.h>
#include <stdlib.h>
#include <process.h>
// #include <ctype.h>
#include <stddef.h>
#include "msapi_utf8.h"
#include "rufus.h"
@ -38,6 +38,11 @@
#include "file.h"
#include "format.h"
/*
* Globals
*/
DWORD FormatStatus;
/*
* FormatEx callback. Return FALSE to halt operations
*/

131
rufus.c
View File

@ -30,7 +30,6 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <commctrl.h>
#include <setupapi.h>
@ -71,14 +70,9 @@ static const char* ClusterSizeLabel[] = { "512 bytes", "1024 bytes","2048 bytes"
HINSTANCE hMainInstance;
HWND hMainDialog;
char szFolderPath[MAX_PATH];
HWND hStatus;
float fScale = 1.0f;
int default_fs;
ULONG default_clutersize;
RUFUS_DRIVE_INFO SelectedDrive;
BOOL bBootable;
BOOL bQuickFormat;
DWORD FormatStatus;
HWND hDeviceList, hCapacity, hFileSystem, hClusterSize, hLabel;
static HWND hDeviceTooltip = NULL, hFSTooltip = NULL;
@ -98,124 +92,6 @@ static const char* GetPartitionType(BYTE Type)
return "Unknown";
}
/*
* Open a drive with optional write access - returns a drive HANDLE and the drive letter
* or INVALID_HANDLE_VALUE (/!\ which is DIFFERENT from NULL /!\) on failure
* This call is quite risky (left unchecked, inadvertently passing 0 as index would
* return a handle to C:, which we might then proceed to unknowingly repartition!),
* so we apply the following mitigation factors:
* - Valid indexes must belong to a specific range [DRIVE_INDEX_MIN; DRIVE_INDEX_MAX]
* - When opening for write access, we lock the volume. If that fails, which would
* typically be the case on C:\ or any other drive in use, we report failure
* - We report the full path of any drive that was successfully opened for write acces
*/
HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BOOL bLockDrive)
{
BOOL r;
DWORD size;
HANDLE hDrive = INVALID_HANDLE_VALUE;
STORAGE_DEVICE_NUMBER_REDEF device_number = {0};
char drives[26*4]; /* "D:\", "E:\", etc. */
char *drive = drives;
char logical_drive[] = "\\\\.\\#:";
char physical_drive[24];
if ((DriveIndex < DRIVE_INDEX_MIN) || (DriveIndex > DRIVE_INDEX_MAX)) {
uprintf("WARNING: Bad index value. Please check the code!\n");
}
DriveIndex -= DRIVE_INDEX_MIN;
// If no drive letter is requested, open a phyical drive
if (DriveLetter == NULL) {
safe_sprintf(physical_drive, sizeof(physical_drive), "\\\\.\\PHYSICALDRIVE%d", DriveIndex);
hDrive = CreateFileA(physical_drive, GENERIC_READ|(bWriteAccess?GENERIC_WRITE:0),
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if (hDrive == INVALID_HANDLE_VALUE) {
uprintf("Could not open drive %s: %s\n", physical_drive, WindowsErrorString());
goto out;
}
if (bWriteAccess) {
uprintf("Caution: Opened %s drive for write access\n", physical_drive);
}
} else {
*DriveLetter = ' ';
size = GetLogicalDriveStringsA(sizeof(drives), drives);
if (size == 0) {
uprintf("GetLogicalDriveStrings failed: %s\n", WindowsErrorString());
goto out;
}
if (size > sizeof(drives)) {
uprintf("GetLogicalDriveStrings: buffer too small (required %d vs %d)\n", size, sizeof(drives));
goto out;
}
hDrive = INVALID_HANDLE_VALUE;
for ( ;*drive; drive += safe_strlen(drive)+1) {
if (!isalpha(*drive))
continue;
*drive = (char)toupper((int)*drive);
if (*drive < 'C') {
continue;
}
safe_sprintf(logical_drive, sizeof(logical_drive), "\\\\.\\%c:", drive[0]);
hDrive = CreateFileA(logical_drive, GENERIC_READ|(bWriteAccess?GENERIC_WRITE:0),
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
if (hDrive == INVALID_HANDLE_VALUE) {
uprintf("Warning: could not open drive %c: %s\n", drive[0], WindowsErrorString());
continue;
}
r = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL,
0, &device_number, sizeof(device_number), &size, NULL);
if ((!r) || (size <= 0)) {
uprintf("IOCTL_STORAGE_GET_DEVICE_NUMBER failed for device %s: %s\n", logical_drive, WindowsErrorString());
} else if (device_number.DeviceNumber == DriveIndex) {
break;
}
safe_closehandle(hDrive);
}
if (hDrive == INVALID_HANDLE_VALUE) {
goto out;
}
if (bWriteAccess) {
uprintf("Caution: Opened %s drive for write access\n", logical_drive);
}
*DriveLetter = *drive?*drive:' ';
}
if ((bLockDrive) && (!DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL))) {
uprintf("Could not get exclusive access to %s: %s\n", logical_drive, WindowsErrorString());
safe_closehandle(hDrive);
goto out;
}
out:
return hDrive;
}
/*
* Return the drive letter and volume label
*/
static BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label)
{
HANDLE hDrive;
char DrivePath[] = "#:\\";
static char volume_label[MAX_PATH+1];
*label = STR_NO_LABEL;
hDrive = GetDriveHandle(DriveIndex, DrivePath, FALSE, FALSE);
if (hDrive == INVALID_HANDLE_VALUE)
return FALSE;
safe_closehandle(hDrive);
*letter = DrivePath[0];
if (GetVolumeInformationA(DrivePath, volume_label, sizeof(volume_label), NULL, NULL, NULL, NULL, 0) && *volume_label) {
*label = volume_label;
}
return TRUE;
}
#define KB 1024LL
#define MB 1048576LL
@ -316,6 +192,9 @@ out:
#undef GB
#undef TB
/*
* Populate the Allocation unit size field
*/
static BOOL SetClusterSizes(int FSType)
{
char szDefault[64];
@ -689,7 +568,9 @@ static BOOL GetUSBDevices(void)
return TRUE;
}
/* Toggle controls according to operation */
/*
* Toggle controls according to operation
*/
static void EnableControls(BOOL bEnable)
{
EnableWindow(GetDlgItem(hMainDialog, IDC_DEVICE), bEnable);

11
rufus.h
View File

@ -136,6 +136,7 @@ extern BOOL ExtractMSDOS(const char* path);
extern void __cdecl FormatThread(void* param);
extern BOOL CreatePartition(HANDLE hDrive);
extern HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BOOL bLockDrive);
extern BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label);
__inline static BOOL UnlockDrive(HANDLE hDrive)
{
@ -155,6 +156,16 @@ extern void StrArrayAdd(StrArray* arr, const char* str);
extern void StrArrayClear(StrArray* arr);
extern void StrArrayDestroy(StrArray* arr);
/* Clang/MinGW32 has an issue with intptr_t */
#ifndef _UINTPTR_T_DEFINED
#define _UINTPTR_T_DEFINED
#ifdef _WIN64
typedef unsigned __int64 uintptr_t;
#else
typedef unsigned int uintptr_t;
#endif
#endif
/* We need a redef of this MS structure */
typedef struct {
DWORD DeviceType;

View File

@ -63,7 +63,7 @@ BEGIN
DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP
CONTROL "<a href=""https://github.com/pbatard/rufus/wiki/Rufus"">https://github.com/pbatard/rufus</a>",IDC_ABOUT_RUFUS_URL,
"SysLink",WS_TABSTOP,46,47,114,9
LTEXT "Version 1.0.0 (Build 58)",IDC_STATIC,46,19,78,8
LTEXT "Version 1.0.0 (Build 59)",IDC_STATIC,46,19,78,8
PUSHBUTTON "License...",IDC_ABOUT_LICENSE,46,175,50,14,WS_GROUP
EDITTEXT IDC_ABOUT_COPYRIGHTS,46,107,235,63,ES_MULTILINE | ES_READONLY | WS_VSCROLL
LTEXT "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8
@ -162,8 +162,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,58
PRODUCTVERSION 1,0,0,58
FILEVERSION 1,0,0,59
PRODUCTVERSION 1,0,0,59
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -180,13 +180,13 @@ BEGIN
BEGIN
VALUE "CompanyName", "akeo.ie"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "1.0.0.58"
VALUE "FileVersion", "1.0.0.59"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "1.0.0.58"
VALUE "ProductVersion", "1.0.0.59"
END
END
BLOCK "VarFileInfo"
@ -212,7 +212,7 @@ IDI_ICON ICON "rufus.ico"
STRINGTABLE
BEGIN
IDS_VERSION "Rufus v1.0.0.58"
IDS_VERSION "Rufus v1.0.0.59"
END
#endif // English resources

View File

@ -31,6 +31,11 @@
#include "rufus.h"
#include "resource.h"
/*
* Globals
*/
HWND hStatus;
#ifdef RUFUS_DEBUG
void _uprintf(const char *format, ...)
{