Fix the format failure when install Ventoy.

This commit is contained in:
longpanda
2022-12-16 17:03:05 +08:00
parent 27eda4d1e7
commit c76ece4b74
21 changed files with 829 additions and 104 deletions

View File

@@ -0,0 +1,385 @@
/******************************************************************************
* AlertSuppress.c
*
* Copyright (c) 2022, longpanda <admin@ventoy.net>
* Copyright (c) 2011-2022 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 <winternl.h>
#include <commctrl.h>
#include <initguid.h>
#include <vds.h>
#include "Ventoy2Disk.h"
#define sfree(p) do {if (p != NULL) {free((void*)(p)); p = NULL;}} while(0)
#define wconvert(p) wchar_t* w ## p = utf8_to_wchar(p)
#define walloc(p, size) wchar_t* w ## p = (p == NULL)?NULL:(wchar_t*)calloc(size, sizeof(wchar_t))
#define wfree(p) sfree(w ## p)
#define static_strcpy(dst, src) strcpy_s(dst, sizeof(dst), src)
#define static_strcat(dst, src) strcat_s(dst, sizeof(dst), src)
#define wchar_to_utf8_no_alloc(wsrc, dest, dest_size) \
WideCharToMultiByte(CP_UTF8, 0, wsrc, -1, dest, dest_size, NULL, NULL)
#define utf8_to_wchar_no_alloc(src, wdest, wdest_size) \
MultiByteToWideChar(CP_UTF8, 0, src, -1, wdest, wdest_size)
/*
* Converts an UTF8 string to UTF-16 (allocate returned string)
* Returns NULL on error
*/
static __inline wchar_t* utf8_to_wchar(const char* str)
{
int size = 0;
wchar_t* wstr = NULL;
if (str == NULL)
return NULL;
// Convert the empty string too
if (str[0] == 0)
return (wchar_t*)calloc(1, sizeof(wchar_t));
// Find out the size we need to allocate for our converted string
size = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
if (size <= 1) // An empty string would be size 1
return NULL;
if ((wstr = (wchar_t*)calloc(size, sizeof(wchar_t))) == NULL)
return NULL;
if (utf8_to_wchar_no_alloc(str, wstr, size) != size) {
sfree(wstr);
return NULL;
}
return wstr;
}
static char title_str[2][128], button_str[128];
static char system_dir[MAX_PATH], sysnative_dir[MAX_PATH];
static HWINEVENTHOOK ap_weh = NULL;
static __inline UINT GetSystemDirectoryU(char* lpBuffer, UINT uSize)
{
UINT ret = 0, err = ERROR_INVALID_DATA;
// coverity[returned_null]
walloc(lpBuffer, uSize);
ret = GetSystemDirectoryW(wlpBuffer, uSize);
err = GetLastError();
if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpBuffer, lpBuffer, uSize)) == 0)) {
err = GetLastError();
}
wfree(lpBuffer);
SetLastError(err);
return ret;
}
static char* ToLocaleName(DWORD lang_id)
{
static char mui_str[LOCALE_NAME_MAX_LENGTH];
wchar_t wmui_str[LOCALE_NAME_MAX_LENGTH];
if (LCIDToLocaleName(lang_id, wmui_str, LOCALE_NAME_MAX_LENGTH, 0) > 0) {
wchar_to_utf8_no_alloc(wmui_str, mui_str, LOCALE_NAME_MAX_LENGTH);
}
else {
static_strcpy(mui_str, "en-US");
}
return mui_str;
}
static __inline int LoadStringU(HINSTANCE hInstance, UINT uID, LPSTR lpBuffer, int nBufferMax)
{
int ret;
DWORD err = ERROR_INVALID_DATA;
if (nBufferMax == 0) {
// read-only pointer to resource mode is not supported
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
// coverity[returned_null]
walloc(lpBuffer, nBufferMax);
ret = LoadStringW(hInstance, uID, wlpBuffer, nBufferMax);
err = GetLastError();
if ((ret > 0) && ((ret = wchar_to_utf8_no_alloc(wlpBuffer, lpBuffer, nBufferMax)) == 0)) {
err = GetLastError();
}
wfree(lpBuffer);
SetLastError(err);
return ret;
}
/*
* 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.
*/
#define MAX_LIBRARY_HANDLES 64
extern HMODULE OpenedLibrariesHandle[MAX_LIBRARY_HANDLES];
extern UINT16 OpenedLibrariesHandleSize;
#define OPENED_LIBRARIES_VARS HMODULE OpenedLibrariesHandle[MAX_LIBRARY_HANDLES]; uint16_t OpenedLibrariesHandleSize = 0
#define CLOSE_OPENED_LIBRARIES while(OpenedLibrariesHandleSize > 0) FreeLibrary(OpenedLibrariesHandle[--OpenedLibrariesHandleSize])
static __inline HMODULE GetLibraryHandle(char* szLibraryName) {
HMODULE h = NULL;
wchar_t* wszLibraryName = NULL;
int size;
if (szLibraryName == NULL || szLibraryName[0] == 0)
goto out;
size = MultiByteToWideChar(CP_UTF8, 0, szLibraryName, -1, NULL, 0);
if ((size <= 1) || ((wszLibraryName = (wchar_t*)calloc(size, sizeof(wchar_t))) == NULL) ||
(MultiByteToWideChar(CP_UTF8, 0, szLibraryName, -1, wszLibraryName, size) != size))
goto out;
// If the library is already opened, just return a handle (that doesn't need to be freed)
if ((h = GetModuleHandleW(wszLibraryName)) != NULL)
goto out;
// Sanity check
if (OpenedLibrariesHandleSize >= MAX_LIBRARY_HANDLES) {
Log("Error: MAX_LIBRARY_HANDLES is too small");
goto out;
}
h = LoadLibraryExW(wszLibraryName, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
// Some Windows 7 platforms (most likely the ones missing KB2533623 per the
// official LoadLibraryEx doc) can return ERROR_INVALID_PARAMETER when using
// the Ex() version. If that's the case, fallback to using LoadLibraryW().
if ((h == NULL) && (SCODE_CODE(GetLastError()) == ERROR_INVALID_PARAMETER))
h = LoadLibraryW(wszLibraryName);
if (h != NULL)
OpenedLibrariesHandle[OpenedLibrariesHandleSize++] = h;
else
Log("Unable to load '%S.dll': %u", wszLibraryName, LASTERR);
out:
free(wszLibraryName);
return h;
}
#define PF_TYPE(api, ret, proc, args) typedef ret (api *proc##_t)args
#define PF_DECL(proc) static proc##_t pf##proc = NULL
#define PF_TYPE_DECL(api, ret, proc, args) PF_TYPE(api, ret, proc, args); PF_DECL(proc)
#define PF_INIT(proc, name) if (pf##proc == NULL) pf##proc = \
(proc##_t) GetProcAddress(GetLibraryHandle(#name), #proc)
#define PF_INIT_OR_OUT(proc, name) do {PF_INIT(proc, name); \
if (pf##proc == NULL) {Log("Unable to locate %s() in '%s.dll': %u", \
#proc, #name, LASTERR); goto out;} } while(0)
#define PF_INIT_OR_SET_STATUS(proc, name) do {PF_INIT(proc, name); \
if ((pf##proc == NULL) && (NT_SUCCESS(status))) status = STATUS_NOT_IMPLEMENTED; } while(0)
static BOOL is_x64(void)
{
BOOL ret = FALSE;
PF_TYPE_DECL(WINAPI, BOOL, IsWow64Process, (HANDLE, PBOOL));
// Detect if we're running a 32 or 64 bit system
if (sizeof(uintptr_t) < 8) {
PF_INIT(IsWow64Process, Kernel32);
if (pfIsWow64Process != NULL) {
(*pfIsWow64Process)(GetCurrentProcess(), &ret);
}
}
else {
ret = TRUE;
}
return ret;
}
static __inline UINT GetSystemWindowsDirectoryU(char* lpBuffer, UINT uSize)
{
UINT ret = 0, err = ERROR_INVALID_DATA;
// coverity[returned_null]
walloc(lpBuffer, uSize);
ret = GetSystemWindowsDirectoryW(wlpBuffer, uSize);
err = GetLastError();
if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpBuffer, lpBuffer, uSize)) == 0)) {
err = GetLastError();
}
wfree(lpBuffer);
SetLastError(err);
return ret;
}
static __inline HMODULE LoadLibraryU(LPCSTR lpFileName)
{
HMODULE ret;
DWORD err = ERROR_INVALID_DATA;
wconvert(lpFileName);
ret = LoadLibraryW(wlpFileName);
err = GetLastError();
wfree(lpFileName);
SetLastError(err);
return ret;
}
BOOL SetAlertPromptMessages(void)
{
HMODULE hMui;
char mui_path[MAX_PATH];
if (GetSystemDirectoryU(system_dir, sizeof(system_dir)) == 0) {
Log("Could not get system directory: %u", LASTERR);
static_strcpy(system_dir, "C:\\Windows\\System32");
}
// Construct Sysnative ourselves as there is no GetSysnativeDirectory() call
// By default (64bit app running on 64 bit OS or 32 bit app running on 32 bit OS)
// Sysnative and System32 are the same
static_strcpy(sysnative_dir, system_dir);
// But if the app is 32 bit and the OS is 64 bit, Sysnative must differ from System32
#if (defined(VTARCH_X86) || defined(VTARCH_ARM))
if (is_x64()) {
if (GetSystemWindowsDirectoryU(sysnative_dir, sizeof(sysnative_dir)) == 0) {
Log("Could not get Windows directory: %u", LASTERR);
static_strcpy(sysnative_dir, "C:\\Windows");
}
static_strcat(sysnative_dir, "\\Sysnative");
}
#endif
Log("system_dir=<%s>", system_dir);
Log("sysnative_dir=<%s>", sysnative_dir);
sprintf_s(mui_path, MAX_PATH, "%s\\%s\\shell32.dll.mui", sysnative_dir, ToLocaleName(GetUserDefaultUILanguage()));
hMui = LoadLibraryU(mui_path);
if (hMui)
{
// 4097 = "You need to format the disk in drive %c: before you can use it." (dialog text)
// 4125 = "Microsoft Windows" (dialog title)
// 4126 = "Format disk" (button)
if (LoadStringU(hMui, 4125, title_str[0], sizeof(title_str[0])) <= 0) {
static_strcpy(title_str[0], "Microsoft Windows");
Log("Warning: Could not locate localized format prompt title string in '%s': %u", mui_path, LASTERR);
}
if (LoadStringU(hMui, 4126, button_str, sizeof(button_str)) <= 0) {
static_strcpy(button_str, "Format disk");
Log("Warning: Could not locate localized format prompt button string in '%s': %u", mui_path, LASTERR);
}
FreeLibrary(hMui);
Log("LoadLibrary shell32.dll.mui SUCCESS");
}
else
{
Log("LoadLibrary shell32.dll.mui FAILED");
}
return TRUE;
}
static __inline int GetWindowTextU(HWND hWnd, char* lpString, int nMaxCount)
{
int ret = 0;
DWORD err = ERROR_INVALID_DATA;
if (nMaxCount < 0)
return 0;
// Handle the empty string as GetWindowTextW() returns 0 then
if ((lpString != NULL) && (nMaxCount > 0))
lpString[0] = 0;
// coverity[returned_null]
walloc(lpString, nMaxCount);
ret = GetWindowTextW(hWnd, wlpString, nMaxCount);
err = GetLastError();
// coverity[var_deref_model]
if ((ret != 0) && ((ret = wchar_to_utf8_no_alloc(wlpString, lpString, nMaxCount)) == 0)) {
err = GetLastError();
}
wfree(lpString);
lpString[nMaxCount - 1] = 0;
SetLastError(err);
return ret;
}
/*
* The following function calls are used to automatically detect and close the native
* Windows format prompt "You must format the disk in drive X:". To do that, we use
* an event hook that gets triggered whenever a window is placed in the foreground.
* In that hook, we look for a dialog that has style WS_POPUPWINDOW and has the relevant
* title. However, because the title in itself is too generic (the expectation is that
* it will be "Microsoft Windows") we also enumerate all the child controls from that
* prompt, using another callback, until we find one that contains the text we expect
* for the "Format disk" button.
* Oh, and since all of these strings are localized, we must first pick them up from
* the relevant mui's.
*/
static BOOL CALLBACK AlertPromptCallback(HWND hWnd, LPARAM lParam)
{
char str[128];
BOOL* found = (BOOL*)lParam;
if (GetWindowTextU(hWnd, str, sizeof(str)) == 0)
return TRUE;
if (strcmp(str, button_str) == 0)
*found = TRUE;
return TRUE;
}
static void CALLBACK AlertPromptHook(HWINEVENTHOOK hWinEventHook, DWORD Event, HWND hWnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
{
char str[128];
BOOL found;
if (Event == EVENT_SYSTEM_FOREGROUND) {
if (GetWindowLongPtr(hWnd, GWL_STYLE) & WS_POPUPWINDOW) {
str[0] = 0;
GetWindowTextU(hWnd, str, sizeof(str));
if (strcmp(str, title_str[0]) == 0) {
found = FALSE;
EnumChildWindows(hWnd, AlertPromptCallback, (LPARAM)&found);
if (found) {
SendMessage(hWnd, WM_COMMAND, (WPARAM)IDCANCEL, (LPARAM)0);
Log("###### Closed Windows format prompt #######");
}
}
}
}
}
BOOL SetAlertPromptHook(void)
{
if (ap_weh != NULL)
return TRUE; // No need to set again if active
ap_weh = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, NULL,
AlertPromptHook, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
return (ap_weh != NULL);
}
BOOL AlertSuppressInit(void)
{
BOOL bRet;
SetAlertPromptMessages();
bRet = SetAlertPromptHook();
Log("SetAlertPromptHook %s", bRet ? "SUCCESS" : "FAILED");
return TRUE;
}

View File

@@ -2,6 +2,7 @@
* DiskService.c
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
* Copyright (c) 2011-2021 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
@@ -26,6 +27,22 @@
#include "Ventoy2Disk.h"
#include "DiskService.h"
static CHAR g_WindowsDir[MAX_PATH] = {0};
const CHAR* DISK_GetWindowsDir(void)
{
if (g_WindowsDir[0] == 0)
{
GetEnvironmentVariableA("SystemRoot", g_WindowsDir, MAX_PATH);
if (g_WindowsDir[0] == 0)
{
sprintf_s(g_WindowsDir, MAX_PATH, "C:\\Windows");
}
}
return g_WindowsDir;
}
BOOL DISK_CleanDisk(int DriveIndex)
{
BOOL ret;
@@ -85,7 +102,7 @@ BOOL DISK_ChangeVtoyEFIAttr(int DriveIndex, UINT64 Offset, UINT64 Attr)
BOOL ret;
ret = VDS_ChangeVtoyEFIAttr(DriveIndex, Offset, Attr);
return ret;
}
@@ -118,29 +135,51 @@ typedef struct
PCHAR Output;
} TEXTOUTPUT, * PTEXTOUTPUT;
// Callback command types
typedef enum
{
PROGRESS,
DONEWITHSTRUCTURE,
UNKNOWN2,
UNKNOWN3,
UNKNOWN4,
UNKNOWN5,
INSUFFICIENTRIGHTS,
UNKNOWN7,
UNKNOWN8,
UNKNOWN9,
UNKNOWNA,
DONE,
UNKNOWNC,
UNKNOWND,
OUTPUT,
STRUCTUREPROGRESS
} CALLBACKCOMMAND;
/* Callback command types (some errorcode were filled from HPUSBFW V2.2.3 and their
designation from docs.microsoft.com/windows/win32/api/vds/nf-vds-ivdsvolumemf2-formatex */
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,
FCC_UNKNOWN15,
FCC_UNKNOWN16,
FCC_UNKNOWN17,
FCC_DEVICE_NOT_READY,
FCC_CHECKDISK_PROGRESS,
FCC_UNKNOWN1A,
FCC_UNKNOWN1B,
FCC_UNKNOWN1C,
FCC_UNKNOWN1D,
FCC_UNKNOWN1E,
FCC_UNKNOWN1F,
FCC_READ_ONLY_MODE,
FCC_UNKNOWN21,
FCC_UNKNOWN22,
FCC_UNKNOWN23,
FCC_UNKNOWN24,
FCC_ALIGNMENT_VIOLATION,
} FILE_SYSTEM_CALLBACK_COMMAND;
// FMIFS callback definition
typedef BOOLEAN(__stdcall* PFMIFSCALLBACK)(CALLBACKCOMMAND Command, DWORD SubAction, PVOID ActionInfo);
typedef BOOLEAN(__stdcall* PFMIFSCALLBACK)(FILE_SYSTEM_CALLBACK_COMMAND Command, DWORD SubAction, PVOID ActionInfo);
// Chkdsk command in FMIFS
@@ -167,36 +206,87 @@ typedef VOID(__stdcall* PFORMATEX)(PWCHAR DriveRoot,
DWORD ClusterSize,
PFMIFSCALLBACK Callback);
#define FP_FORCE 0x00000001
#define FP_QUICK 0x00000002
#define FP_COMPRESSION 0x00000004
#define FP_DUPLICATE_METADATA 0x00000008
#define FP_LARGE_FAT32 0x00010000
#define FP_NO_BOOT 0x00020000
#define FP_CREATE_PERSISTENCE_CONF 0x00040000
// FormatExCallback
static int g_dll_format_error = 0;
BOOLEAN __stdcall FormatExCallback(CALLBACKCOMMAND Command, DWORD Modifier, PVOID Argument)
BOOLEAN __stdcall FormatExCallback(FILE_SYSTEM_CALLBACK_COMMAND Command, DWORD Modifier, PVOID Argument)
{
PDWORD percent;
PBOOLEAN status;
switch (Command)
{
case PROGRESS:
switch (Command) {
case FCC_PROGRESS:
percent = (PDWORD)Argument;
Log("Format percent: %d \n", *percent);
Log("Format percent: %u%%", *percent);
break;
case OUTPUT:
case FCC_STRUCTURE_PROGRESS: // No progress on quick format
Log("Creating file system...");
break;
case DONE:
case FCC_DONE:
status = (PBOOLEAN)Argument;
if (*status == FALSE)
{
Log("Format error: %u ERROR_NOT_SUPPORTED=%u", LASTERR, ERROR_NOT_SUPPORTED);
g_dll_format_error = 1;
}
else
{
Log("Format Done");
}
break;
case FCC_DONE_WITH_STRUCTURE:
Log("Format FCC_DONE_WITH_STRUCTURE");
break;
case FCC_INCOMPATIBLE_FILE_SYSTEM:
Log("Incompatible File System");
break;
case FCC_ACCESS_DENIED:
Log("Access denied");
break;
case FCC_MEDIA_WRITE_PROTECTED:
Log("Media is write protected");
break;
case FCC_VOLUME_IN_USE:
Log("Volume is in use");
break;
case FCC_DEVICE_NOT_READY:
Log("The device is not ready");
break;
case FCC_CANT_QUICK_FORMAT:
Log("Cannot quick format this volume");
break;
case FCC_BAD_LABEL:
Log("Bad label");
break;
case FCC_OUTPUT:
Log("%s", ((PTEXTOUTPUT)Argument)->Output);
break;
case FCC_CLUSTER_SIZE_TOO_BIG:
case FCC_CLUSTER_SIZE_TOO_SMALL:
Log("Unsupported cluster size");
break;
case FCC_VOLUME_TOO_BIG:
case FCC_VOLUME_TOO_SMALL:
Log("Volume is too %s", (Command == FCC_VOLUME_TOO_BIG) ? "big" : "small");
break;
case FCC_NO_MEDIA_IN_DRIVE:
Log("No media in drive");
break;
case FCC_ALIGNMENT_VIOLATION:
Log("Partition start offset is not aligned to the cluster size");
break;
default:
Log("FormatExCallback: Received unhandled command 0x%02X - aborting", Command);
break;
}
return TRUE;
}
@@ -244,7 +334,7 @@ BOOL DLL_FormatVolume(char DriveLetter, int fs, DWORD ClusterSize)
g_dll_format_error = 0;
Log("Call FormatEx Function for %C: %s ClusterSize=%u(%uKB)", DriveLetter, GetVentoyFsFmtNameByTypeA(fs), ClusterSize, ClusterSize / 1024);
FormatEx(RootDirectory, media, Format, Label, TRUE, ClusterSize, FormatExCallback);
FormatEx(RootDirectory, media, Format, Label, FP_FORCE | FP_QUICK, ClusterSize, FormatExCallback);
FreeLibrary(ifsModule);
if (g_dll_format_error)
@@ -260,24 +350,30 @@ BOOL DLL_FormatVolume(char DriveLetter, int fs, DWORD ClusterSize)
BOOL DISK_FormatVolume(char DriveLetter, int fs, UINT64 VolumeSize)
{
int i;
DWORD ClusterSize = 0;
BOOL ret = FALSE;
FmtFunc astFmtFunc[] =
{
FMT_DEF(VDS_FormatVolume),
FMT_DEF(DLL_FormatVolume),
FMT_DEF(PSHELL_FormatVolume),
FMT_DEF(DSPT_FormatVolume),
FMT_DEF(CMD_FormatVolume),
{ NULL, NULL }
};
ClusterSize = (DWORD)GetClusterSize();
Log("DISK_FormatVolume %C:\\ %s VolumeSize=%llu ClusterSize=%u(%uKB)",
DriveLetter, GetVentoyFsNameByType(fs), (ULONGLONG)VolumeSize, ClusterSize, ClusterSize/1024);
DriveLetter, GetVentoyFsNameByType(fs), (ULONGLONG)VolumeSize, ClusterSize, ClusterSize / 1024);
ret = DLL_FormatVolume(DriveLetter, fs, ClusterSize);
if (!ret)
for (i = 0; astFmtFunc[i].formatFunc; i++)
{
ret = VDS_FormatVolume(DriveLetter, fs, ClusterSize);
if (!ret)
Log("%s ...", astFmtFunc[i].name);
ret = astFmtFunc[i].formatFunc(DriveLetter, fs, ClusterSize);
if (ret)
{
ret = DSPT_FormatVolume(DriveLetter, fs, ClusterSize);
if (!ret)
{
ret = PSHELL_FormatVolume(DriveLetter, fs, ClusterSize);
}
break;
}
}

View File

@@ -58,6 +58,8 @@ BOOL VDS_FormatVolume(char DriveLetter, int fs, DWORD ClusterSize);
BOOL DSPT_CleanDisk(int DriveIndex);
BOOL DSPT_FormatVolume(char DriveLetter, int fs, DWORD ClusterSize);
BOOL CMD_FormatVolume(char DriveLetter, int fs, DWORD ClusterSize);
//powershell.exe
BOOL PSHELL_CleanDisk(int DriveIndex);
BOOL PSHELL_DeleteVtoyEFIPartition(int DriveIndex, UINT64 EfiPartOffset);
@@ -66,11 +68,22 @@ BOOL PSHELL_ChangeVtoyEFI2Basic(int DriveIndex, UINT64 Offset);
BOOL PSHELL_ShrinkVolume(int DriveIndex, const char* VolumeGuid, CHAR DriveLetter, UINT64 OldBytes, UINT64 ReduceBytes);
BOOL PSHELL_FormatVolume(char DriveLetter, int fs, DWORD ClusterSize);
const CHAR* DISK_GetWindowsDir(void);
//
// Internel define
//
typedef BOOL(*FormatVolume_PF)(char DriveLetter, int fs, DWORD ClusterSize);
typedef struct FmtFunc
{
const char* name;
FormatVolume_PF formatFunc;
}FmtFunc;
#define FMT_DEF(func) { #func, func }
#endif

View File

@@ -30,7 +30,7 @@ STATIC BOOL IsDiskpartExist(void)
{
BOOL ret;
ret = IsFileExist("C:\\Windows\\system32\\diskpart.exe");
ret = IsFileExist("%s\\system32\\diskpart.exe", DISK_GetWindowsDir());
if (!ret)
{
Log("diskpart.exe not exist");
@@ -39,6 +39,20 @@ STATIC BOOL IsDiskpartExist(void)
return ret;
}
STATIC BOOL IsCmdExist(void)
{
BOOL ret;
ret = IsFileExist("%s\\system32\\cmd.exe", DISK_GetWindowsDir());
if (!ret)
{
Log("cmd.exe not exist");
}
return ret;
}
STATIC BOOL DSPT_CommProc(const char *Cmd)
{
CHAR CmdBuf[MAX_PATH];
@@ -71,6 +85,29 @@ STATIC BOOL DSPT_CommProc(const char *Cmd)
return TRUE;
}
STATIC BOOL CMD_CommProc(char* Cmd)
{
STARTUPINFOA Si;
PROCESS_INFORMATION Pi;
GetStartupInfoA(&Si);
Si.dwFlags |= STARTF_USESHOWWINDOW;
Si.wShowWindow = SW_HIDE;
Log("CreateProcess <%s>", Cmd);
CreateProcessA(NULL, Cmd, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
Log("Wair process ...");
WaitForSingleObject(Pi.hProcess, INFINITE);
Log("Process finished...");
CHECK_CLOSE_HANDLE(Pi.hProcess);
CHECK_CLOSE_HANDLE(Pi.hThread);
return TRUE;
}
BOOL DSPT_CleanDisk(int DriveIndex)
{
CHAR CmdBuf[128];
@@ -90,6 +127,7 @@ BOOL DSPT_FormatVolume(char DriveLetter, int fs, DWORD ClusterSize)
{
const char* fsname = NULL;
CHAR CmdBuf[256];
CHAR FsName[128];
Log("FormatVolumeByDiskpart <%C:>", DriveLetter);
@@ -108,8 +146,72 @@ BOOL DSPT_FormatVolume(char DriveLetter, int fs, DWORD ClusterSize)
{
sprintf_s(CmdBuf, sizeof(CmdBuf), "select volume %C:\r\nformat FS=%s LABEL=Ventoy QUICK OVERRIDE\r\n", DriveLetter, fsname);
}
Log("Diskpart cmd:<%s>", CmdBuf);
return DSPT_CommProc(CmdBuf);
DSPT_CommProc(CmdBuf);
sprintf_s(CmdBuf, sizeof(CmdBuf), "%C:\\", DriveLetter);
GetVolumeInformationA(CmdBuf, NULL, 0, NULL, NULL, NULL, FsName, sizeof(FsName));
VentoyStringToUpper(FsName);
Log("New fs name after run diskpart:<%s>", FsName);
if (strcmp(FsName, fsname) == 0)
{
Log("FormatVolumeByDiskpart <%C:> SUCCESS", DriveLetter);
return TRUE;
}
else
{
Log("FormatVolumeByDiskpart <%C:> FAILED", DriveLetter);
return FALSE;
}
}
BOOL CMD_FormatVolume(char DriveLetter, int fs, DWORD ClusterSize)
{
const char* fsname = NULL;
CHAR CmdBuf[256];
CHAR FsName[128];
Log("FormatVolumeByCmd <%C:>", DriveLetter);
if (!IsCmdExist())
{
return FALSE;
}
fsname = GetVentoyFsFmtNameByTypeA(fs);
if (ClusterSize > 0)
{
sprintf_s(CmdBuf, sizeof(CmdBuf), "cmd.exe /c \"echo Y|format %C: /V:Ventoy /fs:%s /q /A:%u /X\"", DriveLetter, fsname, ClusterSize);
}
else
{
sprintf_s(CmdBuf, sizeof(CmdBuf), "cmd.exe /c \"echo Y|format %C: /V:Ventoy /fs:%s /q /X\"", DriveLetter, fsname);
}
Log("Cmd.exe <%s>", CmdBuf);
CMD_CommProc(CmdBuf);
sprintf_s(CmdBuf, sizeof(CmdBuf), "%C:\\", DriveLetter);
GetVolumeInformationA(CmdBuf, NULL, 0, NULL, NULL, NULL, FsName, sizeof(FsName));
VentoyStringToUpper(FsName);
Log("New fs name after run cmd.exe:<%s>", FsName);
if (strcmp(FsName, fsname) == 0)
{
Log("FormatVolumeByCmd <%C:> SUCCESS", DriveLetter);
return TRUE;
}
else
{
Log("FormatVolumeByCmd <%C:> FAILED", DriveLetter);
return FALSE;
}
}

View File

@@ -29,15 +29,9 @@
STATIC BOOL IsPowershellExist(void)
{
BOOL ret;
BOOL ret;
if (!IsWindows8OrGreater())
{
Log("This is before Windows8 powershell disk not supported.");
return FALSE;
}
ret = IsFileExist("C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe");
ret = IsFileExist("%s\\system32\\WindowsPowerShell\\v1.0\\powershell.exe", DISK_GetWindowsDir());
if (!ret)
{
Log("powershell.exe not exist");
@@ -261,6 +255,7 @@ BOOL PSHELL_FormatVolume(char DriveLetter, int fs, DWORD ClusterSize)
BOOL ret;
const char* fsname = NULL;
CHAR CmdBuf[512];
CHAR FsName[128];
fsname = GetVentoyFsFmtNameByTypeA(fs);
@@ -279,5 +274,26 @@ BOOL PSHELL_FormatVolume(char DriveLetter, int fs, DWORD ClusterSize)
ret = PSHELL_CommProc(CmdBuf);
Log("PSHELL_FormatVolume %C: ret:%d (%s)", DriveLetter, ret, ret ? "SUCCESS" : "FAIL");
return ret;
if (!ret)
{
return FALSE;
}
sprintf_s(CmdBuf, sizeof(CmdBuf), "%C:\\", DriveLetter);
GetVolumeInformationA(CmdBuf, NULL, 0, NULL, NULL, NULL, FsName, sizeof(FsName));
VentoyStringToUpper(FsName);
Log("New fs name after run PSHELL:<%s>", FsName);
if (strcmp(FsName, fsname) == 0)
{
Log("PSHELL_FormatVolume <%C:> SUCCESS", DriveLetter);
return TRUE;
}
else
{
Log("PSHELL_FormatVolume <%C:> FAILED", DriveLetter);
return FALSE;
}
}

View File

@@ -92,6 +92,8 @@ typedef enum STR_ID
STR_PART_CLUSTER, //52
STR_PART_CLUSTER_DEFAULT, //53
STR_DONATE, //54
STR_ID_MAX
}STR_ID;

View File

@@ -725,12 +725,13 @@ int VentoyProcSecureBoot(BOOL SecureBoot)
fl_fclose(file);
Log("Now delete all efi files ...");
fl_remove("/EFI/BOOT/BOOTX64.EFI");
fl_remove("/EFI/BOOT/grubx64.efi");
fl_remove("/EFI/BOOT/BOOTX64.EFI");
fl_remove("/EFI/BOOT/grubx64.efi");
fl_remove("/EFI/BOOT/grubx64_real.efi");
fl_remove("/EFI/BOOT/MokManager.efi");
fl_remove("/EFI/BOOT/mmx64.efi");
fl_remove("/ENROLL_THIS_KEY_IN_MOKMANAGER.cer");
fl_remove("/EFI/BOOT/grub.efi");
file = fl_fopen("/EFI/BOOT/BOOTX64.EFI", "wb");
Log("Open bootx64 efi file %p ", file);
@@ -1698,6 +1699,7 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle, int TryId)
int i;
int rc = 0;
int state = 0;
BOOL ReformatOK;
HANDLE hDrive;
DWORD dwSize;
BOOL bRet;
@@ -1824,15 +1826,15 @@ int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle, int TryId)
}
else
{
Log("Formatting part1 exFAT ...");
if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))
CHAR TmpBuffer[512] = { 0 };
Log("Zero part1 file system ...");
SetFilePointer(hDrive, VENTOY_PART1_START_SECTOR * 512, NULL, FILE_BEGIN);
for (i = 0; i < 32; i++)
{
Log("FormatPart1exFAT failed.");
rc = 1;
goto End;
WriteFile(hDrive, TmpBuffer, 512, &dwSize, NULL);
}
}
PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);
Log("Writing part2 FAT img ...");
@@ -1956,6 +1958,12 @@ End:
}
}
// close handle, or it will deny reformat
Log("Close handle ...");
CHECK_CLOSE_HANDLE(hDrive);
ReformatOK = FALSE;
if (state)
{
if (LargeFAT32)
@@ -1963,22 +1971,34 @@ End:
Log("No need to reformat for large FAT32");
pPhyDrive->VentoyFsClusterSize = GetVolumeClusterSize(MountDrive);
}
else if (DISK_FormatVolume(MountDrive, GetVentoyFsType(), Part1SectorCount * 512))
{
Log("Reformat %C:\\ to %s SUCCESS", MountDrive, GetVentoyFsName());
pPhyDrive->VentoyFsClusterSize = GetVolumeClusterSize(MountDrive);
if ((GetVentoyFsType() != VTOY_FS_UDF) && (pPhyDrive->VentoyFsClusterSize < 2048))
{
for (i = 0; i < 10; i++)
{
Log("### Invalid cluster size %d ###", pPhyDrive->VentoyFsClusterSize);
}
}
}
else
{
Log("Reformat %C:\\ to %s FAILED", MountDrive, GetVentoyFsName());
bRet = DISK_FormatVolume(MountDrive, GetVentoyFsType(), Part1SectorCount * 512);
for (i = 0; bRet == FALSE && i < 2; i++)
{
Log("Wait and retry reformat ...");
Sleep(1000);
bRet = DISK_FormatVolume(MountDrive, GetVentoyFsType(), Part1SectorCount * 512);
}
if (bRet)
{
ReformatOK = TRUE;
Log("Reformat %C:\\ to %s SUCCESS", MountDrive, GetVentoyFsName());
pPhyDrive->VentoyFsClusterSize = GetVolumeClusterSize(MountDrive);
if ((GetVentoyFsType() != VTOY_FS_UDF) && (pPhyDrive->VentoyFsClusterSize < 2048))
{
for (i = 0; i < 10; i++)
{
Log("### Invalid cluster size %d ###", pPhyDrive->VentoyFsClusterSize);
}
}
}
else
{
Log("Reformat %C:\\ to %s FAILED", MountDrive, GetVentoyFsName());
}
}
}
else
@@ -1986,6 +2006,30 @@ End:
Log("Can not reformat %s to %s", DriveName, GetVentoyFsName());
}
if (!ReformatOK)
{
Log("Format to exfat with built-in algorithm");
hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
if (hDrive == INVALID_HANDLE_VALUE)
{
Log("Failed to GetPhysicalHandle for write.");
}
else
{
if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))
{
Log("FormatPart1exFAT SUCCESS.");
}
else
{
Log("FormatPart1exFAT FAILED.");
}
CHECK_CLOSE_HANDLE(hDrive);
}
}
Log("OK\n");
}
else
@@ -2002,14 +2046,15 @@ End:
Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
Log("###### [Error:] Virtual Disk Service (VDS) Unavailable ######");
}
CHECK_CLOSE_HANDLE(hDrive);
}
if (pGptInfo)
{
free(pGptInfo);
}
CHECK_CLOSE_HANDLE(hDrive);
return rc;
}

View File

@@ -1124,5 +1124,14 @@ int GetPhysicalDriveCount(void)
return Count;
}
void VentoyStringToUpper(CHAR* str)
{
while (str && *str)
{
if (*str >= 'a' && *str <= 'z')
{
*str = toupper(*str);
}
str++;
}
}

View File

@@ -209,7 +209,7 @@ typedef enum PROGRESS_POINT
PT_MOUNT_VOLUME,
PT_REFORMAT_START,
PT_REFORMAT_FINISH = PT_REFORMAT_START + 2,
PT_REFORMAT_FINISH = PT_REFORMAT_START + 16,
PT_FINISH
}PROGRESS_POINT;
@@ -355,6 +355,8 @@ void InitComboxCtrl(HWND hWnd, int PhyDrive);
int disk_io_is_write_error(void);
void disk_io_reset_write_error(void);
const char* GUID2String(void* guid, char* buf, int len);
void VentoyStringToUpper(CHAR* str);
BOOL AlertSuppressInit(void);
#define VTSI_SUPPORT 1

View File

@@ -342,6 +342,7 @@
</Manifest>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="AlertSuppress.c" />
<ClCompile Include="crc32.c" />
<ClCompile Include="DiskService.c" />
<ClCompile Include="DiskService_diskpart.c" />

View File

@@ -96,6 +96,9 @@
<ClCompile Include="YesDialog.c">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="AlertSuppress.c">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Ventoy2Disk.h">

Binary file not shown.

Binary file not shown.