* DiskService.c\r
*\r
* Copyright (c) 2021, longpanda <admin@ventoy.net>\r
+* Copyright (c) 2011-2021 Pete Batard <pete@akeo.ie>\r
*\r
* This program is free software; you can redistribute it and/or\r
* modify it under the terms of the GNU General Public License as\r
#include "Ventoy2Disk.h"\r
#include "DiskService.h"\r
\r
+static CHAR g_WindowsDir[MAX_PATH] = {0};\r
+\r
+const CHAR* DISK_GetWindowsDir(void)\r
+{\r
+ if (g_WindowsDir[0] == 0)\r
+ {\r
+ GetEnvironmentVariableA("SystemRoot", g_WindowsDir, MAX_PATH);\r
+ if (g_WindowsDir[0] == 0)\r
+ {\r
+ sprintf_s(g_WindowsDir, MAX_PATH, "C:\\Windows");\r
+ }\r
+ }\r
+\r
+ return g_WindowsDir;\r
+}\r
+\r
BOOL DISK_CleanDisk(int DriveIndex)\r
{\r
BOOL ret;\r
BOOL ret;\r
\r
ret = VDS_ChangeVtoyEFIAttr(DriveIndex, Offset, Attr);\r
- \r
+\r
return ret;\r
}\r
\r
return ret;\r
}\r
\r
+\r
+\r
+// Output command\r
+typedef struct\r
+{\r
+ DWORD Lines;\r
+ PCHAR Output;\r
+} TEXTOUTPUT, * PTEXTOUTPUT;\r
+\r
+/* Callback command types (some errorcode were filled from HPUSBFW V2.2.3 and their\r
+ designation from docs.microsoft.com/windows/win32/api/vds/nf-vds-ivdsvolumemf2-formatex */\r
+typedef enum {\r
+ FCC_PROGRESS,\r
+ FCC_DONE_WITH_STRUCTURE,\r
+ FCC_UNKNOWN2,\r
+ FCC_INCOMPATIBLE_FILE_SYSTEM,\r
+ FCC_UNKNOWN4,\r
+ FCC_UNKNOWN5,\r
+ FCC_ACCESS_DENIED,\r
+ FCC_MEDIA_WRITE_PROTECTED,\r
+ FCC_VOLUME_IN_USE,\r
+ FCC_CANT_QUICK_FORMAT,\r
+ FCC_UNKNOWNA,\r
+ FCC_DONE,\r
+ FCC_BAD_LABEL,\r
+ FCC_UNKNOWND,\r
+ FCC_OUTPUT,\r
+ FCC_STRUCTURE_PROGRESS,\r
+ FCC_CLUSTER_SIZE_TOO_SMALL,\r
+ FCC_CLUSTER_SIZE_TOO_BIG,\r
+ FCC_VOLUME_TOO_SMALL,\r
+ FCC_VOLUME_TOO_BIG,\r
+ FCC_NO_MEDIA_IN_DRIVE,\r
+ FCC_UNKNOWN15,\r
+ FCC_UNKNOWN16,\r
+ FCC_UNKNOWN17,\r
+ FCC_DEVICE_NOT_READY,\r
+ FCC_CHECKDISK_PROGRESS,\r
+ FCC_UNKNOWN1A,\r
+ FCC_UNKNOWN1B,\r
+ FCC_UNKNOWN1C,\r
+ FCC_UNKNOWN1D,\r
+ FCC_UNKNOWN1E,\r
+ FCC_UNKNOWN1F,\r
+ FCC_READ_ONLY_MODE,\r
+ FCC_UNKNOWN21,\r
+ FCC_UNKNOWN22,\r
+ FCC_UNKNOWN23,\r
+ FCC_UNKNOWN24,\r
+ FCC_ALIGNMENT_VIOLATION,\r
+} FILE_SYSTEM_CALLBACK_COMMAND;\r
+\r
+// FMIFS callback definition\r
+typedef BOOLEAN(__stdcall* PFMIFSCALLBACK)(FILE_SYSTEM_CALLBACK_COMMAND Command, DWORD SubAction, PVOID ActionInfo);\r
+\r
+\r
+// Chkdsk command in FMIFS\r
+typedef VOID(__stdcall* PCHKDSK)(PWCHAR DriveRoot,\r
+ PWCHAR Format,\r
+ BOOL CorrectErrors,\r
+ BOOL Verbose,\r
+ BOOL CheckOnlyIfDirty,\r
+ BOOL ScanDrive,\r
+ PVOID Unused2,\r
+ PVOID Unused3,\r
+ PFMIFSCALLBACK Callback);\r
+\r
+\r
+// media flags\r
+#define FMIFS_HARDDISK 0xC\r
+#define FMIFS_FLOPPY 0x8\r
+// Format command in FMIFS\r
+typedef VOID(__stdcall* PFORMATEX)(PWCHAR DriveRoot,\r
+ DWORD MediaFlag,\r
+ PWCHAR Format,\r
+ PWCHAR Label,\r
+ BOOL QuickFormat,\r
+ DWORD ClusterSize,\r
+ PFMIFSCALLBACK Callback);\r
+\r
+#define FP_FORCE 0x00000001\r
+#define FP_QUICK 0x00000002\r
+#define FP_COMPRESSION 0x00000004\r
+#define FP_DUPLICATE_METADATA 0x00000008\r
+#define FP_LARGE_FAT32 0x00010000\r
+#define FP_NO_BOOT 0x00020000\r
+#define FP_CREATE_PERSISTENCE_CONF 0x00040000\r
+\r
+// FormatExCallback\r
+static int g_dll_format_error = 0;\r
+BOOLEAN __stdcall FormatExCallback(FILE_SYSTEM_CALLBACK_COMMAND Command, DWORD Modifier, PVOID Argument)\r
+{\r
+ PDWORD percent;\r
+ PBOOLEAN status;\r
+\r
+ switch (Command) {\r
+ case FCC_PROGRESS:\r
+ percent = (PDWORD)Argument;\r
+ Log("Format percent: %u%%", *percent);\r
+ break;\r
+ case FCC_STRUCTURE_PROGRESS: // No progress on quick format\r
+ Log("Creating file system...");\r
+ break;\r
+ case FCC_DONE:\r
+ status = (PBOOLEAN)Argument;\r
+ if (*status == FALSE)\r
+ {\r
+ Log("Format error: %u ERROR_NOT_SUPPORTED=%u", LASTERR, ERROR_NOT_SUPPORTED);\r
+ g_dll_format_error = 1;\r
+ }\r
+ else\r
+ {\r
+ Log("Format Done");\r
+ }\r
+ break;\r
+ case FCC_DONE_WITH_STRUCTURE:\r
+ Log("Format FCC_DONE_WITH_STRUCTURE");\r
+ break;\r
+ case FCC_INCOMPATIBLE_FILE_SYSTEM:\r
+ Log("Incompatible File System");\r
+ break;\r
+ case FCC_ACCESS_DENIED:\r
+ Log("Access denied");\r
+ break;\r
+ case FCC_MEDIA_WRITE_PROTECTED:\r
+ Log("Media is write protected");\r
+ break;\r
+ case FCC_VOLUME_IN_USE:\r
+ Log("Volume is in use");\r
+ break;\r
+ case FCC_DEVICE_NOT_READY:\r
+ Log("The device is not ready");\r
+ break;\r
+ case FCC_CANT_QUICK_FORMAT:\r
+ Log("Cannot quick format this volume");\r
+ break;\r
+ case FCC_BAD_LABEL:\r
+ Log("Bad label");\r
+ break;\r
+ case FCC_OUTPUT:\r
+ Log("%s", ((PTEXTOUTPUT)Argument)->Output);\r
+ break;\r
+ case FCC_CLUSTER_SIZE_TOO_BIG:\r
+ case FCC_CLUSTER_SIZE_TOO_SMALL:\r
+ Log("Unsupported cluster size");\r
+ break;\r
+ case FCC_VOLUME_TOO_BIG:\r
+ case FCC_VOLUME_TOO_SMALL:\r
+ Log("Volume is too %s", (Command == FCC_VOLUME_TOO_BIG) ? "big" : "small");\r
+ break;\r
+ case FCC_NO_MEDIA_IN_DRIVE:\r
+ Log("No media in drive");\r
+ break;\r
+ case FCC_ALIGNMENT_VIOLATION:\r
+ Log("Partition start offset is not aligned to the cluster size");\r
+ break;\r
+ default:\r
+ Log("FormatExCallback: Received unhandled command 0x%02X - aborting", Command);\r
+ break;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+\r
+BOOL DLL_FormatVolume(char DriveLetter, int fs, DWORD ClusterSize)\r
+{\r
+ PWCHAR Label = L"Ventoy";\r
+ PWCHAR Format = NULL;\r
+ WCHAR RootDirectory[MAX_PATH] = { 0 };\r
+ HMODULE ifsModule;\r
+ PFORMATEX FormatEx;\r
+\r
+ ifsModule = LoadLibraryA("fmifs.dll");\r
+ if (NULL == ifsModule)\r
+ {\r
+ Log("LoadLibrary fmifs.dll failed %u", LASTERR);\r
+ return FALSE;\r
+ }\r
+\r
+ Log("Find ifsModule");\r
+\r
+ FormatEx = (PFORMATEX)GetProcAddress(ifsModule, "FormatEx");\r
+ if (FormatEx == NULL)\r
+ {\r
+ Log("Failed to get FormatEx handler\n");\r
+ return FALSE;\r
+ }\r
+ Log("Find FormatEx=%p", FormatEx);\r
+\r
+ RootDirectory[0] = DriveLetter;\r
+ RootDirectory[1] = L':';\r
+ RootDirectory[2] = L'\\';\r
+ RootDirectory[3] = (WCHAR)0;\r
+\r
+ DWORD media;\r
+ DWORD driveType;\r
+ driveType = GetDriveTypeW(RootDirectory);\r
+ if (driveType != DRIVE_FIXED)\r
+ media = FMIFS_FLOPPY;\r
+ if (driveType == DRIVE_FIXED)\r
+ media = FMIFS_HARDDISK;\r
+\r
+ Format = GetVentoyFsFmtNameByTypeW(fs);\r
+\r
+ g_dll_format_error = 0;\r
+\r
+ Log("Call FormatEx Function for %C: %s ClusterSize=%u(%uKB)", DriveLetter, GetVentoyFsFmtNameByTypeA(fs), ClusterSize, ClusterSize / 1024);\r
+ FormatEx(RootDirectory, media, Format, Label, FP_FORCE | FP_QUICK, ClusterSize, FormatExCallback);\r
+ FreeLibrary(ifsModule);\r
+\r
+ if (g_dll_format_error)\r
+ {\r
+ Log("Format failed by DLL");\r
+ return FALSE;\r
+ }\r
+\r
+ Log("Format success by DLL");\r
+ return TRUE;\r
+}\r
+\r
+\r
+BOOL DISK_FormatVolume(char DriveLetter, int fs, UINT64 VolumeSize)\r
+{\r
+ int i;\r
+ DWORD ClusterSize = 0;\r
+ BOOL ret = FALSE;\r
+ FmtFunc astFmtFunc[] =\r
+ {\r
+ FMT_DEF(VDS_FormatVolume),\r
+ FMT_DEF(DLL_FormatVolume),\r
+ FMT_DEF(PSHELL_FormatVolume),\r
+ FMT_DEF(DSPT_FormatVolume),\r
+ FMT_DEF(CMD_FormatVolume),\r
+ { NULL, NULL }\r
+ };\r
+\r
+ ClusterSize = (DWORD)GetClusterSize();\r
+ Log("DISK_FormatVolume %C:\\ %s VolumeSize=%llu ClusterSize=%u(%uKB)",\r
+ DriveLetter, GetVentoyFsNameByType(fs), (ULONGLONG)VolumeSize, ClusterSize, ClusterSize / 1024);\r
+\r
+ for (i = 0; astFmtFunc[i].formatFunc; i++)\r
+ {\r
+ Log("%s ...", astFmtFunc[i].name);\r
+ ret = astFmtFunc[i].formatFunc(DriveLetter, fs, ClusterSize);\r
+ if (ret)\r
+ {\r
+ break;\r
+ }\r
+ }\r
+\r
+ return ret;\r
+}\r