]> glassweightruler.freedombox.rocks Git - Ventoy.git/blobdiff - Ventoy2Disk/Ventoy2Disk/DiskService.c
Fix the media missing issue when boot UOS server ISO file.
[Ventoy.git] / Ventoy2Disk / Ventoy2Disk / DiskService.c
index 4272d6fef8438c613597073b35b1855efa806787..2eebde0d0e0d63b255682b7138cc627f4e31ef9c 100644 (file)
@@ -2,6 +2,7 @@
 * 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
@@ -85,7 +102,7 @@ BOOL DISK_ChangeVtoyEFIAttr(int DriveIndex, UINT64 Offset, UINT64 Attr)
        BOOL ret;\r
 \r
        ret = VDS_ChangeVtoyEFIAttr(DriveIndex, Offset, Attr);\r
-       \r
+\r
        return ret;\r
 }\r
 \r
@@ -109,3 +126,256 @@ BOOL DISK_ShrinkVolume(int DriveIndex, const char* VolumeGuid, CHAR DriveLetter,
        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