mirror of
https://github.com/pbatard/rufus.git
synced 2024-08-14 23:57:05 +00:00
misc] move formatting functions into their own source
* also add missing #pragma once in msapi_utf8.h
This commit is contained in:
parent
bc252400a1
commit
79f3e78ec3
11 changed files with 644 additions and 569 deletions
|
@ -151,12 +151,14 @@
|
||||||
<ClCompile Include="..\fat16.c" />
|
<ClCompile Include="..\fat16.c" />
|
||||||
<ClCompile Include="..\fat32.c" />
|
<ClCompile Include="..\fat32.c" />
|
||||||
<ClCompile Include="..\file.c" />
|
<ClCompile Include="..\file.c" />
|
||||||
|
<ClCompile Include="..\format.c" />
|
||||||
<ClCompile Include="..\msdos.c" />
|
<ClCompile Include="..\msdos.c" />
|
||||||
<ClCompile Include="..\rufus.c" />
|
<ClCompile Include="..\rufus.c" />
|
||||||
<ClCompile Include="..\stdio.c" />
|
<ClCompile Include="..\stdio.c" />
|
||||||
<ClCompile Include="..\stdlg.c" />
|
<ClCompile Include="..\stdlg.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\format.h" />
|
||||||
<ClInclude Include="..\inc\br.h" />
|
<ClInclude Include="..\inc\br.h" />
|
||||||
<ClInclude Include="..\inc\br_fat12_0x0.h" />
|
<ClInclude Include="..\inc\br_fat12_0x0.h" />
|
||||||
<ClInclude Include="..\inc\br_fat12_0x3e.h" />
|
<ClInclude Include="..\inc\br_fat12_0x3e.h" />
|
||||||
|
|
|
@ -45,6 +45,9 @@
|
||||||
<ClCompile Include="..\stdio.c">
|
<ClCompile Include="..\stdio.c">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\format.c">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\rufus.h">
|
<ClInclude Include="..\rufus.h">
|
||||||
|
@ -146,6 +149,9 @@
|
||||||
<ClInclude Include="..\inc\mbr_zero.h">
|
<ClInclude Include="..\inc\mbr_zero.h">
|
||||||
<Filter>Header Files\inc</Filter>
|
<Filter>Header Files\inc</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\format.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\rufus.ico">
|
<None Include="..\rufus.ico">
|
||||||
|
|
|
@ -23,13 +23,14 @@ TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \
|
||||||
# http://jpassing.com/2008/02/01/how-to-use-manifests-with-buildexe/
|
# http://jpassing.com/2008/02/01/how-to-use-manifests-with-buildexe/
|
||||||
SXS_APPLICATION_MANIFEST=common_controls_and_elevation.manifest
|
SXS_APPLICATION_MANIFEST=common_controls_and_elevation.manifest
|
||||||
|
|
||||||
SOURCES=rufus.c \
|
SOURCES=rufus.c \
|
||||||
stdio.c \
|
format.c \
|
||||||
stdlg.c \
|
stdio.c \
|
||||||
msdos.c \
|
stdlg.c \
|
||||||
file.c \
|
msdos.c \
|
||||||
br.c \
|
file.c \
|
||||||
fat12.c \
|
br.c \
|
||||||
fat16.c \
|
fat12.c \
|
||||||
fat32.c \
|
fat16.c \
|
||||||
|
fat32.c \
|
||||||
rufus.rc
|
rufus.rc
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -17,7 +17,7 @@
|
||||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
# 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 stdio.o stdlg.o rufus.o
|
OBJECTS = fat12.o fat16.o fat32.o br.o file.o msdos.o format.o stdio.o stdlg.o rufus.o
|
||||||
TARGET = rufus
|
TARGET = rufus
|
||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
|
|
435
format.c
Normal file
435
format.c
Normal file
|
@ -0,0 +1,435 @@
|
||||||
|
/*
|
||||||
|
* Rufus: The Resourceful USB Formatting Utility
|
||||||
|
* Formatting 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 <windowsx.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <process.h>
|
||||||
|
// #include <ctype.h>
|
||||||
|
|
||||||
|
#include "msapi_utf8.h"
|
||||||
|
#include "rufus.h"
|
||||||
|
#include "resource.h"
|
||||||
|
#include "br.h"
|
||||||
|
#include "fat16.h"
|
||||||
|
#include "fat32.h"
|
||||||
|
#include "file.h"
|
||||||
|
#include "format.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FormatEx callback. Return FALSE to halt operations
|
||||||
|
*/
|
||||||
|
static BOOLEAN __stdcall FormatExCallback(FILE_SYSTEM_CALLBACK_COMMAND Command, DWORD Action, PVOID pData)
|
||||||
|
{
|
||||||
|
DWORD* percent;
|
||||||
|
int task_number = 0;
|
||||||
|
|
||||||
|
if (IS_ERROR(FormatStatus))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
switch(Command) {
|
||||||
|
case FCC_PROGRESS:
|
||||||
|
percent = (DWORD*)pData;
|
||||||
|
PostMessage(hMainDialog, UM_FORMAT_PROGRESS, (WPARAM)*percent, (LPARAM)0);
|
||||||
|
uprintf("%d percent completed.\n", *percent);
|
||||||
|
break;
|
||||||
|
case FCC_STRUCTURE_PROGRESS: // No progress on quick format
|
||||||
|
uprintf("Format task %d/? completed.\n", ++task_number);
|
||||||
|
break;
|
||||||
|
case FCC_DONE:
|
||||||
|
if(*(BOOLEAN*)pData == FALSE) {
|
||||||
|
uprintf("Error while formatting.\n");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_GEN_FAILURE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FCC_DONE_WITH_STRUCTURE: // We get this message when formatting Small FAT16
|
||||||
|
// pData Seems to be a struct with at least one (32 BIT!!!) string pointer to the size in MB
|
||||||
|
uprintf("Done with that sort of things: Action=%d pData=%0p\n", Action, pData);
|
||||||
|
DumpBufferHex(pData, 8);
|
||||||
|
uprintf("Volume size: %s MB\n", (char*)(LONG_PTR)(*(ULONG32*)pData));
|
||||||
|
break;
|
||||||
|
case FCC_INCOMPATIBLE_FILE_SYSTEM:
|
||||||
|
uprintf("Incompatible File System\n");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INCOMPATIBLE_FS;
|
||||||
|
break;
|
||||||
|
case FCC_ACCESS_DENIED:
|
||||||
|
uprintf("Access denied\n");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_ACCESS_DENIED;
|
||||||
|
break;
|
||||||
|
case FCC_MEDIA_WRITE_PROTECTED:
|
||||||
|
uprintf("Media is write protected\n");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_PROTECT;
|
||||||
|
break;
|
||||||
|
case FCC_VOLUME_IN_USE:
|
||||||
|
uprintf("Volume is in use\n");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_DEVICE_IN_USE;
|
||||||
|
break;
|
||||||
|
case FCC_CANT_QUICK_FORMAT:
|
||||||
|
uprintf("Cannot quick format this volume\n");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANT_QUICK_FORMAT;
|
||||||
|
break;
|
||||||
|
case FCC_BAD_LABEL:
|
||||||
|
uprintf("Bad label\n");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_LABEL_TOO_LONG;
|
||||||
|
break;
|
||||||
|
case FCC_OUTPUT:
|
||||||
|
uprintf("%s\n", ((PTEXTOUTPUT)pData)->Output);
|
||||||
|
break;
|
||||||
|
case FCC_CLUSTER_SIZE_TOO_BIG:
|
||||||
|
case FCC_CLUSTER_SIZE_TOO_SMALL:
|
||||||
|
uprintf("Unsupported cluster size\n");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INVALID_CLUSTER_SIZE;
|
||||||
|
break;
|
||||||
|
case FCC_VOLUME_TOO_BIG:
|
||||||
|
case FCC_VOLUME_TOO_SMALL:
|
||||||
|
uprintf("Volume is too %s\n", FCC_VOLUME_TOO_BIG?"big":"small");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INVALID_VOLUME_SIZE;
|
||||||
|
case FCC_NO_MEDIA_IN_DRIVE:
|
||||||
|
uprintf("No media in drive\n");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NO_MEDIA_IN_DRIVE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
uprintf("FormatExCallback: received unhandled command %X\n", Command);
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_SUPPORTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return (!IS_ERROR(FormatStatus));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Call on fmifs.dll's FormatEx() to format the drive
|
||||||
|
*/
|
||||||
|
static BOOL FormatDrive(char DriveLetter)
|
||||||
|
{
|
||||||
|
BOOL r = FALSE;
|
||||||
|
PF_DECL(FormatEx);
|
||||||
|
WCHAR wDriveRoot[] = L"?:\\";
|
||||||
|
WCHAR wFSType[32];
|
||||||
|
WCHAR wLabel[128];
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
wDriveRoot[0] = (WCHAR)DriveLetter;
|
||||||
|
PrintStatus("Formatting...");
|
||||||
|
PF_INIT_OR_OUT(FormatEx, fmifs);
|
||||||
|
|
||||||
|
// TODO: properly set MediaType
|
||||||
|
GetWindowTextW(hFileSystem, wFSType, ARRAYSIZE(wFSType));
|
||||||
|
// We may have a " (Default)" trail
|
||||||
|
for (i=0; i<wcslen(wFSType); i++) {
|
||||||
|
if (wFSType[i] == ' ') {
|
||||||
|
uprintf("removed %d\n", i);
|
||||||
|
wFSType[i] = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GetWindowTextW(hLabel, wLabel, ARRAYSIZE(wLabel));
|
||||||
|
uprintf("Using cluster size: %d bytes\n", ComboBox_GetItemData(hClusterSize, ComboBox_GetCurSel(hClusterSize)));
|
||||||
|
pfFormatEx(wDriveRoot, RemovableMedia, wFSType, wLabel,
|
||||||
|
IsChecked(IDC_QUICKFORMAT), (ULONG)ComboBox_GetItemData(hClusterSize, ComboBox_GetCurSel(hClusterSize)),
|
||||||
|
FormatExCallback);
|
||||||
|
if (!IS_ERROR(FormatStatus)) {
|
||||||
|
uprintf("Format completed.\n");
|
||||||
|
r = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL AnalyzeMBR(HANDLE hPhysicalDrive)
|
||||||
|
{
|
||||||
|
FILE fake_fd;
|
||||||
|
|
||||||
|
fake_fd._ptr = (char*)hPhysicalDrive;
|
||||||
|
fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector;
|
||||||
|
|
||||||
|
// TODO: Apply this detection before partitioning
|
||||||
|
// TODO: since we detect all these, might as well give some MBR choice to the user?
|
||||||
|
if (is_br(&fake_fd)) {
|
||||||
|
uprintf("Drive has an x86 boot sector\n");
|
||||||
|
} else{
|
||||||
|
uprintf("Drive is missing an x86 boot sector!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
// TODO: Add/Eliminate FAT12?
|
||||||
|
if (is_fat_16_br(&fake_fd) || is_fat_32_br(&fake_fd)) {
|
||||||
|
if (entire_fat_16_br_matches(&fake_fd)) {
|
||||||
|
uprintf("Exact FAT16 DOS boot record match\n");
|
||||||
|
} else if (entire_fat_16_fd_br_matches(&fake_fd)) {
|
||||||
|
uprintf("Exact FAT16 FreeDOS boot record match\n");
|
||||||
|
} else if (entire_fat_32_br_matches(&fake_fd)) {
|
||||||
|
uprintf("Exact FAT32 DOS boot record match\n");
|
||||||
|
} else if (entire_fat_32_nt_br_matches(&fake_fd)) {
|
||||||
|
uprintf("Exact FAT32 NT boot record match\n");
|
||||||
|
} else if (entire_fat_32_fd_br_matches(&fake_fd)) {
|
||||||
|
uprintf("Exactly FAT32 FreeDOS boot record match\n");
|
||||||
|
} else {
|
||||||
|
uprintf("Unknown FAT16 or FAT32 boot record\n");
|
||||||
|
}
|
||||||
|
} else if (is_dos_mbr(&fake_fd)) {
|
||||||
|
uprintf("Microsoft DOS/NT/95A master boot record match\n");
|
||||||
|
} else if (is_dos_f2_mbr(&fake_fd)) {
|
||||||
|
uprintf("Microsoft DOS/NT/95A master boot record with the undocumented\n");
|
||||||
|
uprintf("F2 instruction match\n");
|
||||||
|
} else if (is_95b_mbr(&fake_fd)) {
|
||||||
|
uprintf("Microsoft 95B/98/98SE/ME master boot record match\n");
|
||||||
|
} else if (is_2000_mbr(&fake_fd)) {
|
||||||
|
uprintf("Microsoft 2000/XP/2003 master boot record match\n");
|
||||||
|
} else if (is_vista_mbr(&fake_fd)) {
|
||||||
|
uprintf("Microsoft Vista master boot record match\n");
|
||||||
|
} else if (is_win7_mbr(&fake_fd)) {
|
||||||
|
uprintf("Microsoft 7 master boot record match\n");
|
||||||
|
} else if (is_zero_mbr(&fake_fd)) {
|
||||||
|
uprintf("Zeroed non-bootable master boot record match\n");
|
||||||
|
} else {
|
||||||
|
uprintf("Unknown boot record\n");
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process the MBR
|
||||||
|
*/
|
||||||
|
static BOOL ProcessMBR(HANDLE hPhysicalDrive)
|
||||||
|
{
|
||||||
|
BOOL r = FALSE;
|
||||||
|
unsigned char* buf = NULL;
|
||||||
|
size_t SecSize = SelectedDrive.Geometry.BytesPerSector;
|
||||||
|
size_t nSecs = (0x200 + SecSize -1) / SecSize;
|
||||||
|
FILE fake_fd;
|
||||||
|
|
||||||
|
if (!AnalyzeMBR(hPhysicalDrive)) return FALSE;
|
||||||
|
|
||||||
|
// FormatEx rewrites the MBR and removes the LBA attribute of FAT16
|
||||||
|
// and FAT32 partitions - we need to correct this in the MBR
|
||||||
|
// TODO: something else for bootable GPT
|
||||||
|
buf = (unsigned char*)malloc(SecSize * nSecs);
|
||||||
|
if (buf == NULL) {
|
||||||
|
uprintf("Could not allocate memory for MBR");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!read_sectors(hPhysicalDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize)) {
|
||||||
|
uprintf("Could not read MBR\n");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
// DumpBufferHex(buf, 0x200);
|
||||||
|
switch (ComboBox_GetCurSel(hFileSystem)) {
|
||||||
|
// TODO: check for 0x06 & 0x0b?
|
||||||
|
case FS_FAT16:
|
||||||
|
buf[0x1c2] = 0x0e;
|
||||||
|
break;
|
||||||
|
case FS_FAT32:
|
||||||
|
buf[0x1c2] = 0x0c;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (IsChecked(IDC_DOSSTARTUP)) {
|
||||||
|
buf[0x1be] = 0x80; // Set first partition bootable
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!write_sectors(hPhysicalDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize*nSecs)) {
|
||||||
|
uprintf("Could not write MBR\n");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
fake_fd._ptr = (char*)hPhysicalDrive;
|
||||||
|
fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector;
|
||||||
|
r = write_95b_mbr(&fake_fd);
|
||||||
|
|
||||||
|
if (!read_sectors(hPhysicalDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize)) {
|
||||||
|
uprintf("Could not re-read MBR\n");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
DumpBufferHex(buf, 0x200);
|
||||||
|
|
||||||
|
out:
|
||||||
|
safe_free(buf);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL ProcessFS_BR(HANDLE hLogicalVolume)
|
||||||
|
{
|
||||||
|
BOOL r = FALSE;
|
||||||
|
unsigned char* buf = NULL;
|
||||||
|
FILE fake_fd;
|
||||||
|
size_t SecSize = SelectedDrive.Geometry.BytesPerSector;
|
||||||
|
size_t nSecs = (0x400 + SecSize -1) / SecSize;
|
||||||
|
|
||||||
|
fake_fd._ptr = (char*)hLogicalVolume;
|
||||||
|
fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector;
|
||||||
|
write_fat_32_br(&fake_fd, 0);
|
||||||
|
|
||||||
|
// FormatEx rewrites the MBR and removes the LBA attribute of FAT16
|
||||||
|
// and FAT32 partitions - we need to correct this in the MBR
|
||||||
|
// TODO: something else for bootable GPT
|
||||||
|
buf = (unsigned char*)malloc(SecSize * nSecs);
|
||||||
|
if (buf == NULL) {
|
||||||
|
uprintf("Could not allocate memory for FS BR");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!read_sectors(hLogicalVolume, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize*nSecs)) {
|
||||||
|
uprintf("Could not read FS BR\n");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
uprintf("FS_BR:\n");
|
||||||
|
DumpBufferHex(buf, 0x400);
|
||||||
|
|
||||||
|
out:
|
||||||
|
safe_free(buf);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa364562%28v=vs.85%29.aspx
|
||||||
|
Dismounting a volume is useful when a volume needs to disappear for a while. For
|
||||||
|
example, an application that changes a volume file system from the FAT file system
|
||||||
|
to the NTFS file system might use the following procedure.
|
||||||
|
|
||||||
|
To change a volume file system
|
||||||
|
|
||||||
|
Open a volume.
|
||||||
|
Lock the volume.
|
||||||
|
Format the volume.
|
||||||
|
Dismount the volume.
|
||||||
|
Unlock the volume.
|
||||||
|
Close the volume handle.
|
||||||
|
|
||||||
|
A dismounting operation removes the volume from the FAT file system awareness.
|
||||||
|
When the operating system mounts the volume, it appears as an NTFS file system volume.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Standalone thread for the formatting operation
|
||||||
|
*/
|
||||||
|
void __cdecl FormatThread(void* param)
|
||||||
|
{
|
||||||
|
DWORD num = (DWORD)(uintptr_t)param;
|
||||||
|
HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE;
|
||||||
|
HANDLE hLogicalVolume = INVALID_HANDLE_VALUE;
|
||||||
|
char drive_name[] = "?:";
|
||||||
|
int i;
|
||||||
|
// DWORD size;
|
||||||
|
|
||||||
|
hPhysicalDrive = GetDriveHandle(num, NULL, TRUE, TRUE);
|
||||||
|
if (hPhysicalDrive == INVALID_HANDLE_VALUE) {
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
// At this stage with have both a handle and a lock to the physical drive
|
||||||
|
|
||||||
|
if (!CreatePartition(hPhysicalDrive)) {
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_PARTITION_FAILURE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we can access the volume again before trying to format it
|
||||||
|
for (i=0; i<10; i++) {
|
||||||
|
Sleep(500);
|
||||||
|
hLogicalVolume = GetDriveHandle(num, drive_name, FALSE, TRUE);
|
||||||
|
if (hLogicalVolume != INVALID_HANDLE_VALUE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i >= 10) {
|
||||||
|
uprintf("Could not access volume after partitioning\n");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
// Handle needs to be closed for FormatEx to be happy - we keep a lock though
|
||||||
|
safe_closehandle(hLogicalVolume);
|
||||||
|
|
||||||
|
if (!FormatDrive(drive_name[0])) {
|
||||||
|
// Error will be set by FormatDrive() in FormatStatus
|
||||||
|
uprintf("Format error: 0x%08X\n", FormatStatus);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Enable compression on NTFS
|
||||||
|
// TODO: optionally disable indexing on NTFS
|
||||||
|
// TODO: use progress bar during MBR/FSBR/MSDOS copy
|
||||||
|
|
||||||
|
// Ideally we would lock, FSCTL_DISMOUNT_VOLUME, unlock and close our volume
|
||||||
|
// handle, but some explorer versions have problems with volumes disappear
|
||||||
|
// #define VOL_DISMOUNT
|
||||||
|
#ifdef VOL_DISMOUNT
|
||||||
|
// Dismount the volume
|
||||||
|
hLogicalVolume = GetDriveHandle(num, drive_name, FALSE, TRUE);
|
||||||
|
if (hLogicalVolume == INVALID_HANDLE_VALUE) {
|
||||||
|
uprintf("Could not open the volume for dismount\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DeviceIoControl(hLogicalVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &size, NULL)) {
|
||||||
|
uprintf("Could not dismount volume\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
PrintStatus("Writing master boot record...\n");
|
||||||
|
if (!ProcessMBR(hPhysicalDrive)) {
|
||||||
|
// Errorcode has already been set
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef VOL_DISMOUNT
|
||||||
|
safe_unlockclose(hLogicalVolume);
|
||||||
|
// Sleep(10000);
|
||||||
|
hLogicalVolume = GetDriveHandle(num, drive_name, FALSE, FALSE);
|
||||||
|
if (hLogicalVolume == INVALID_HANDLE_VALUE) {
|
||||||
|
uprintf("Could not re-mount volume\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (IsChecked(IDC_DOSSTARTUP)) {
|
||||||
|
hLogicalVolume = GetDriveHandle(num, drive_name, TRUE, FALSE);
|
||||||
|
if (hLogicalVolume == INVALID_HANDLE_VALUE) {
|
||||||
|
uprintf("Could not re-mount volume\n");
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
PrintStatus("Writing filesystem boot record...\n");
|
||||||
|
if (!ProcessFS_BR(hLogicalVolume)) {
|
||||||
|
// Errorcode has already been set
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
PrintStatus("Copying MS-DOS files...\n");
|
||||||
|
if (!ExtractMSDOS(drive_name)) {
|
||||||
|
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
safe_unlockclose(hLogicalVolume);
|
||||||
|
safe_unlockclose(hPhysicalDrive);
|
||||||
|
PostMessage(hMainDialog, UM_FORMAT_COMPLETED, 0, 0);
|
||||||
|
_endthread();
|
||||||
|
}
|
106
format.h
Normal file
106
format.h
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* Rufus: The Resourceful USB Formatting Utility
|
||||||
|
* Formatting 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/>.
|
||||||
|
*/
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <winioctl.h> // for MEDIA_TYPE
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*
|
||||||
|
* typedefs for the function prototypes. Use the something like:
|
||||||
|
* PF_DECL(FormatEx);
|
||||||
|
* which translates to:
|
||||||
|
* FormatEx_t pfFormatEx = NULL;
|
||||||
|
* in your code, to declare the entrypoint and then use:
|
||||||
|
* PF_INIT(FormatEx, fmifs);
|
||||||
|
* which translates to:
|
||||||
|
* pfFormatEx = (FormatEx_t) GetProcAddress(GetDLLHandle("fmifs"), "FormatEx");
|
||||||
|
* to make it accessible.
|
||||||
|
*/
|
||||||
|
static __inline HMODULE GetDLLHandle(char* szDLLName)
|
||||||
|
{
|
||||||
|
HMODULE h = NULL;
|
||||||
|
if ((h = GetModuleHandleA(szDLLName)) == NULL)
|
||||||
|
h = LoadLibraryA(szDLLName);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
#define PF_DECL(proc) proc##_t pf##proc = NULL
|
||||||
|
#define PF_INIT(proc, dllname) pf##proc = (proc##_t) GetProcAddress(GetDLLHandle(#dllname), #proc)
|
||||||
|
#define PF_INIT_OR_OUT(proc, dllname) \
|
||||||
|
PF_INIT(proc, dllname); if (pf##proc == NULL) { \
|
||||||
|
uprintf("unable to access %s DLL: %s", #dllname, \
|
||||||
|
WindowsErrorString()); goto out; }
|
||||||
|
|
||||||
|
/* Callback command types (some errorcode were filled from HPUSBFW V2.2.3 and their
|
||||||
|
designation from msdn.microsoft.com/en-us/library/windows/desktop/aa819439.aspx */
|
||||||
|
typedef enum {
|
||||||
|
FCC_PROGRESS,
|
||||||
|
FCC_DONE_WITH_STRUCTURE,
|
||||||
|
FCC_UNKNOWN2,
|
||||||
|
FCC_INCOMPATIBLE_FILE_SYSTEM,
|
||||||
|
FCC_UNKNOWN4,
|
||||||
|
FCC_UNKNOWN5,
|
||||||
|
FCC_ACCESS_DENIED,
|
||||||
|
FCC_MEDIA_WRITE_PROTECTED,
|
||||||
|
FCC_VOLUME_IN_USE,
|
||||||
|
FCC_CANT_QUICK_FORMAT,
|
||||||
|
FCC_UNKNOWNA,
|
||||||
|
FCC_DONE,
|
||||||
|
FCC_BAD_LABEL,
|
||||||
|
FCC_UNKNOWND,
|
||||||
|
FCC_OUTPUT,
|
||||||
|
FCC_STRUCTURE_PROGRESS,
|
||||||
|
FCC_CLUSTER_SIZE_TOO_SMALL,
|
||||||
|
FCC_CLUSTER_SIZE_TOO_BIG,
|
||||||
|
FCC_VOLUME_TOO_SMALL,
|
||||||
|
FCC_VOLUME_TOO_BIG,
|
||||||
|
FCC_NO_MEDIA_IN_DRIVE,
|
||||||
|
} FILE_SYSTEM_CALLBACK_COMMAND;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DWORD Lines;
|
||||||
|
CHAR* Output;
|
||||||
|
} TEXTOUTPUT, *PTEXTOUTPUT;
|
||||||
|
|
||||||
|
typedef BOOLEAN (__stdcall *FILE_SYSTEM_CALLBACK)(
|
||||||
|
FILE_SYSTEM_CALLBACK_COMMAND Command,
|
||||||
|
ULONG Action,
|
||||||
|
PVOID pData
|
||||||
|
);
|
||||||
|
|
||||||
|
/* Parameter names aligned to
|
||||||
|
http://msdn.microsoft.com/en-us/library/windows/desktop/aa819439.aspx */
|
||||||
|
typedef VOID (WINAPI *FormatEx_t)(
|
||||||
|
WCHAR* DriveRoot,
|
||||||
|
MEDIA_TYPE MediaType, // See WinIoCtl.h
|
||||||
|
WCHAR* FileSystemTypeName,
|
||||||
|
WCHAR* Label,
|
||||||
|
BOOL QuickFormat,
|
||||||
|
ULONG DesiredUnitAllocationSize,
|
||||||
|
FILE_SYSTEM_CALLBACK Callback
|
||||||
|
);
|
||||||
|
|
||||||
|
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa383357.aspx */
|
||||||
|
typedef enum {
|
||||||
|
FPF_COMPRESSED = 0x01
|
||||||
|
} FILE_SYSTEM_PROP_FLAG;
|
||||||
|
|
||||||
|
typedef BOOLEAN (WINAPI* EnableVolumeCompression_t)(
|
||||||
|
WCHAR* DriveRoot,
|
||||||
|
ULONG CompressionFlags // FILE_SYSTEM_PROP_FLAG
|
||||||
|
);
|
|
@ -25,6 +25,8 @@
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
#include <setupapi.h>
|
#include <setupapi.h>
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
441
rufus.c
441
rufus.c
|
@ -40,26 +40,20 @@
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
|
||||||
// http://git.kernel.org/?p=fs/ext2/e2fsprogs.git;a=blob;f=misc/badblocks.c
|
// http://git.kernel.org/?p=fs/ext2/e2fsprogs.git;a=blob;f=misc/badblocks.c
|
||||||
// http://ms-sys.sourceforge.net/
|
|
||||||
// http://thestarman.pcministry.com/asm/mbr/MSWIN41.htm
|
// http://thestarman.pcministry.com/asm/mbr/MSWIN41.htm
|
||||||
// http://www.c-jump.com/CIS24/Slides/FAT/lecture.html#F01_0130_sector_assignments
|
|
||||||
|
|
||||||
#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 "sys_types.h"
|
||||||
#include "br.h"
|
|
||||||
#include "fat16.h"
|
|
||||||
#include "fat32.h"
|
|
||||||
#include "file.h"
|
|
||||||
|
|
||||||
#if !defined(GUID_DEVINTERFACE_DISK)
|
#if !defined(GUID_DEVINTERFACE_DISK)
|
||||||
const GUID GUID_DEVINTERFACE_DISK = { 0x53f56307L, 0xb6bf, 0x11d0, {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b} };
|
const GUID GUID_DEVINTERFACE_DISK = { 0x53f56307L, 0xb6bf, 0x11d0, {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b} };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char* FileSystemLabel[FS_MAX] = { "FAT", "FAT32", "NTFS", "exFAT" };
|
static const char* FileSystemLabel[FS_MAX] = { "FAT", "FAT32", "NTFS", "exFAT" };
|
||||||
// Don't ask me - just following the MS standard here
|
// Don't ask me - just following the MS standard here
|
||||||
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" };
|
||||||
|
|
||||||
|
@ -81,27 +75,14 @@ HWND hStatus;
|
||||||
float fScale = 1.0f;
|
float fScale = 1.0f;
|
||||||
int default_fs;
|
int default_fs;
|
||||||
ULONG default_clutersize;
|
ULONG default_clutersize;
|
||||||
|
RUFUS_DRIVE_INFO SelectedDrive;
|
||||||
BOOL bBootable;
|
BOOL bBootable;
|
||||||
BOOL bQuickFormat;
|
BOOL bQuickFormat;
|
||||||
|
DWORD FormatStatus;
|
||||||
struct {
|
HWND hDeviceList, hCapacity, hFileSystem, hClusterSize, hLabel;
|
||||||
DWORD DeviceNumber;
|
|
||||||
LONGLONG DiskSize;
|
|
||||||
DISK_GEOMETRY Geometry;
|
|
||||||
DWORD FirstSector;
|
|
||||||
int FSType;
|
|
||||||
struct {
|
|
||||||
ULONG Allowed;
|
|
||||||
ULONG Default;
|
|
||||||
} ClusterSize[FS_MAX];
|
|
||||||
} SelectedDrive;
|
|
||||||
|
|
||||||
static HWND hDeviceList, hCapacity, hFileSystem, hClusterSize, hLabel;
|
|
||||||
static HWND hDeviceTooltip = NULL, hFSTooltip = NULL;
|
static HWND hDeviceTooltip = NULL, hFSTooltip = NULL;
|
||||||
static StrArray DriveID, DriveLabel;
|
|
||||||
static DWORD FormatStatus;
|
|
||||||
|
|
||||||
|
static StrArray DriveID, DriveLabel;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert a partition type to its human readable form using
|
* Convert a partition type to its human readable form using
|
||||||
|
@ -119,7 +100,7 @@ static const char* GetPartitionType(BYTE Type)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open a drive with optional write access - returns a drive HANDLE and the drive letter
|
* Open a drive with optional write access - returns a drive HANDLE and the drive letter
|
||||||
* or INVALID_HANDLE_VALUE (/!\ which is != NULL /!\) on failure
|
* or INVALID_HANDLE_VALUE (/!\ which is DIFFERENT from NULL /!\) on failure
|
||||||
* This call is quite risky (left unchecked, inadvertently passing 0 as index would
|
* 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!),
|
* return a handle to C:, which we might then proceed to unknowingly repartition!),
|
||||||
* so we apply the following mitigation factors:
|
* so we apply the following mitigation factors:
|
||||||
|
@ -128,7 +109,7 @@ static const char* GetPartitionType(BYTE Type)
|
||||||
* typically be the case on C:\ or any other drive in use, we report failure
|
* 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
|
* - We report the full path of any drive that was successfully opened for write acces
|
||||||
*/
|
*/
|
||||||
static HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BOOL bLockDrive)
|
HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BOOL bLockDrive)
|
||||||
{
|
{
|
||||||
BOOL r;
|
BOOL r;
|
||||||
DWORD size;
|
DWORD size;
|
||||||
|
@ -212,12 +193,6 @@ out:
|
||||||
return hDrive;
|
return hDrive;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline BOOL UnlockDrive(HANDLE hDrive)
|
|
||||||
{
|
|
||||||
DWORD size;
|
|
||||||
return DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the drive letter and volume label
|
* Return the drive letter and volume label
|
||||||
*/
|
*/
|
||||||
|
@ -242,12 +217,10 @@ static BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define KB 1024LL
|
#define KB 1024LL
|
||||||
#define MB 1048576LL
|
#define MB 1048576LL
|
||||||
#define GB 1073741824LL
|
#define GB 1073741824LL
|
||||||
#define TB 1099511627776LL
|
#define TB 1099511627776LL
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set cluster size values according to http://support.microsoft.com/kb/140365
|
* Set cluster size values according to http://support.microsoft.com/kb/140365
|
||||||
* this call will return FALSE if we can't find a supportable FS for the drive
|
* this call will return FALSE if we can't find a supportable FS for the drive
|
||||||
|
@ -559,7 +532,7 @@ static BOOL PopulateProperties(int ComboIndex)
|
||||||
/*
|
/*
|
||||||
* Create a partition table
|
* Create a partition table
|
||||||
*/
|
*/
|
||||||
static BOOL CreatePartition(HANDLE hDrive)
|
BOOL CreatePartition(HANDLE hDrive)
|
||||||
{
|
{
|
||||||
BYTE layout[sizeof(DRIVE_LAYOUT_INFORMATION_EX) + 3*sizeof(PARTITION_INFORMATION_EX)] = {0};
|
BYTE layout[sizeof(DRIVE_LAYOUT_INFORMATION_EX) + 3*sizeof(PARTITION_INFORMATION_EX)] = {0};
|
||||||
PDRIVE_LAYOUT_INFORMATION_EX DriveLayoutEx = (PDRIVE_LAYOUT_INFORMATION_EX)layout;
|
PDRIVE_LAYOUT_INFORMATION_EX DriveLayoutEx = (PDRIVE_LAYOUT_INFORMATION_EX)layout;
|
||||||
|
@ -605,402 +578,6 @@ static BOOL CreatePartition(HANDLE hDrive)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* FormatEx callback. Return FALSE to halt operations
|
|
||||||
*/
|
|
||||||
static BOOLEAN __stdcall FormatExCallback(FILE_SYSTEM_CALLBACK_COMMAND Command, DWORD Action, PVOID pData)
|
|
||||||
{
|
|
||||||
DWORD* percent;
|
|
||||||
int task_number = 0;
|
|
||||||
|
|
||||||
if (IS_ERROR(FormatStatus))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
switch(Command) {
|
|
||||||
case FCC_PROGRESS:
|
|
||||||
percent = (DWORD*)pData;
|
|
||||||
PostMessage(hMainDialog, UM_FORMAT_PROGRESS, (WPARAM)*percent, (LPARAM)0);
|
|
||||||
uprintf("%d percent completed.\n", *percent);
|
|
||||||
break;
|
|
||||||
case FCC_STRUCTURE_PROGRESS: // No progress on quick format
|
|
||||||
uprintf("Format task %d/? completed.\n", ++task_number);
|
|
||||||
break;
|
|
||||||
case FCC_DONE:
|
|
||||||
if(*(BOOLEAN*)pData == FALSE) {
|
|
||||||
uprintf("Error while formatting.\n");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_GEN_FAILURE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case FCC_DONE_WITH_STRUCTURE: // We get this message when formatting Small FAT16
|
|
||||||
// pData Seems to be a struct with at least one (32 BIT!!!) string pointer to the size in MB
|
|
||||||
uprintf("Done with that sort of things: Action=%d pData=%0p\n", Action, pData);
|
|
||||||
DumpBufferHex(pData, 8);
|
|
||||||
uprintf("Volume size: %s MB\n", (char*)(LONG_PTR)(*(ULONG32*)pData));
|
|
||||||
break;
|
|
||||||
case FCC_INCOMPATIBLE_FILE_SYSTEM:
|
|
||||||
uprintf("Incompatible File System\n");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INCOMPATIBLE_FS;
|
|
||||||
break;
|
|
||||||
case FCC_ACCESS_DENIED:
|
|
||||||
uprintf("Access denied\n");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_ACCESS_DENIED;
|
|
||||||
break;
|
|
||||||
case FCC_MEDIA_WRITE_PROTECTED:
|
|
||||||
uprintf("Media is write protected\n");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_PROTECT;
|
|
||||||
break;
|
|
||||||
case FCC_VOLUME_IN_USE:
|
|
||||||
uprintf("Volume is in use\n");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_DEVICE_IN_USE;
|
|
||||||
break;
|
|
||||||
case FCC_CANT_QUICK_FORMAT:
|
|
||||||
uprintf("Cannot quick format this volume\n");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANT_QUICK_FORMAT;
|
|
||||||
break;
|
|
||||||
case FCC_BAD_LABEL:
|
|
||||||
uprintf("Bad label\n");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_LABEL_TOO_LONG;
|
|
||||||
break;
|
|
||||||
case FCC_OUTPUT:
|
|
||||||
uprintf("%s\n", ((PTEXTOUTPUT)pData)->Output);
|
|
||||||
break;
|
|
||||||
case FCC_CLUSTER_SIZE_TOO_BIG:
|
|
||||||
case FCC_CLUSTER_SIZE_TOO_SMALL:
|
|
||||||
uprintf("Unsupported cluster size\n");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INVALID_CLUSTER_SIZE;
|
|
||||||
break;
|
|
||||||
case FCC_VOLUME_TOO_BIG:
|
|
||||||
case FCC_VOLUME_TOO_SMALL:
|
|
||||||
uprintf("Volume is too %s\n", FCC_VOLUME_TOO_BIG?"big":"small");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_INVALID_VOLUME_SIZE;
|
|
||||||
case FCC_NO_MEDIA_IN_DRIVE:
|
|
||||||
uprintf("No media in drive\n");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NO_MEDIA_IN_DRIVE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
uprintf("FormatExCallback: received unhandled command %X\n", Command);
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_SUPPORTED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return (!IS_ERROR(FormatStatus));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Call on fmifs.dll's FormatEx() to format the drive
|
|
||||||
*/
|
|
||||||
static BOOL FormatDrive(char DriveLetter)
|
|
||||||
{
|
|
||||||
BOOL r = FALSE;
|
|
||||||
PF_DECL(FormatEx);
|
|
||||||
WCHAR wDriveRoot[] = L"?:\\";
|
|
||||||
WCHAR wFSType[32];
|
|
||||||
WCHAR wLabel[128];
|
|
||||||
size_t i;
|
|
||||||
|
|
||||||
wDriveRoot[0] = (WCHAR)DriveLetter;
|
|
||||||
PrintStatus("Formatting...");
|
|
||||||
PF_INIT_OR_OUT(FormatEx, fmifs);
|
|
||||||
|
|
||||||
// TODO: properly set MediaType
|
|
||||||
GetWindowTextW(hFileSystem, wFSType, ARRAYSIZE(wFSType));
|
|
||||||
// We may have a " (Default)" trail
|
|
||||||
for (i=0; i<wcslen(wFSType); i++) {
|
|
||||||
if (wFSType[i] == ' ') {
|
|
||||||
uprintf("removed %d\n", i);
|
|
||||||
wFSType[i] = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GetWindowTextW(hLabel, wLabel, ARRAYSIZE(wLabel));
|
|
||||||
uprintf("Using cluster size: %d bytes\n", ComboBox_GetItemData(hClusterSize, ComboBox_GetCurSel(hClusterSize)));
|
|
||||||
pfFormatEx(wDriveRoot, RemovableMedia, wFSType, wLabel,
|
|
||||||
IsChecked(IDC_QUICKFORMAT), (ULONG)ComboBox_GetItemData(hClusterSize, ComboBox_GetCurSel(hClusterSize)),
|
|
||||||
FormatExCallback);
|
|
||||||
if (!IS_ERROR(FormatStatus)) {
|
|
||||||
uprintf("Format completed.\n");
|
|
||||||
r = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL AnalyzeMBR(HANDLE hPhysicalDrive)
|
|
||||||
{
|
|
||||||
FILE fake_fd;
|
|
||||||
|
|
||||||
fake_fd._ptr = (char*)hPhysicalDrive;
|
|
||||||
fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector;
|
|
||||||
|
|
||||||
// TODO: Apply this detection before partitioning
|
|
||||||
// TODO: since we detect all these, might as well give some MBR choice to the user?
|
|
||||||
if (is_br(&fake_fd)) {
|
|
||||||
uprintf("Drive has an x86 boot sector\n");
|
|
||||||
} else{
|
|
||||||
uprintf("Drive is missing an x86 boot sector!\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
// TODO: Add/Eliminate FAT12?
|
|
||||||
if (is_fat_16_br(&fake_fd) || is_fat_32_br(&fake_fd)) {
|
|
||||||
if (entire_fat_16_br_matches(&fake_fd)) {
|
|
||||||
uprintf("Exact FAT16 DOS boot record match\n");
|
|
||||||
} else if (entire_fat_16_fd_br_matches(&fake_fd)) {
|
|
||||||
uprintf("Exact FAT16 FreeDOS boot record match\n");
|
|
||||||
} else if (entire_fat_32_br_matches(&fake_fd)) {
|
|
||||||
uprintf("Exact FAT32 DOS boot record match\n");
|
|
||||||
} else if (entire_fat_32_nt_br_matches(&fake_fd)) {
|
|
||||||
uprintf("Exact FAT32 NT boot record match\n");
|
|
||||||
} else if (entire_fat_32_fd_br_matches(&fake_fd)) {
|
|
||||||
uprintf("Exactly FAT32 FreeDOS boot record match\n");
|
|
||||||
} else {
|
|
||||||
uprintf("Unknown FAT16 or FAT32 boot record\n");
|
|
||||||
}
|
|
||||||
} else if (is_dos_mbr(&fake_fd)) {
|
|
||||||
uprintf("Microsoft DOS/NT/95A master boot record match\n");
|
|
||||||
} else if (is_dos_f2_mbr(&fake_fd)) {
|
|
||||||
uprintf("Microsoft DOS/NT/95A master boot record with the undocumented\n");
|
|
||||||
uprintf("F2 instruction match\n");
|
|
||||||
} else if (is_95b_mbr(&fake_fd)) {
|
|
||||||
uprintf("Microsoft 95B/98/98SE/ME master boot record match\n");
|
|
||||||
} else if (is_2000_mbr(&fake_fd)) {
|
|
||||||
uprintf("Microsoft 2000/XP/2003 master boot record match\n");
|
|
||||||
} else if (is_vista_mbr(&fake_fd)) {
|
|
||||||
uprintf("Microsoft Vista master boot record match\n");
|
|
||||||
} else if (is_win7_mbr(&fake_fd)) {
|
|
||||||
uprintf("Microsoft 7 master boot record match\n");
|
|
||||||
} else if (is_zero_mbr(&fake_fd)) {
|
|
||||||
uprintf("Zeroed non-bootable master boot record match\n");
|
|
||||||
} else {
|
|
||||||
uprintf("Unknown boot record\n");
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Process the MBR
|
|
||||||
*/
|
|
||||||
static BOOL ProcessMBR(HANDLE hPhysicalDrive)
|
|
||||||
{
|
|
||||||
BOOL r = FALSE;
|
|
||||||
unsigned char* buf = NULL;
|
|
||||||
size_t SecSize = SelectedDrive.Geometry.BytesPerSector;
|
|
||||||
size_t nSecs = (0x200 + SecSize -1) / SecSize;
|
|
||||||
FILE fake_fd;
|
|
||||||
|
|
||||||
if (!AnalyzeMBR(hPhysicalDrive)) return FALSE;
|
|
||||||
|
|
||||||
// FormatEx rewrites the MBR and removes the LBA attribute of FAT16
|
|
||||||
// and FAT32 partitions - we need to correct this in the MBR
|
|
||||||
// TODO: something else for bootable GPT
|
|
||||||
buf = (unsigned char*)malloc(SecSize * nSecs);
|
|
||||||
if (buf == NULL) {
|
|
||||||
uprintf("Could not allocate memory for MBR");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_ENOUGH_MEMORY;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!read_sectors(hPhysicalDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize)) {
|
|
||||||
uprintf("Could not read MBR\n");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
// DumpBufferHex(buf, 0x200);
|
|
||||||
switch (ComboBox_GetCurSel(hFileSystem)) {
|
|
||||||
// TODO: check for 0x06 & 0x0b?
|
|
||||||
case FS_FAT16:
|
|
||||||
buf[0x1c2] = 0x0e;
|
|
||||||
break;
|
|
||||||
case FS_FAT32:
|
|
||||||
buf[0x1c2] = 0x0c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (IsChecked(IDC_DOSSTARTUP)) {
|
|
||||||
buf[0x1be] = 0x80; // Set first partition bootable
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!write_sectors(hPhysicalDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize*nSecs)) {
|
|
||||||
uprintf("Could not write MBR\n");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
fake_fd._ptr = (char*)hPhysicalDrive;
|
|
||||||
fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector;
|
|
||||||
r = write_95b_mbr(&fake_fd);
|
|
||||||
|
|
||||||
if (!read_sectors(hPhysicalDrive, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize)) {
|
|
||||||
uprintf("Could not re-read MBR\n");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
DumpBufferHex(buf, 0x200);
|
|
||||||
|
|
||||||
out:
|
|
||||||
safe_free(buf);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static BOOL ProcessFS_BR(HANDLE hLogicalVolume)
|
|
||||||
{
|
|
||||||
BOOL r = FALSE;
|
|
||||||
unsigned char* buf = NULL;
|
|
||||||
FILE fake_fd;
|
|
||||||
size_t SecSize = SelectedDrive.Geometry.BytesPerSector;
|
|
||||||
size_t nSecs = (0x400 + SecSize -1) / SecSize;
|
|
||||||
|
|
||||||
fake_fd._ptr = (char*)hLogicalVolume;
|
|
||||||
fake_fd._bufsiz = SelectedDrive.Geometry.BytesPerSector;
|
|
||||||
write_fat_32_br(&fake_fd, 0);
|
|
||||||
|
|
||||||
// FormatEx rewrites the MBR and removes the LBA attribute of FAT16
|
|
||||||
// and FAT32 partitions - we need to correct this in the MBR
|
|
||||||
// TODO: something else for bootable GPT
|
|
||||||
buf = (unsigned char*)malloc(SecSize * nSecs);
|
|
||||||
if (buf == NULL) {
|
|
||||||
uprintf("Could not allocate memory for FS BR");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_NOT_ENOUGH_MEMORY;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!read_sectors(hLogicalVolume, SelectedDrive.Geometry.BytesPerSector, 0, nSecs, buf, SecSize*nSecs)) {
|
|
||||||
uprintf("Could not read FS BR\n");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_READ_FAULT;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
uprintf("FS_BR:\n");
|
|
||||||
DumpBufferHex(buf, 0x400);
|
|
||||||
|
|
||||||
out:
|
|
||||||
safe_free(buf);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa364562%28v=vs.85%29.aspx
|
|
||||||
Dismounting a volume is useful when a volume needs to disappear for a while. For
|
|
||||||
example, an application that changes a volume file system from the FAT file system
|
|
||||||
to the NTFS file system might use the following procedure.
|
|
||||||
|
|
||||||
To change a volume file system
|
|
||||||
|
|
||||||
Open a volume.
|
|
||||||
Lock the volume.
|
|
||||||
Format the volume.
|
|
||||||
Dismount the volume.
|
|
||||||
Unlock the volume.
|
|
||||||
Close the volume handle.
|
|
||||||
|
|
||||||
A dismounting operation removes the volume from the FAT file system awareness.
|
|
||||||
When the operating system mounts the volume, it appears as an NTFS file system volume.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Standalone thread for the formatting operation
|
|
||||||
*/
|
|
||||||
static void __cdecl FormatThread(void* param)
|
|
||||||
{
|
|
||||||
DWORD num = (DWORD)(uintptr_t)param;
|
|
||||||
HANDLE hPhysicalDrive = INVALID_HANDLE_VALUE;
|
|
||||||
HANDLE hLogicalVolume = INVALID_HANDLE_VALUE;
|
|
||||||
char drive_name[] = "?:";
|
|
||||||
int i;
|
|
||||||
// DWORD size;
|
|
||||||
|
|
||||||
hPhysicalDrive = GetDriveHandle(num, NULL, TRUE, TRUE);
|
|
||||||
if (hPhysicalDrive == INVALID_HANDLE_VALUE) {
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
// At this stage with have both a handle and a lock to the physical drive
|
|
||||||
|
|
||||||
if (!CreatePartition(hPhysicalDrive)) {
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_PARTITION_FAILURE;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we can access the volume again before trying to format it
|
|
||||||
for (i=0; i<10; i++) {
|
|
||||||
Sleep(500);
|
|
||||||
hLogicalVolume = GetDriveHandle(num, drive_name, FALSE, TRUE);
|
|
||||||
if (hLogicalVolume != INVALID_HANDLE_VALUE) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i >= 10) {
|
|
||||||
uprintf("Could not access volume after partitioning\n");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
// Handle needs to be closed for FormatEx to be happy - we keep a lock though
|
|
||||||
safe_closehandle(hLogicalVolume);
|
|
||||||
|
|
||||||
if (!FormatDrive(drive_name[0])) {
|
|
||||||
// Error will be set by FormatDrive() in FormatStatus
|
|
||||||
uprintf("Format error: 0x%08X\n", FormatStatus);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Enable compression on NTFS
|
|
||||||
// TODO: optionally disable indexing on NTFS
|
|
||||||
// TODO: use progress bar during MBR/FSBR/MSDOS copy
|
|
||||||
|
|
||||||
// Ideally we would lock, FSCTL_DISMOUNT_VOLUME, unlock and close our volume
|
|
||||||
// handle, but some explorer versions have problems with volumes disappear
|
|
||||||
// #define VOL_DISMOUNT
|
|
||||||
#ifdef VOL_DISMOUNT
|
|
||||||
// Dismount the volume
|
|
||||||
hLogicalVolume = GetDriveHandle(num, drive_name, FALSE, TRUE);
|
|
||||||
if (hLogicalVolume == INVALID_HANDLE_VALUE) {
|
|
||||||
uprintf("Could not open the volume for dismount\n");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DeviceIoControl(hLogicalVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &size, NULL)) {
|
|
||||||
uprintf("Could not dismount volume\n");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
PrintStatus("Writing master boot record...\n");
|
|
||||||
if (!ProcessMBR(hPhysicalDrive)) {
|
|
||||||
// Errorcode has already been set
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef VOL_DISMOUNT
|
|
||||||
safe_unlockclose(hLogicalVolume);
|
|
||||||
// Sleep(10000);
|
|
||||||
hLogicalVolume = GetDriveHandle(num, drive_name, FALSE, FALSE);
|
|
||||||
if (hLogicalVolume == INVALID_HANDLE_VALUE) {
|
|
||||||
uprintf("Could not re-mount volume\n");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (IsChecked(IDC_DOSSTARTUP)) {
|
|
||||||
hLogicalVolume = GetDriveHandle(num, drive_name, TRUE, FALSE);
|
|
||||||
if (hLogicalVolume == INVALID_HANDLE_VALUE) {
|
|
||||||
uprintf("Could not re-mount volume\n");
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_OPEN_FAILED;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
PrintStatus("Writing filesystem boot record...\n");
|
|
||||||
if (!ProcessFS_BR(hLogicalVolume)) {
|
|
||||||
// Errorcode has already been set
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
PrintStatus("Copying MS-DOS files...\n");
|
|
||||||
if (!ExtractMSDOS(drive_name)) {
|
|
||||||
FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
safe_unlockclose(hLogicalVolume);
|
|
||||||
safe_unlockclose(hPhysicalDrive);
|
|
||||||
PostMessage(hMainDialog, UM_FORMAT_COMPLETED, 0, 0);
|
|
||||||
_endthread();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Refresh the list of USB devices
|
* Refresh the list of USB devices
|
||||||
*/
|
*/
|
||||||
|
|
184
rufus.h
184
rufus.h
|
@ -15,8 +15,8 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include <Windows.h>
|
#include <windows.h>
|
||||||
#include <winioctl.h> // for MEDIA_TYPE
|
#include <winioctl.h> // for DISK_GEOMETRY
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
@ -62,42 +62,6 @@
|
||||||
#define safe_vsnprintf vsnprintf
|
#define safe_vsnprintf vsnprintf
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Globals
|
|
||||||
*/
|
|
||||||
extern HINSTANCE hMainInstance;
|
|
||||||
extern HWND hMainDialog;
|
|
||||||
extern HWND hStatus;
|
|
||||||
extern float fScale;
|
|
||||||
extern char szFolderPath[MAX_PATH];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Shared prototypes
|
|
||||||
*/
|
|
||||||
extern char *WindowsErrorString(void);
|
|
||||||
extern void DumpBufferHex(void *buf, size_t size);
|
|
||||||
extern void PrintStatus(const char *format, ...);
|
|
||||||
extern void CenterDialog(HWND hDlg);
|
|
||||||
extern void CreateStatusBar(void);
|
|
||||||
extern INT_PTR CreateAboutBox(void);
|
|
||||||
extern HWND CreateTooltip(HWND hControl, const char* message, int duration);
|
|
||||||
extern void DestroyTooltip(HWND hWnd);
|
|
||||||
extern void DestroyAllTooltips(void);
|
|
||||||
extern void Notification(int type, char* text, char* title);
|
|
||||||
extern BOOL ExtractMSDOS(const char* path);
|
|
||||||
|
|
||||||
/* Basic String Array */
|
|
||||||
typedef struct {
|
|
||||||
char** Table;
|
|
||||||
size_t Size;
|
|
||||||
size_t Index;
|
|
||||||
size_t Max;
|
|
||||||
} StrArray;
|
|
||||||
extern void StrArrayCreate(StrArray* arr, size_t initial_size);
|
|
||||||
extern void StrArrayAdd(StrArray* arr, const char* str);
|
|
||||||
extern void StrArrayClear(StrArray* arr);
|
|
||||||
extern void StrArrayDestroy(StrArray* arr);
|
|
||||||
|
|
||||||
#ifdef RUFUS_DEBUG
|
#ifdef RUFUS_DEBUG
|
||||||
extern void _uprintf(const char *format, ...);
|
extern void _uprintf(const char *format, ...);
|
||||||
#define uprintf(...) _uprintf(__VA_ARGS__)
|
#define uprintf(...) _uprintf(__VA_ARGS__)
|
||||||
|
@ -131,95 +95,73 @@ enum {
|
||||||
FS_MAX
|
FS_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Current drive info */
|
||||||
|
typedef struct {
|
||||||
|
DWORD DeviceNumber;
|
||||||
|
LONGLONG DiskSize;
|
||||||
|
DISK_GEOMETRY Geometry;
|
||||||
|
DWORD FirstSector;
|
||||||
|
int FSType;
|
||||||
|
struct {
|
||||||
|
ULONG Allowed;
|
||||||
|
ULONG Default;
|
||||||
|
} ClusterSize[FS_MAX];
|
||||||
|
} RUFUS_DRIVE_INFO;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Globals
|
||||||
|
*/
|
||||||
|
extern HINSTANCE hMainInstance;
|
||||||
|
extern HWND hMainDialog, hStatus, hDeviceList, hCapacity;
|
||||||
|
extern HWND hFileSystem, hClusterSize, hLabel;
|
||||||
|
extern float fScale;
|
||||||
|
extern char szFolderPath[MAX_PATH];
|
||||||
|
extern DWORD FormatStatus;
|
||||||
|
extern RUFUS_DRIVE_INFO SelectedDrive;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Shared prototypes
|
||||||
|
*/
|
||||||
|
extern char *WindowsErrorString(void);
|
||||||
|
extern void DumpBufferHex(void *buf, size_t size);
|
||||||
|
extern void PrintStatus(const char *format, ...);
|
||||||
|
extern void CenterDialog(HWND hDlg);
|
||||||
|
extern void CreateStatusBar(void);
|
||||||
|
extern INT_PTR CreateAboutBox(void);
|
||||||
|
extern HWND CreateTooltip(HWND hControl, const char* message, int duration);
|
||||||
|
extern void DestroyTooltip(HWND hWnd);
|
||||||
|
extern void DestroyAllTooltips(void);
|
||||||
|
extern void Notification(int type, char* text, char* title);
|
||||||
|
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);
|
||||||
|
|
||||||
|
__inline static BOOL UnlockDrive(HANDLE hDrive)
|
||||||
|
{
|
||||||
|
DWORD size;
|
||||||
|
return DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Basic String Array */
|
||||||
|
typedef struct {
|
||||||
|
char** Table;
|
||||||
|
size_t Size;
|
||||||
|
size_t Index;
|
||||||
|
size_t Max;
|
||||||
|
} StrArray;
|
||||||
|
extern void StrArrayCreate(StrArray* arr, size_t initial_size);
|
||||||
|
extern void StrArrayAdd(StrArray* arr, const char* str);
|
||||||
|
extern void StrArrayClear(StrArray* arr);
|
||||||
|
extern void StrArrayDestroy(StrArray* arr);
|
||||||
|
|
||||||
|
/* We need a redef of this MS structure */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
DWORD DeviceType;
|
DWORD DeviceType;
|
||||||
ULONG DeviceNumber;
|
ULONG DeviceNumber;
|
||||||
ULONG PartitionNumber;
|
ULONG PartitionNumber;
|
||||||
} STORAGE_DEVICE_NUMBER_REDEF;
|
} STORAGE_DEVICE_NUMBER_REDEF;
|
||||||
|
|
||||||
/*
|
|
||||||
* typedefs for the function prototypes. Use the something like:
|
|
||||||
* PF_DECL(FormatEx);
|
|
||||||
* which translates to:
|
|
||||||
* FormatEx_t pfFormatEx = NULL;
|
|
||||||
* in your code, to declare the entrypoint and then use:
|
|
||||||
* PF_INIT(FormatEx, fmifs);
|
|
||||||
* which translates to:
|
|
||||||
* pfFormatEx = (FormatEx_t) GetProcAddress(GetDLLHandle("fmifs"), "FormatEx");
|
|
||||||
* to make it accessible.
|
|
||||||
*/
|
|
||||||
static __inline HMODULE GetDLLHandle(char* szDLLName)
|
|
||||||
{
|
|
||||||
HMODULE h = NULL;
|
|
||||||
if ((h = GetModuleHandleA(szDLLName)) == NULL)
|
|
||||||
h = LoadLibraryA(szDLLName);
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
#define PF_DECL(proc) proc##_t pf##proc = NULL
|
|
||||||
#define PF_INIT(proc, dllname) pf##proc = (proc##_t) GetProcAddress(GetDLLHandle(#dllname), #proc)
|
|
||||||
#define PF_INIT_OR_OUT(proc, dllname) \
|
|
||||||
PF_INIT(proc, dllname); if (pf##proc == NULL) { \
|
|
||||||
uprintf("unable to access %s DLL: %s", #dllname, \
|
|
||||||
WindowsErrorString()); goto out; }
|
|
||||||
|
|
||||||
/* Callback command types (some errorcode were filled from HPUSBFW V2.2.3 and their
|
|
||||||
designation from msdn.microsoft.com/en-us/library/windows/desktop/aa819439.aspx */
|
|
||||||
typedef enum {
|
|
||||||
FCC_PROGRESS,
|
|
||||||
FCC_DONE_WITH_STRUCTURE,
|
|
||||||
FCC_UNKNOWN2,
|
|
||||||
FCC_INCOMPATIBLE_FILE_SYSTEM,
|
|
||||||
FCC_UNKNOWN4,
|
|
||||||
FCC_UNKNOWN5,
|
|
||||||
FCC_ACCESS_DENIED,
|
|
||||||
FCC_MEDIA_WRITE_PROTECTED,
|
|
||||||
FCC_VOLUME_IN_USE,
|
|
||||||
FCC_CANT_QUICK_FORMAT,
|
|
||||||
FCC_UNKNOWNA,
|
|
||||||
FCC_DONE,
|
|
||||||
FCC_BAD_LABEL,
|
|
||||||
FCC_UNKNOWND,
|
|
||||||
FCC_OUTPUT,
|
|
||||||
FCC_STRUCTURE_PROGRESS,
|
|
||||||
FCC_CLUSTER_SIZE_TOO_SMALL,
|
|
||||||
FCC_CLUSTER_SIZE_TOO_BIG,
|
|
||||||
FCC_VOLUME_TOO_SMALL,
|
|
||||||
FCC_VOLUME_TOO_BIG,
|
|
||||||
FCC_NO_MEDIA_IN_DRIVE,
|
|
||||||
} FILE_SYSTEM_CALLBACK_COMMAND;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
DWORD Lines;
|
|
||||||
CHAR* Output;
|
|
||||||
} TEXTOUTPUT, *PTEXTOUTPUT;
|
|
||||||
|
|
||||||
typedef BOOLEAN (__stdcall *FILE_SYSTEM_CALLBACK)(
|
|
||||||
FILE_SYSTEM_CALLBACK_COMMAND Command,
|
|
||||||
ULONG Action,
|
|
||||||
PVOID pData
|
|
||||||
);
|
|
||||||
|
|
||||||
/* Parameter names aligned to
|
|
||||||
http://msdn.microsoft.com/en-us/library/windows/desktop/aa819439.aspx */
|
|
||||||
typedef VOID (WINAPI *FormatEx_t)(
|
|
||||||
WCHAR* DriveRoot,
|
|
||||||
MEDIA_TYPE MediaType, // See WinIoCtl.h
|
|
||||||
WCHAR* FileSystemTypeName,
|
|
||||||
WCHAR* Label,
|
|
||||||
BOOL QuickFormat,
|
|
||||||
ULONG DesiredUnitAllocationSize,
|
|
||||||
FILE_SYSTEM_CALLBACK Callback
|
|
||||||
);
|
|
||||||
|
|
||||||
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa383357.aspx */
|
|
||||||
typedef enum {
|
|
||||||
FPF_COMPRESSED = 0x01
|
|
||||||
} FILE_SYSTEM_PROP_FLAG;
|
|
||||||
|
|
||||||
typedef BOOLEAN (WINAPI* EnableVolumeCompression_t)(
|
|
||||||
WCHAR* DriveRoot,
|
|
||||||
ULONG CompressionFlags // FILE_SYSTEM_PROP_FLAG
|
|
||||||
);
|
|
||||||
|
|
||||||
/* Custom application errors */
|
/* Custom application errors */
|
||||||
#define FAC(f) (f<<16)
|
#define FAC(f) (f<<16)
|
||||||
|
|
12
rufus.rc
12
rufus.rc
|
@ -63,7 +63,7 @@ BEGIN
|
||||||
DEFPUSHBUTTON "OK",IDOK,231,175,50,14,WS_GROUP
|
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,
|
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
|
"SysLink",WS_TABSTOP,46,47,114,9
|
||||||
LTEXT "Version 1.0.0 (Build 57)",IDC_STATIC,46,19,78,8
|
LTEXT "Version 1.0.0 (Build 58)",IDC_STATIC,46,19,78,8
|
||||||
PUSHBUTTON "License...",IDC_ABOUT_LICENSE,46,175,50,14,WS_GROUP
|
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
|
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
|
LTEXT "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8
|
||||||
|
@ -162,8 +162,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,0,0,57
|
FILEVERSION 1,0,0,58
|
||||||
PRODUCTVERSION 1,0,0,57
|
PRODUCTVERSION 1,0,0,58
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -180,13 +180,13 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "akeo.ie"
|
VALUE "CompanyName", "akeo.ie"
|
||||||
VALUE "FileDescription", "Rufus"
|
VALUE "FileDescription", "Rufus"
|
||||||
VALUE "FileVersion", "1.0.0.57"
|
VALUE "FileVersion", "1.0.0.58"
|
||||||
VALUE "InternalName", "Rufus"
|
VALUE "InternalName", "Rufus"
|
||||||
VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)"
|
VALUE "LegalCopyright", "© 2011 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.0.0.57"
|
VALUE "ProductVersion", "1.0.0.58"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
@ -212,7 +212,7 @@ IDI_ICON ICON "rufus.ico"
|
||||||
|
|
||||||
STRINGTABLE
|
STRINGTABLE
|
||||||
BEGIN
|
BEGIN
|
||||||
IDS_VERSION "Rufus v1.0.0.57"
|
IDS_VERSION "Rufus v1.0.0.58"
|
||||||
END
|
END
|
||||||
|
|
||||||
#endif // English resources
|
#endif // English resources
|
||||||
|
|
4
stdio.c
4
stdio.c
|
@ -16,6 +16,10 @@
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* 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 <windows.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
Loading…
Reference in a new issue