1 /******************************************************************************
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 #include <VersionHelpers.h>
29 #include "fat_filelib.h"
31 static ventoy_os_param g_os_param
;
32 static ventoy_windows_data g_windows_data
;
33 static UINT8 g_os_param_reserved
[32];
34 static INT g_system_bit
= VTOY_BIT
;
35 static ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
36 static HANDLE g_vtoylog_mutex
= NULL
;
37 static HANDLE g_vtoyins_mutex
= NULL
;
39 static BOOL g_wimboot_mode
= FALSE
;
41 static DWORD g_vtoy_disk_drive
;
43 static CHAR g_prog_full_path
[MAX_PATH
];
44 static CHAR g_prog_dir
[MAX_PATH
];
45 static CHAR g_prog_name
[MAX_PATH
];
47 #define VTOY_PECMD_PATH "X:\\Windows\\system32\\ventoy\\PECMD.EXE"
48 #define ORG_PECMD_PATH "X:\\Windows\\system32\\PECMD.EXE"
49 #define ORG_PECMD_BK_PATH "X:\\Windows\\system32\\VTOYJUMP.EXE"
51 #define WIMBOOT_FILE "X:\\Windows\\system32\\vtoy_wimboot"
52 #define WIMBOOT_DONE "X:\\Windows\\system32\\vtoy_wimboot_done"
54 #define AUTO_RUN_BAT "X:\\VentoyAutoRun.bat"
55 #define AUTO_RUN_LOG "X:\\VentoyAutoRun.log"
57 #define VTOY_AUTO_FILE "X:\\_vtoy_auto_install"
59 #define LOG_FILE "X:\\Windows\\system32\\ventoy.log"
60 #define MUTEX_LOCK(hmutex) if (hmutex != NULL) LockStatus = WaitForSingleObject(hmutex, INFINITE)
61 #define MUTEX_UNLOCK(hmutex) if (hmutex != NULL && WAIT_OBJECT_0 == LockStatus) ReleaseMutex(hmutex)
63 #define BREAK() BreakAndLaunchCmd(__LINE__)
65 static void BreakAndLaunchCmd(int line
)
68 PROCESS_INFORMATION Pi
;
70 Log("Break at line:%d", line
);
73 Si
.dwFlags
|= STARTF_USESHOWWINDOW
;
74 Si
.wShowWindow
= SW_NORMAL
;
76 CreateProcessA(NULL
, "cmd.exe", NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
77 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
80 static const char * GetFileNameInPath(const char *fullpath
)
84 if (strstr(fullpath
, ":"))
86 for (i
= (int)strlen(fullpath
); i
> 0; i
--)
88 if (fullpath
[i
- 1] == '/' || fullpath
[i
- 1] == '\\')
98 static int split_path_name(char *fullpath
, char *dir
, char *name
)
103 Pos
= (CHAR
*)GetFileNameInPath(fullpath
);
105 strcpy_s(name
, MAX_PATH
, Pos
);
109 strcpy_s(dir
, MAX_PATH
, fullpath
);
115 static void TrimString(CHAR
*String
, BOOL TrimLeft
)
119 size_t Len
= strlen(String
);
123 if (String
[Len
- 1] != ' ' && String
[Len
- 1] != '\t')
133 while (*Pos1
== ' ' || *Pos1
== '\t')
148 static int VentoyProcessRunCmd(const char *Fmt
, ...)
153 PROCESS_INFORMATION Pi
;
154 char szBuf
[1024] = { 0 };
157 Len
+= vsnprintf_s(szBuf
+ Len
, sizeof(szBuf
)-Len
, sizeof(szBuf
)-Len
, Fmt
, Arg
);
160 GetStartupInfoA(&Si
);
161 Si
.dwFlags
|= STARTF_USESHOWWINDOW
;
162 Si
.wShowWindow
= SW_HIDE
;
164 Log("Process Run: <%s>", szBuf
);
165 CreateProcessA(NULL
, szBuf
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
166 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
171 static CHAR
VentoyGetFirstFreeDriveLetter(BOOL Reverse
)
177 Drives
= GetLogicalDrives();
181 for (i
= 25; i
>= 2; i
--)
183 if (0 == (Drives
& (1 << i
)))
192 for (i
= 2; i
< 26; i
++)
194 if (0 == (Drives
& (1 << i
)))
202 Log("FirstFreeDriveLetter %u %C:", Reverse
, Letter
);
206 void Log(const char *Fmt
, ...)
213 DWORD LockStatus
= 0;
214 DWORD PID
= GetCurrentProcessId();
217 Len
+= sprintf_s(szBuf
, sizeof(szBuf
),
218 "[%4d/%02d/%02d %02d:%02d:%02d.%03d] [%u] ",
219 Sys
.wYear
, Sys
.wMonth
, Sys
.wDay
,
220 Sys
.wHour
, Sys
.wMinute
, Sys
.wSecond
,
221 Sys
.wMilliseconds
, PID
);
224 Len
+= vsnprintf_s(szBuf
+ Len
, sizeof(szBuf
)-Len
, sizeof(szBuf
)-Len
, Fmt
, Arg
);
227 MUTEX_LOCK(g_vtoylog_mutex
);
229 fopen_s(&File
, LOG_FILE
, "a+");
232 fwrite(szBuf
, 1, Len
, File
);
233 fwrite("\n", 1, 1, File
);
237 MUTEX_UNLOCK(g_vtoylog_mutex
);
241 static int LoadNtDriver(const char *DrvBinPath
)
247 SC_HANDLE hServiceMgr
;
249 char name
[256] = { 0 };
251 for (i
= (int)strlen(DrvBinPath
) - 1; i
>= 0; i
--)
253 if (DrvBinPath
[i
] == '\\' || DrvBinPath
[i
] == '/')
255 sprintf_s(name
, sizeof(name
), "%s", DrvBinPath
+ i
+ 1);
260 Log("Load NT driver: %s %s", DrvBinPath
, name
);
262 hServiceMgr
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_ALL_ACCESS
);
263 if (hServiceMgr
== NULL
)
265 Log("OpenSCManager failed Error:%u", GetLastError());
269 Log("OpenSCManager OK");
271 hService
= CreateServiceA(hServiceMgr
,
275 SERVICE_KERNEL_DRIVER
,
276 SERVICE_DEMAND_START
,
277 SERVICE_ERROR_NORMAL
,
279 NULL
, NULL
, NULL
, NULL
, NULL
);
280 if (hService
== NULL
)
282 Status
= GetLastError();
283 if (Status
!= ERROR_IO_PENDING
&& Status
!= ERROR_SERVICE_EXISTS
)
285 Log("CreateService failed v %u", Status
);
286 CloseServiceHandle(hServiceMgr
);
290 hService
= OpenServiceA(hServiceMgr
, name
, SERVICE_ALL_ACCESS
);
291 if (hService
== NULL
)
293 Log("OpenService failed %u", Status
);
294 CloseServiceHandle(hServiceMgr
);
299 Log("CreateService imdisk OK");
301 Ret
= StartServiceA(hService
, 0, NULL
);
304 Log("StartService OK");
308 Status
= GetLastError();
309 if (Status
== ERROR_SERVICE_ALREADY_RUNNING
)
315 Log("StartService error %u", Status
);
320 CloseServiceHandle(hService
);
321 CloseServiceHandle(hServiceMgr
);
323 Log("Load NT driver %s", rc
? "failed" : "success");
328 static int ReadWholeFile2Buf(const char *Fullpath
, void **Data
, DWORD
*Size
)
336 Log("ReadWholeFile2Buf <%s>", Fullpath
);
338 Handle
= CreateFileA(Fullpath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
339 if (Handle
== INVALID_HANDLE_VALUE
)
341 Log("Could not open the file<%s>, error:%u", Fullpath
, GetLastError());
345 FileSize
= SetFilePointer(Handle
, 0, NULL
, FILE_END
);
347 Buffer
= malloc(FileSize
);
350 Log("Failed to alloc memory size:%u", FileSize
);
354 SetFilePointer(Handle
, 0, NULL
, FILE_BEGIN
);
355 if (!ReadFile(Handle
, Buffer
, FileSize
, &dwSize
, NULL
))
357 Log("ReadFile failed, dwSize:%u error:%u", dwSize
, GetLastError());
364 Log("Success read file size:%u", FileSize
);
369 SAFE_CLOSE_HANDLE(Handle
);
374 static BOOL
CheckPeHead(BYTE
*Buffer
, DWORD Size
, DWORD Offset
)
379 ventoy_windows_data
*pdata
= NULL
;
381 Head
= Buffer
+ Offset
;
382 pdata
= (ventoy_windows_data
*)Head
;
383 Head
+= sizeof(ventoy_windows_data
);
385 if (pdata
->auto_install_script
[0] && pdata
->auto_install_len
> 0)
387 End
= Offset
+ sizeof(ventoy_windows_data
) + pdata
->auto_install_len
+ 60;
390 Head
+= pdata
->auto_install_len
;
394 if (Head
[0] != 'M' || Head
[1] != 'Z')
399 PeOffset
= *(UINT32
*)(Head
+ 60);
400 if (*(UINT32
*)(Head
+ PeOffset
) != 0x00004550)
409 static BOOL
CheckOsParam(ventoy_os_param
*param
)
414 if (memcmp(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
)))
419 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
421 Sum
+= *((BYTE
*)param
+ i
);
429 if (param
->vtoy_img_location_addr
% 4096)
437 static int SaveBuffer2File(const char *Fullpath
, void *Buffer
, DWORD Length
)
443 Log("SaveBuffer2File <%s> len:%u", Fullpath
, Length
);
445 Handle
= CreateFileA(Fullpath
, GENERIC_READ
| GENERIC_WRITE
,
446 FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, CREATE_NEW
, 0, 0);
447 if (Handle
== INVALID_HANDLE_VALUE
)
449 Log("Could not create new file, error:%u", GetLastError());
453 WriteFile(Handle
, Buffer
, Length
, &dwSize
, NULL
);
458 SAFE_CLOSE_HANDLE(Handle
);
463 static int IsUTF8Encode(const char *src
)
466 const UCHAR
*Byte
= (const UCHAR
*)src
;
468 for (i
= 0; i
< MAX_PATH
&& Byte
[i
]; i
++)
479 static int Utf16ToUtf8(const WCHAR
*src
, char *dst
)
484 len
= (int)wcslen(src
) + 1;
485 size
= WideCharToMultiByte(CP_UTF8
, 0, src
, len
, NULL
, 0, NULL
, NULL
);
486 return WideCharToMultiByte(CP_UTF8
, 0, src
, len
, dst
, size
, NULL
, NULL
);
489 static int Utf8ToUtf16(const char* src
, WCHAR
* dst
)
491 int size
= MultiByteToWideChar(CP_UTF8
, 0, src
, -1, dst
, 0);
492 return MultiByteToWideChar(CP_UTF8
, 0, src
, -1, dst
, size
+ 1);
495 static BOOL
IsDirExist(const char *Fmt
, ...)
500 CHAR FilePathA
[MAX_PATH
];
501 WCHAR FilePathW
[MAX_PATH
];
504 vsnprintf_s(FilePathA
, sizeof(FilePathA
), sizeof(FilePathA
), Fmt
, Arg
);
507 UTF8
= IsUTF8Encode(FilePathA
);
511 Utf8ToUtf16(FilePathA
, FilePathW
);
512 Attr
= GetFileAttributesW(FilePathW
);
516 Attr
= GetFileAttributesA(FilePathA
);
519 if (Attr
!= INVALID_FILE_ATTRIBUTES
&& (Attr
& FILE_ATTRIBUTE_DIRECTORY
))
527 static BOOL
IsFileExist(const char *Fmt
, ...)
534 CHAR FilePathA
[MAX_PATH
];
535 WCHAR FilePathW
[MAX_PATH
];
538 vsnprintf_s(FilePathA
, sizeof(FilePathA
), sizeof(FilePathA
), Fmt
, Arg
);
541 UTF8
= IsUTF8Encode(FilePathA
);
545 Utf8ToUtf16(FilePathA
, FilePathW
);
546 hFile
= CreateFileW(FilePathW
, FILE_READ_EA
, FILE_SHARE_READ
, 0, OPEN_EXISTING
, 0, 0);
550 hFile
= CreateFileA(FilePathA
, FILE_READ_EA
, FILE_SHARE_READ
, 0, OPEN_EXISTING
, 0, 0);
552 if (INVALID_HANDLE_VALUE
== hFile
)
561 Attr
= GetFileAttributesW(FilePathW
);
565 Attr
= GetFileAttributesA(FilePathA
);
568 if (Attr
& FILE_ATTRIBUTE_DIRECTORY
)
576 Log("File <%s> %s", FilePathA
, (bRet
? "exist" : "NOT exist"));
580 static int GetPhyDiskUUID(const char LogicalDrive
, UINT8
*UUID
, UINT32
*DiskSig
, DISK_EXTENT
*DiskExtent
)
585 VOLUME_DISK_EXTENTS DiskExtents
;
587 UINT8 SectorBuf
[512];
589 Log("GetPhyDiskUUID %C", LogicalDrive
);
591 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\%C:", LogicalDrive
);
592 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
593 if (Handle
== INVALID_HANDLE_VALUE
)
595 Log("Could not open the disk<%s>, error:%u", PhyPath
, GetLastError());
599 Ret
= DeviceIoControl(Handle
,
600 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
604 (DWORD
)(sizeof(DiskExtents
)),
607 if (!Ret
|| DiskExtents
.NumberOfDiskExtents
== 0)
609 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed, error:%u", GetLastError());
615 memcpy(DiskExtent
, DiskExtents
.Extents
, sizeof(DISK_EXTENT
));
616 Log("%C: is in PhysicalDrive%d Offset:%llu", LogicalDrive
, DiskExtents
.Extents
[0].DiskNumber
,
617 (ULONGLONG
)(DiskExtents
.Extents
[0].StartingOffset
.QuadPart
));
619 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\PhysicalDrive%d", DiskExtents
.Extents
[0].DiskNumber
);
620 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
621 if (Handle
== INVALID_HANDLE_VALUE
)
623 Log("Could not open the disk<%s>, error:%u", PhyPath
, GetLastError());
627 if (!ReadFile(Handle
, SectorBuf
, sizeof(SectorBuf
), &dwSize
, NULL
))
629 Log("ReadFile failed, dwSize:%u error:%u", dwSize
, GetLastError());
634 memcpy(UUID
, SectorBuf
+ 0x180, 16);
637 memcpy(DiskSig
, SectorBuf
+ 0x1B8, 4);
644 static int VentoyMountAnywhere(HANDLE Handle
)
647 ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters
;
649 Log("VentoyMountAnywhere");
651 memset(&AttachParameters
, 0, sizeof(AttachParameters
));
652 AttachParameters
.Version
= ATTACH_VIRTUAL_DISK_VERSION_1
;
654 Status
= AttachVirtualDisk(Handle
, NULL
, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY
| ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME
, 0, &AttachParameters
, NULL
);
655 if (Status
!= ERROR_SUCCESS
)
657 Log("Failed to attach virtual disk ErrorCode:%u", Status
);
664 int VentoyMountY(HANDLE Handle
)
669 DWORD physicalDriveNameSize
;
671 WCHAR physicalDriveName
[MAX_PATH
];
672 CHAR physicalDriveNameA
[MAX_PATH
];
673 CHAR cdromDriveName
[MAX_PATH
];
674 ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters
;
678 memset(&AttachParameters
, 0, sizeof(AttachParameters
));
679 AttachParameters
.Version
= ATTACH_VIRTUAL_DISK_VERSION_1
;
681 Status
= AttachVirtualDisk(Handle
, NULL
, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY
| ATTACH_VIRTUAL_DISK_FLAG_NO_DRIVE_LETTER
| ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME
, 0, &AttachParameters
, NULL
);
682 if (Status
!= ERROR_SUCCESS
)
684 Log("Failed to attach virtual disk ErrorCode:%u", Status
);
688 memset(physicalDriveName
, 0, sizeof(physicalDriveName
));
689 memset(physicalDriveNameA
, 0, sizeof(physicalDriveNameA
));
691 physicalDriveNameSize
= MAX_PATH
;
692 Status
= GetVirtualDiskPhysicalPath(Handle
, &physicalDriveNameSize
, physicalDriveName
);
693 if (Status
!= ERROR_SUCCESS
)
695 Log("Failed GetVirtualDiskPhysicalPath ErrorCode:%u", Status
);
699 for (i
= 0; physicalDriveName
[i
]; i
++)
701 physicalDriveNameA
[i
] = (CHAR
)toupper((CHAR
)(physicalDriveName
[i
]));
704 Log("physicalDriveNameA=<%s>", physicalDriveNameA
);
706 Pos
= strstr(physicalDriveNameA
, "CDROM");
709 Log("Not cdrom phy drive");
713 sprintf_s(cdromDriveName
, sizeof(cdromDriveName
), "\\Device\\%s", Pos
);
714 Log("cdromDriveName=<%s>", cdromDriveName
);
716 for (i
= 0; i
< 3 && (bRet
== FALSE
); i
++)
719 bRet
= DefineDosDeviceA(DDD_RAW_TARGET_PATH
, "Y:", cdromDriveName
);
720 Log("DefineDosDeviceA %s", bRet
? "success" : "failed");
726 static BOOL
VentoyAPINeedMountY(const char *IsoPath
)
734 static int VentoyAttachVirtualDisk(HANDLE Handle
, const char *IsoPath
)
739 Drives
= GetLogicalDrives();
740 if ((1 << 24) & Drives
)
742 Log("Y: is occupied");
747 Log("Y: is free now");
751 if (DriveYFree
&& VentoyAPINeedMountY(IsoPath
))
753 return VentoyMountY(Handle
);
757 return VentoyMountAnywhere(Handle
);
761 int VentoyMountISOByAPI(const char *IsoPath
)
766 WCHAR wFilePath
[512] = { 0 };
767 VIRTUAL_STORAGE_TYPE StorageType
;
768 OPEN_VIRTUAL_DISK_PARAMETERS OpenParameters
;
770 Log("VentoyMountISOByAPI <%s>", IsoPath
);
772 if (IsUTF8Encode(IsoPath
))
774 Log("This is UTF8 encoding");
775 MultiByteToWideChar(CP_UTF8
, 0, IsoPath
, (int)strlen(IsoPath
), wFilePath
, (int)(sizeof(wFilePath
) / sizeof(WCHAR
)));
779 Log("This is ANSI encoding");
780 MultiByteToWideChar(CP_ACP
, 0, IsoPath
, (int)strlen(IsoPath
), wFilePath
, (int)(sizeof(wFilePath
) / sizeof(WCHAR
)));
783 memset(&StorageType
, 0, sizeof(StorageType
));
784 memset(&OpenParameters
, 0, sizeof(OpenParameters
));
786 OpenParameters
.Version
= OPEN_VIRTUAL_DISK_VERSION_1
;
788 for (i
= 0; i
< 10; i
++)
790 Status
= OpenVirtualDisk(&StorageType
, wFilePath
, VIRTUAL_DISK_ACCESS_READ
, 0, &OpenParameters
, &Handle
);
791 if (ERROR_FILE_NOT_FOUND
== Status
|| ERROR_PATH_NOT_FOUND
== Status
)
793 Log("OpenVirtualDisk ErrorCode:%u, now wait and retry...", Status
);
798 if (ERROR_SUCCESS
== Status
)
800 Log("OpenVirtualDisk success");
802 else if (ERROR_VIRTDISK_PROVIDER_NOT_FOUND
== Status
)
804 Log("VirtualDisk for ISO file is not supported in current system");
808 Log("Failed to open virtual disk ErrorCode:%u", Status
);
814 if (Status
!= ERROR_SUCCESS
)
819 Log("OpenVirtualDisk success");
821 Status
= VentoyAttachVirtualDisk(Handle
, IsoPath
);
822 if (Status
!= ERROR_SUCCESS
)
824 Log("Failed to attach virtual disk ErrorCode:%u", Status
);
829 Log("VentoyAttachVirtualDisk success");
836 static HANDLE g_FatPhyDrive
;
837 static UINT64 g_Part2StartSec
;
839 static int CopyFileFromFatDisk(const CHAR
* SrcFile
, const CHAR
*DstFile
)
846 Log("CopyFileFromFatDisk (%s)==>(%s)", SrcFile
, DstFile
);
848 flfile
= fl_fopen(SrcFile
, "rb");
851 fl_fseek(flfile
, 0, SEEK_END
);
852 size
= (int)fl_ftell(flfile
);
853 fl_fseek(flfile
, 0, SEEK_SET
);
855 buf
= (char *)malloc(size
);
858 fl_fread(buf
, 1, size
, flfile
);
861 SaveBuffer2File(DstFile
, buf
, size
);
871 static int VentoyFatDiskRead(uint32 Sector
, uint8
*Buffer
, uint32 SectorCount
)
876 LARGE_INTEGER liCurrentPosition
;
878 liCurrentPosition
.QuadPart
= Sector
+ g_Part2StartSec
;
879 liCurrentPosition
.QuadPart
*= 512;
880 SetFilePointerEx(g_FatPhyDrive
, liCurrentPosition
, &liCurrentPosition
, FILE_BEGIN
);
882 ReadSize
= (DWORD
)(SectorCount
* 512);
884 bRet
= ReadFile(g_FatPhyDrive
, Buffer
, ReadSize
, &dwSize
, NULL
);
885 if (bRet
== FALSE
|| dwSize
!= ReadSize
)
887 Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u", bRet
, ReadSize
, dwSize
, GetLastError());
893 static BOOL
Is2K10PE(void)
899 fopen_s(&fp
, "X:\\Windows\\System32\\PECMD.INI", "r");
905 memset(szLine
, 0, sizeof(szLine
));
906 while (fgets(szLine
, sizeof(szLine
) - 1, fp
))
908 if (strstr(szLine
, "2k10\\"))
919 static CHAR
GetIMDiskMountLogicalDrive(const char *suffix
)
923 DWORD Mask
= 0x1000000;
925 // fixed use M as mountpoint for 2K10 PE
928 Log("Use M: for 2K10 PE");
932 //fixed use Z as mountpoint for Lenovo Product Recovery
933 if (strcmp(suffix
, "VTLRI") == 0)
938 Drives
= GetLogicalDrives();
939 Log("Drives=0x%x", Drives
);
943 if ((Drives
& Mask
) == 0)
955 UINT64
GetVentoyEfiPartStartSector(HANDLE hDrive
)
960 VTOY_GPT_INFO
*pGpt
= NULL
;
961 UINT64 StartSector
= 0;
963 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
965 bRet
= ReadFile(hDrive
, &MBR
, sizeof(MBR
), &dwSize
, NULL
);
966 Log("Read MBR Ret:%u Size:%u code:%u", bRet
, dwSize
, LASTERR
);
968 if ((!bRet
) || (dwSize
!= sizeof(MBR
)))
973 if (MBR
.PartTbl
[0].FsFlag
== 0xEE)
975 Log("GPT partition style");
977 pGpt
= malloc(sizeof(VTOY_GPT_INFO
));
983 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
984 bRet
= ReadFile(hDrive
, pGpt
, sizeof(VTOY_GPT_INFO
), &dwSize
, NULL
);
985 if ((!bRet
) || (dwSize
!= sizeof(VTOY_GPT_INFO
)))
987 Log("Failed to read gpt info %d %u %d", bRet
, dwSize
, LASTERR
);
991 StartSector
= pGpt
->PartTbl
[1].StartLBA
;
996 Log("MBR partition style");
997 StartSector
= MBR
.PartTbl
[1].StartSectorId
;
1000 Log("GetVentoyEfiPart StartSector: %llu", StartSector
);
1004 static int VentoyCopyImdisk(DWORD PhyDrive
, CHAR
*ImPath
)
1010 CHAR PhyPath
[MAX_PATH
];
1011 GET_LENGTH_INFORMATION LengthInfo
;
1013 if (IsFileExist("X:\\Windows\\System32\\imdisk.exe"))
1015 Log("imdisk.exe already exist, no need to copy...");
1016 strcpy_s(ImPath
, MAX_PATH
, "imdisk.exe");
1020 if (IsFileExist("X:\\Windows\\System32\\ventoy\\imdisk.exe"))
1022 Log("imdisk.exe already copied, no need to copy...");
1023 strcpy_s(ImPath
, MAX_PATH
, "ventoy\\imdisk.exe");
1027 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\PhysicalDrive%d", PhyDrive
);
1028 hDrive
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
1029 if (hDrive
== INVALID_HANDLE_VALUE
)
1031 Log("Could not open the disk<%s>, error:%u", PhyPath
, GetLastError());
1035 bRet
= DeviceIoControl(hDrive
, IOCTL_DISK_GET_LENGTH_INFO
, NULL
, 0, &LengthInfo
, sizeof(LengthInfo
), &dwBytes
, NULL
);
1038 Log("Could not get phy disk %s size, error:%u", PhyPath
, GetLastError());
1042 g_FatPhyDrive
= hDrive
;
1043 g_Part2StartSec
= GetVentoyEfiPartStartSector(hDrive
);
1045 Log("Parse FAT fs...");
1049 if (0 == fl_attach_media(VentoyFatDiskRead
, NULL
))
1051 if (g_system_bit
== 64)
1053 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.sys", "ventoy\\imdisk.sys");
1054 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.exe", "ventoy\\imdisk.exe");
1055 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.cpl", "ventoy\\imdisk.cpl");
1059 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.sys", "ventoy\\imdisk.sys");
1060 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.exe", "ventoy\\imdisk.exe");
1061 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.cpl", "ventoy\\imdisk.cpl");
1064 GetCurrentDirectoryA(sizeof(PhyPath
), PhyPath
);
1065 strcat_s(PhyPath
, sizeof(PhyPath
), "\\ventoy\\imdisk.sys");
1067 if (LoadNtDriver(PhyPath
) == 0)
1069 strcpy_s(ImPath
, MAX_PATH
, "ventoy\\imdisk.exe");
1077 SAFE_CLOSE_HANDLE(hDrive
);
1082 static int VentoyRunImdisk(const char *suffix
, const char *IsoPath
, const char *imdiskexe
, const char *opt
)
1086 WCHAR CmdlineW
[512];
1087 PROCESS_INFORMATION Pi
;
1089 Log("VentoyRunImdisk <%s> <%s> <%s> <%s>", suffix
, IsoPath
, imdiskexe
, opt
);
1091 Letter
= GetIMDiskMountLogicalDrive(suffix
);
1093 sprintf_s(Cmdline
, sizeof(Cmdline
), "%s -a -o %s -f \"%s\" -m %C:", imdiskexe
, opt
, IsoPath
, Letter
);
1094 Log("mount iso to %C: use imdisk cmd <%s>", Letter
, Cmdline
);
1096 if (IsUTF8Encode(IsoPath
))
1099 GetStartupInfoW(&Si
);
1100 Si
.dwFlags
|= STARTF_USESHOWWINDOW
;
1101 Si
.wShowWindow
= SW_HIDE
;
1103 Utf8ToUtf16(Cmdline
, CmdlineW
);
1104 CreateProcessW(NULL
, CmdlineW
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
1106 Log("This is UTF8 encoding");
1111 GetStartupInfoA(&Si
);
1112 Si
.dwFlags
|= STARTF_USESHOWWINDOW
;
1113 Si
.wShowWindow
= SW_HIDE
;
1115 CreateProcessA(NULL
, Cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
1117 Log("This is ANSI encoding");
1120 Log("Wait for imdisk process ...");
1121 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
1122 Log("imdisk process finished");
1127 int VentoyMountISOByImdisk(const char *IsoPath
, DWORD PhyDrive
)
1130 CHAR ImPath
[MAX_PATH
];
1132 Log("VentoyMountISOByImdisk %s", IsoPath
);
1134 if (0 == VentoyCopyImdisk(PhyDrive
, ImPath
))
1136 VentoyRunImdisk("iso", IsoPath
, ImPath
, "ro");
1143 static int GetIsoId(CONST CHAR
*IsoPath
, IsoId
*ids
)
1151 hFile
= CreateFileA(IsoPath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
1152 if (hFile
== INVALID_HANDLE_VALUE
)
1157 SetFilePointer(hFile
, 2048 * 16 + 8, NULL
, FILE_BEGIN
);
1158 bRet
[n
++] = ReadFile(hFile
, ids
->SystemId
, 32, &dwSize
, NULL
);
1160 SetFilePointer(hFile
, 2048 * 16 + 40, NULL
, FILE_BEGIN
);
1161 bRet
[n
++] = ReadFile(hFile
, ids
->VolumeId
, 32, &dwSize
, NULL
);
1163 SetFilePointer(hFile
, 2048 * 16 + 318, NULL
, FILE_BEGIN
);
1164 bRet
[n
++] = ReadFile(hFile
, ids
->PulisherId
, 128, &dwSize
, NULL
);
1166 SetFilePointer(hFile
, 2048 * 16 + 446, NULL
, FILE_BEGIN
);
1167 bRet
[n
++] = ReadFile(hFile
, ids
->PreparerId
, 128, &dwSize
, NULL
);
1172 for (i
= 0; i
< n
; i
++)
1174 if (bRet
[i
] == FALSE
)
1181 TrimString(ids
->SystemId
, FALSE
);
1182 TrimString(ids
->VolumeId
, FALSE
);
1183 TrimString(ids
->PulisherId
, FALSE
);
1184 TrimString(ids
->PreparerId
, FALSE
);
1186 Log("ISO ID: System<%s> Volume<%s> Pulisher<%s> Preparer<%s>",
1187 ids
->SystemId
, ids
->VolumeId
, ids
->PulisherId
, ids
->PreparerId
);
1192 static int CheckSkipMountIso(CONST CHAR
*IsoPath
)
1194 BOOL InRoot
= FALSE
;
1196 CONST CHAR
*p
= NULL
;
1200 for (p
= IsoPath
; *p
; p
++)
1202 if (*p
== '\\' || *p
== '/')
1213 memset(&ID
, 0, sizeof(ID
));
1214 if (GetIsoId(IsoPath
, &ID
))
1219 //Bob.Ombs.Modified.Win10PEx64.iso will auto find ISO file in root, so we can skip the mount
1220 if (InRoot
&& strcmp(ID
.VolumeId
, "Modified-Win10PEx64") == 0)
1228 static int MountIsoFile(CONST CHAR
*IsoPath
, DWORD PhyDrive
)
1230 if (CheckSkipMountIso(IsoPath
))
1232 Log("Skip mount ISO file for <%s>", IsoPath
);
1236 if (IsWindows8OrGreater())
1238 Log("This is Windows 8 or latter...");
1239 if (VentoyMountISOByAPI(IsoPath
) == 0)
1241 Log("Mount iso by API success");
1246 Log("Mount iso by API failed, maybe not supported, try imdisk");
1247 return VentoyMountISOByImdisk(IsoPath
, PhyDrive
);
1252 Log("This is before Windows 8 ...");
1253 if (VentoyMountISOByImdisk(IsoPath
, PhyDrive
) == 0)
1255 Log("Mount iso by imdisk success");
1260 return VentoyMountISOByAPI(IsoPath
);
1265 static int GetPhyDriveByLogicalDrive(int DriveLetter
)
1270 VOLUME_DISK_EXTENTS DiskExtents
;
1273 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\%C:", (CHAR
)DriveLetter
);
1275 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
1276 if (Handle
== INVALID_HANDLE_VALUE
)
1278 Log("Could not open the disk<%s>, error:%u", PhyPath
, GetLastError());
1282 Ret
= DeviceIoControl(Handle
,
1283 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
1287 (DWORD
)(sizeof(DiskExtents
)),
1291 if (!Ret
|| DiskExtents
.NumberOfDiskExtents
== 0)
1293 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath
, GetLastError());
1294 SAFE_CLOSE_HANDLE(Handle
);
1297 SAFE_CLOSE_HANDLE(Handle
);
1299 Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",
1301 DiskExtents
.Extents
[0].DiskNumber
,
1302 DiskExtents
.Extents
[0].StartingOffset
.QuadPart
,
1303 DiskExtents
.Extents
[0].ExtentLength
.QuadPart
1306 return (int)DiskExtents
.Extents
[0].DiskNumber
;
1310 static int DeleteVentoyPart2MountPoint(DWORD PhyDrive
)
1315 CHAR DriveName
[] = "?:\\";
1317 Log("DeleteVentoyPart2MountPoint Phy%u ...", PhyDrive
);
1319 Drives
= GetLogicalDrives();
1322 if ((Drives
& 0x01) && IsFileExist("%C:\\ventoy\\ventoy.cpio", Letter
))
1324 Log("File %C:\\ventoy\\ventoy.cpio exist", Letter
);
1326 PhyDisk
= GetPhyDriveByLogicalDrive(Letter
);
1327 Log("PhyDisk=%u for %C", PhyDisk
, Letter
);
1329 if (PhyDisk
== PhyDrive
)
1331 DriveName
[0] = Letter
;
1332 DeleteVolumeMountPointA(DriveName
);
1344 static BOOL
check_tar_archive(const char *archive
, CHAR
*tarName
)
1348 const char *pos
= archive
;
1349 const char *slash
= archive
;
1353 if (*pos
== '\\' || *pos
== '/')
1360 len
= (int)strlen(slash
);
1362 if (len
> 7 && (strncmp(slash
+ len
- 7, ".tar.gz", 7) == 0 || strncmp(slash
+ len
- 7, ".tar.xz", 7) == 0))
1364 nameLen
= (int)sprintf_s(tarName
, MAX_PATH
, "X:%s", slash
);
1365 tarName
[nameLen
- 3] = 0;
1368 else if (len
> 8 && strncmp(slash
+ len
- 8, ".tar.bz2", 8) == 0)
1370 nameLen
= (int)sprintf_s(tarName
, MAX_PATH
, "X:%s", slash
);
1371 tarName
[nameLen
- 4] = 0;
1374 else if (len
> 9 && strncmp(slash
+ len
- 9, ".tar.lzma", 9) == 0)
1376 nameLen
= (int)sprintf_s(tarName
, MAX_PATH
, "X:%s", slash
);
1377 tarName
[nameLen
- 5] = 0;
1384 static UCHAR
*g_unxz_buffer
= NULL
;
1385 static int g_unxz_len
= 0;
1387 static void unxz_error(char *x
)
1392 static int unxz_flush(void *src
, unsigned int size
)
1394 memcpy(g_unxz_buffer
+ g_unxz_len
, src
, size
);
1395 g_unxz_len
+= (int)size
;
1400 static int DecompressInjectionArchive(const char *archive
, DWORD PhyDrive
)
1404 UCHAR
*Buffer
= NULL
;
1405 UCHAR
*RawBuffer
= NULL
;
1411 DWORD flags
= CREATE_NO_WINDOW
;
1412 CHAR StrBuf
[MAX_PATH
];
1413 CHAR tarName
[MAX_PATH
];
1415 PROCESS_INFORMATION Pi
;
1416 PROCESS_INFORMATION NewPi
;
1417 GET_LENGTH_INFORMATION LengthInfo
;
1418 SECURITY_ATTRIBUTES Sa
= { sizeof(SECURITY_ATTRIBUTES
), NULL
, TRUE
};
1420 Log("DecompressInjectionArchive %s", archive
);
1422 sprintf_s(StrBuf
, sizeof(StrBuf
), "\\\\.\\PhysicalDrive%d", PhyDrive
);
1423 hDrive
= CreateFileA(StrBuf
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
1424 if (hDrive
== INVALID_HANDLE_VALUE
)
1426 Log("Could not open the disk<%s>, error:%u", StrBuf
, GetLastError());
1430 bRet
= DeviceIoControl(hDrive
, IOCTL_DISK_GET_LENGTH_INFO
, NULL
, 0, &LengthInfo
, sizeof(LengthInfo
), &dwBytes
, NULL
);
1433 Log("Could not get phy disk %s size, error:%u", StrBuf
, GetLastError());
1437 g_FatPhyDrive
= hDrive
;
1438 g_Part2StartSec
= GetVentoyEfiPartStartSector(hDrive
);
1440 Log("Parse FAT fs...");
1444 if (0 == fl_attach_media(VentoyFatDiskRead
, NULL
))
1446 if (g_system_bit
== 64)
1448 CopyFileFromFatDisk("/ventoy/7z/64/7za.xz", "ventoy\\7za.xz");
1452 CopyFileFromFatDisk("/ventoy/7z/32/7za.xz", "ventoy\\7za.xz");
1455 ReadWholeFile2Buf("ventoy\\7za.xz", &Buffer
, &dwSize
);
1456 Log("7za.xz file size:%u", dwSize
);
1458 RawBuffer
= malloc(SIZE_1MB
* 4);
1461 g_unxz_buffer
= RawBuffer
;
1463 unxz(Buffer
, (int)dwSize
, NULL
, unxz_flush
, NULL
, &writelen
, unxz_error
);
1464 if (writelen
== (int)dwSize
)
1466 Log("Decompress success 7za.xz(%u) ---> 7za.exe(%d)", dwSize
, g_unxz_len
);
1470 Log("Decompress failed 7za.xz(%u) ---> 7za.exe(%u)", dwSize
, dwSize
);
1473 SaveBuffer2File("ventoy\\7za.exe", RawBuffer
, (DWORD
)g_unxz_len
);
1475 g_unxz_buffer
= NULL
;
1481 Log("Failed to alloc 4MB memory");
1484 sprintf_s(StrBuf
, sizeof(StrBuf
), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", archive
);
1486 Log("extract inject to X:");
1487 Log("cmdline:<%s>", StrBuf
);
1489 GetStartupInfoA(&Si
);
1491 hOut
= CreateFileA("ventoy\\7z.log",
1493 FILE_SHARE_WRITE
| FILE_SHARE_READ
,
1496 FILE_ATTRIBUTE_NORMAL
,
1499 Si
.dwFlags
|= STARTF_USESTDHANDLES
;
1501 if (hOut
!= INVALID_HANDLE_VALUE
)
1503 Si
.hStdError
= hOut
;
1504 Si
.hStdOutput
= hOut
;
1507 CreateProcessA(NULL
, StrBuf
, NULL
, NULL
, TRUE
, flags
, NULL
, NULL
, &Si
, &Pi
);
1508 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
1511 // decompress tar archive, for tar.gz/tar.xz/tar.bz2
1513 if (check_tar_archive(archive
, tarName
))
1515 Log("Decompress tar archive...<%s>", tarName
);
1517 sprintf_s(StrBuf
, sizeof(StrBuf
), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", tarName
);
1519 CreateProcessA(NULL
, StrBuf
, NULL
, NULL
, TRUE
, flags
, NULL
, NULL
, &Si
, &NewPi
);
1520 WaitForSingleObject(NewPi
.hProcess
, INFINITE
);
1522 Log("Now delete %s", tarName
);
1523 DeleteFileA(tarName
);
1526 SAFE_CLOSE_HANDLE(hOut
);
1532 SAFE_CLOSE_HANDLE(hDrive
);
1537 static int UnattendNeedVarExpand(const char *script
)
1542 fopen_s(&fp
, script
, "r");
1548 szLine
[0] = szLine
[4095] = 0;
1550 while (fgets(szLine
, sizeof(szLine
) - 1, fp
))
1552 if (strstr(szLine
, "$$VT_"))
1558 szLine
[0] = szLine
[4095] = 0;
1565 static int ExpandSingleVar(VarDiskInfo
*pDiskInfo
, int DiskNum
, const char *var
, char *value
, int len
)
1571 UINT64 uiMaxSize
= 0;
1572 UINT64 uiMaxDelta
= ULLONG_MAX
;
1576 if (strcmp(var
, "VT_WINDOWS_DISK_1ST_NONVTOY") == 0)
1578 for (i
= 0; i
< DiskNum
; i
++)
1580 if (pDiskInfo
[i
].Capacity
> 0 && i
!= g_vtoy_disk_drive
)
1582 Log("%s=<PhyDrive%d>", var
, i
);
1583 sprintf_s(value
, len
, "%d", i
);
1588 else if (strcmp(var
, "VT_WINDOWS_DISK_1ST_NONUSB") == 0)
1590 for (i
= 0; i
< DiskNum
; i
++)
1592 if (pDiskInfo
[i
].Capacity
> 0 && pDiskInfo
[i
].BusType
!= BusTypeUsb
)
1594 Log("%s=<PhyDrive%d>", var
, i
);
1595 sprintf_s(value
, len
, "%d", i
);
1600 else if (strcmp(var
, "VT_WINDOWS_DISK_MAX_SIZE") == 0)
1602 for (i
= 0; i
< DiskNum
; i
++)
1604 if (pDiskInfo
[i
].Capacity
> 0 && pDiskInfo
[i
].Capacity
> uiMaxSize
)
1607 uiMaxSize
= pDiskInfo
[i
].Capacity
;
1611 Log("%s=<PhyDrive%d>", var
, index
);
1612 sprintf_s(value
, len
, "%d", index
);
1614 else if (strncmp(var
, "VT_WINDOWS_DISK_CLOSEST_", 24) == 0)
1616 uiDst
= strtoul(var
+ 24, NULL
, 10);
1617 uiDst
= uiDst
* (1024ULL * 1024ULL * 1024ULL);
1619 for (i
= 0; i
< DiskNum
; i
++)
1621 if (pDiskInfo
[i
].Capacity
== 0)
1626 if (pDiskInfo
[i
].Capacity
> uiDst
)
1628 uiDelta
= pDiskInfo
[i
].Capacity
- uiDst
;
1632 uiDelta
= uiDst
- pDiskInfo
[i
].Capacity
;
1635 if (uiDelta
< uiMaxDelta
)
1637 uiMaxDelta
= uiDelta
;
1642 Log("%s=<PhyDrive%d>", var
, index
);
1643 sprintf_s(value
, len
, "%d", index
);
1647 Log("Invalid var name <%s>", var
);
1648 sprintf_s(value
, len
, "$$%s$$", var
);
1653 sprintf_s(value
, len
, "$$%s$$", var
);
1659 static int GetRegDwordValue(HKEY Key
, LPCSTR SubKey
, LPCSTR ValueName
, DWORD
*pValue
)
1667 lRet
= RegOpenKeyExA(Key
, SubKey
, 0, KEY_QUERY_VALUE
, &hKey
);
1668 Log("RegOpenKeyExA <%s> Ret:%ld", SubKey
, lRet
);
1670 if (ERROR_SUCCESS
== lRet
)
1672 Size
= sizeof(Value
);
1673 lRet
= RegQueryValueExA(hKey
, ValueName
, NULL
, &Type
, (LPBYTE
)&Value
, &Size
);
1674 Log("RegQueryValueExA <%s> ret:%u Size:%u Value:%u", ValueName
, lRet
, Size
, Value
);
1687 static const CHAR
* GetBusTypeString(int Type
)
1691 case BusTypeUnknown
: return "unknown";
1692 case BusTypeScsi
: return "SCSI";
1693 case BusTypeAtapi
: return "Atapi";
1694 case BusTypeAta
: return "ATA";
1695 case BusType1394
: return "1394";
1696 case BusTypeSsa
: return "SSA";
1697 case BusTypeFibre
: return "Fibre";
1698 case BusTypeUsb
: return "USB";
1699 case BusTypeRAID
: return "RAID";
1700 case BusTypeiScsi
: return "iSCSI";
1701 case BusTypeSas
: return "SAS";
1702 case BusTypeSata
: return "SATA";
1703 case BusTypeSd
: return "SD";
1704 case BusTypeMmc
: return "MMC";
1705 case BusTypeVirtual
: return "Virtual";
1706 case BusTypeFileBackedVirtual
: return "FileBackedVirtual";
1707 case BusTypeSpaces
: return "Spaces";
1708 case BusTypeNvme
: return "Nvme";
1713 static int GetHumanReadableGBSize(UINT64 SizeBytes
)
1718 double GB
= SizeBytes
* 1.0 / 1000 / 1000 / 1000;
1720 if ((SizeBytes
% 1073741824) == 0)
1722 return (int)(SizeBytes
/ 1073741824);
1725 for (i
= 0; i
< 12; i
++)
1729 Delta
= (Pow2
- GB
) / Pow2
;
1733 Delta
= (GB
- Pow2
) / Pow2
;
1747 static int EnumerateAllDisk(VarDiskInfo
**ppDiskInfo
, int *pDiskNum
)
1754 VarDiskInfo
*pDiskInfo
= NULL
;
1755 HANDLE Handle
= INVALID_HANDLE_VALUE
;
1757 GET_LENGTH_INFORMATION LengthInfo
;
1758 STORAGE_PROPERTY_QUERY Query
;
1759 STORAGE_DESCRIPTOR_HEADER DevDescHeader
;
1760 STORAGE_DEVICE_DESCRIPTOR
*pDevDesc
;
1762 if (GetRegDwordValue(HKEY_LOCAL_MACHINE
, "SYSTEM\\CurrentControlSet\\Services\\disk\\Enum", "Count", &Value
) == 0)
1764 DiskNum
= (int)Value
;
1768 Log("Failed to read disk count");
1772 Log("Current phy disk count:%d", DiskNum
);
1778 pDiskInfo
= malloc(DiskNum
* sizeof(VarDiskInfo
));
1781 Log("Failed to alloc");
1784 memset(pDiskInfo
, 0, DiskNum
* sizeof(VarDiskInfo
));
1786 for (i
= 0; i
< DiskNum
; i
++)
1788 SAFE_CLOSE_HANDLE(Handle
);
1790 safe_sprintf(PhyDrive
, "\\\\.\\PhysicalDrive%d", i
);
1791 Handle
= CreateFileA(PhyDrive
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
1792 Log("Create file Handle:%p %s status:%u", Handle
, PhyDrive
, LASTERR
);
1794 if (Handle
== INVALID_HANDLE_VALUE
)
1799 bRet
= DeviceIoControl(Handle
,
1800 IOCTL_DISK_GET_LENGTH_INFO
, NULL
,
1808 Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR
);
1812 Log("PHYSICALDRIVE%d size %llu bytes", i
, (ULONGLONG
)LengthInfo
.Length
.QuadPart
);
1814 Query
.PropertyId
= StorageDeviceProperty
;
1815 Query
.QueryType
= PropertyStandardQuery
;
1817 bRet
= DeviceIoControl(Handle
,
1818 IOCTL_STORAGE_QUERY_PROPERTY
,
1822 sizeof(STORAGE_DESCRIPTOR_HEADER
),
1827 Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR
, dwBytes
);
1831 if (DevDescHeader
.Size
< sizeof(STORAGE_DEVICE_DESCRIPTOR
))
1833 Log("Invalid DevDescHeader.Size:%u", DevDescHeader
.Size
);
1837 pDevDesc
= (STORAGE_DEVICE_DESCRIPTOR
*)malloc(DevDescHeader
.Size
);
1840 Log("failed to malloc error:%u len:%u", LASTERR
, DevDescHeader
.Size
);
1844 bRet
= DeviceIoControl(Handle
,
1845 IOCTL_STORAGE_QUERY_PROPERTY
,
1854 Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR
, dwBytes
);
1859 pDiskInfo
[i
].RemovableMedia
= pDevDesc
->RemovableMedia
;
1860 pDiskInfo
[i
].BusType
= pDevDesc
->BusType
;
1861 pDiskInfo
[i
].DeviceType
= pDevDesc
->DeviceType
;
1862 pDiskInfo
[i
].Capacity
= LengthInfo
.Length
.QuadPart
;
1864 if (pDevDesc
->VendorIdOffset
)
1866 safe_strcpy(pDiskInfo
[i
].VendorId
, (char *)pDevDesc
+ pDevDesc
->VendorIdOffset
);
1867 TrimString(pDiskInfo
[i
].VendorId
, TRUE
);
1870 if (pDevDesc
->ProductIdOffset
)
1872 safe_strcpy(pDiskInfo
[i
].ProductId
, (char *)pDevDesc
+ pDevDesc
->ProductIdOffset
);
1873 TrimString(pDiskInfo
[i
].ProductId
, TRUE
);
1876 if (pDevDesc
->ProductRevisionOffset
)
1878 safe_strcpy(pDiskInfo
[i
].ProductRev
, (char *)pDevDesc
+ pDevDesc
->ProductRevisionOffset
);
1879 TrimString(pDiskInfo
[i
].ProductRev
, TRUE
);
1882 if (pDevDesc
->SerialNumberOffset
)
1884 safe_strcpy(pDiskInfo
[i
].SerialNumber
, (char *)pDevDesc
+ pDevDesc
->SerialNumberOffset
);
1885 TrimString(pDiskInfo
[i
].SerialNumber
, TRUE
);
1889 SAFE_CLOSE_HANDLE(Handle
);
1892 Log("########## DUMP DISK BEGIN ##########");
1893 for (i
= 0; i
< DiskNum
; i
++)
1895 Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s",
1896 i
, GetBusTypeString(pDiskInfo
[i
].BusType
), pDiskInfo
[i
].RemovableMedia
,
1897 GetHumanReadableGBSize(pDiskInfo
[i
].Capacity
), pDiskInfo
[i
].Capacity
,
1898 pDiskInfo
[i
].VendorId
, pDiskInfo
[i
].ProductId
);
1900 Log("Ventoy disk is PhyDvr%d", g_vtoy_disk_drive
);
1901 Log("########## DUMP DISK END ##########");
1903 *ppDiskInfo
= pDiskInfo
;
1904 *pDiskNum
= DiskNum
;
1908 static int UnattendVarExpand(const char *script
, const char *tmpfile
)
1917 VarDiskInfo
*pDiskInfo
= NULL
;
1919 Log("UnattendVarExpand ...");
1921 if (EnumerateAllDisk(&pDiskInfo
, &DiskNum
))
1923 Log("Failed to EnumerateAllDisk");
1927 fopen_s(&fp
, script
, "r");
1934 fopen_s(&fout
, tmpfile
, "w+");
1942 szLine
[0] = szLine
[4095] = 0;
1944 while (fgets(szLine
, sizeof(szLine
) - 1, fp
))
1946 start
= strstr(szLine
, "$$VT_");
1949 end
= strstr(start
+ 5, "$$");
1955 fprintf(fout
, "%s", szLine
);
1958 ExpandSingleVar(pDiskInfo
, DiskNum
, start
+ 2, szValue
, sizeof(szValue
) - 1);
1959 fprintf(fout
, "%s", szValue
);
1961 fprintf(fout
, "%s", end
+ 2);
1965 fprintf(fout
, "%s", szLine
);
1968 szLine
[0] = szLine
[4095] = 0;
1977 //#define VAR_DEBUG 1
1979 static int CreateUnattendRegKey(const char *file
)
1986 Ret
= RegCreateKeyEx(HKEY_LOCAL_MACHINE
, "System\\Setup", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hKey
, &dw
);
1987 if (ERROR_SUCCESS
== Ret
)
1989 Ret
= RegSetValueEx(hKey
, "UnattendFile", 0, REG_SZ
, file
, (DWORD
)(strlen(file
) + 1));
1996 static int ProcessUnattendedInstallation(const char *script
, DWORD PhyDrive
)
2000 CHAR TmpFile
[MAX_PATH
];
2001 CHAR CurDir
[MAX_PATH
];
2002 CHAR ImPath
[MAX_PATH
];
2004 Log("Copy unattended XML ...");
2006 GetCurrentDirectory(sizeof(CurDir
), CurDir
);
2008 if ((Letter
>= 'A' && Letter
<= 'Z') || (Letter
>= 'a' && Letter
<= 'z'))
2010 Log("Current Drive Letter: %C", Letter
);
2018 sprintf_s(CurDir
, sizeof(CurDir
), "%C:\\AutounattendXXX.xml", Letter
);
2020 sprintf_s(CurDir
, sizeof(CurDir
), "%C:\\Unattend.xml", Letter
);
2023 if (UnattendNeedVarExpand(script
))
2025 sprintf_s(TmpFile
, sizeof(TmpFile
), "%C:\\__Autounattend", Letter
);
2026 UnattendVarExpand(script
, TmpFile
);
2028 Log("Expand Copy file <%s> --> <%s>", script
, CurDir
);
2029 CopyFileA(TmpFile
, CurDir
, FALSE
);
2033 Log("No var expand copy file <%s> --> <%s>", script
, CurDir
);
2034 CopyFileA(script
, CurDir
, FALSE
);
2037 VentoyCopyImdisk(PhyDrive
, ImPath
);
2038 DrvLetter
= VentoyGetFirstFreeDriveLetter(FALSE
);
2039 VentoyProcessRunCmd("%s -a -s 64M -m %C: -p \"/fs:FAT32 /q /y\"", ImPath
, DrvLetter
);
2043 sprintf_s(TmpFile
, sizeof(TmpFile
), "%C:\\Unattend.xml", DrvLetter
);
2044 if (CopyFileA(CurDir
, TmpFile
, FALSE
))
2046 DeleteFileA(CurDir
);
2047 Log("Move file <%s> ==> <%s>, use the later as unattend XML", CurDir
, TmpFile
);
2048 CreateUnattendRegKey(TmpFile
);
2052 Log("Failed to copy file <%s> ==> <%s>, use OLD", CurDir
, TmpFile
);
2053 CreateUnattendRegKey(CurDir
);
2059 static int VentoyGetFileVersion(const CHAR
*FilePath
, UINT16
*pMajor
, UINT16
*pMinor
, UINT16
*pBuild
, UINT16
*pRevision
)
2065 CHAR
*Buffer
= NULL
;
2066 VS_FIXEDFILEINFO
* VerInfo
= NULL
;
2067 UINT16 Major
, Minor
, Build
, Revision
;
2069 Log("Get file version for <%s>", FilePath
);
2071 dwSize
= GetFileVersionInfoSizeA(FilePath
, &dwHandle
);
2074 Log("Failed to get file version info size: %u", LASTERR
);
2078 Buffer
= malloc(dwSize
);
2081 Log("malloc failed %u", dwSize
);
2085 if (FALSE
== GetFileVersionInfoA(FilePath
, dwHandle
, dwSize
, Buffer
))
2087 Log("Failed to get file version info : %u", LASTERR
);
2091 if (VerQueryValueA(Buffer
, "\\", (LPVOID
)&VerInfo
, &VerLen
) && VerLen
!= 0)
2093 if (VerInfo
->dwSignature
== VS_FFI_SIGNATURE
)
2095 Major
= HIWORD(VerInfo
->dwFileVersionMS
);
2096 Minor
= LOWORD(VerInfo
->dwFileVersionMS
);
2097 Build
= HIWORD(VerInfo
->dwFileVersionLS
);
2098 Revision
= LOWORD(VerInfo
->dwFileVersionLS
);
2100 Log("FileVersionze: <%u %u %u %u>", Major
, Minor
, Build
, Revision
);
2102 if (Major
== 10 && Build
> 20000)
2121 *pRevision
= Revision
;
2128 Log("Invalid verinfo signature 0x%x", VerInfo
->dwSignature
);
2133 Log("VerQueryValueA failed %u", LASTERR
);
2145 static BOOL
VentoyIsNeedBypass(const char *isofile
, const char MntLetter
)
2149 CHAR CheckFile
[MAX_PATH
];
2151 if (FALSE
== IsFileExist("%C:\\sources\\install.wim", MntLetter
) &&
2152 FALSE
== IsFileExist("%C:\\sources\\install.esd", MntLetter
))
2154 Log("install.wim/install.esd not exist, this is not a windows install media.");
2158 if (FALSE
== IsFileExist("%C:\\sources\\boot.wim", MntLetter
))
2160 Log("boot.wim not exist, this is not a windows install media.");
2164 if (IsFileExist("%C:\\sources\\compatresources.dll", MntLetter
))
2166 sprintf_s(CheckFile
, sizeof(CheckFile
), "%C:\\sources\\compatresources.dll", MntLetter
);
2168 else if (IsFileExist("%C:\\setup.exe", MntLetter
))
2170 sprintf_s(CheckFile
, sizeof(CheckFile
), "%C:\\setup.exe", MntLetter
);
2172 else if (IsFileExist("X:\\setup.exe"))
2174 sprintf_s(CheckFile
, sizeof(CheckFile
), "X:\\setup.exe");
2178 Log("No Check file found");
2182 if (VentoyGetFileVersion(CheckFile
, &Major
, NULL
, NULL
, NULL
))
2189 Log("Enable for Windows 11 %u", Major
);
2194 Log("This is not Windows 11, not need to bypass.", Major
);
2201 static int Windows11Bypass(const char *isofile
, const char MntLetter
, UINT8 Check
, UINT8 NRO
)
2205 HKEY hSubKey
= NULL
;
2210 Log("Windows11Bypass for <%s> %C: Check:%u NRO:%u", isofile
, MntLetter
, Check
, NRO
);
2212 if (!VentoyIsNeedBypass(isofile
, MntLetter
))
2217 //Now we really need to bypass windows 11 check. create registry
2221 Status
= RegCreateKeyExA(HKEY_LOCAL_MACHINE
, "System\\Setup", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hKey
, &dwSize
);
2222 if (ERROR_SUCCESS
!= Status
)
2224 Log("Failed to create reg key System\\Setup %u %u", LASTERR
, Status
);
2228 Status
= RegCreateKeyExA(hKey
, "LabConfig", 0, NULL
, 0, KEY_SET_VALUE
| KEY_QUERY_VALUE
| KEY_CREATE_SUB_KEY
, NULL
, &hSubKey
, &dwSize
);
2229 if (ERROR_SUCCESS
!= Status
)
2231 Log("Failed to create LabConfig reg %u %u", LASTERR
, Status
);
2236 Status
+= RegSetValueExA(hSubKey
, "BypassRAMCheck", 0, REG_DWORD
, (LPBYTE
)&dwValue
, sizeof(DWORD
));
2237 Status
+= RegSetValueExA(hSubKey
, "BypassTPMCheck", 0, REG_DWORD
, (LPBYTE
)&dwValue
, sizeof(DWORD
));
2238 Status
+= RegSetValueExA(hSubKey
, "BypassSecureBootCheck", 0, REG_DWORD
, (LPBYTE
)&dwValue
, sizeof(DWORD
));
2239 Status
+= RegSetValueExA(hSubKey
, "BypassCPUCheck", 0, REG_DWORD
, (LPBYTE
)&dwValue
, sizeof(DWORD
));
2241 Log("Create bypass check registry %s %u", (Status
== ERROR_SUCCESS
) ? "SUCCESS" : "FAILED", Status
);
2247 Status
= RegCreateKeyExA(HKEY_LOCAL_MACHINE
, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hKey
, &dwSize
);
2248 if (ERROR_SUCCESS
!= Status
)
2250 Log("Failed to create reg key SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\OOBE %u %u", LASTERR
, Status
);
2254 Status
= RegCreateKeyExA(hKey
, "OOBE", 0, NULL
, 0, KEY_SET_VALUE
| KEY_QUERY_VALUE
| KEY_CREATE_SUB_KEY
, NULL
, &hSubKey
, &dwSize
);
2255 if (ERROR_SUCCESS
!= Status
)
2257 Log("Failed to create OOBE reg %u %u", LASTERR
, Status
);
2261 Status
+= RegSetValueExA(hSubKey
, "BypassNRO", 0, REG_DWORD
, (LPBYTE
)&dwValue
, sizeof(DWORD
));
2262 Log("Create BypassNRO registry %s %u", (Status
== ERROR_SUCCESS
) ? "SUCCESS" : "FAILED", Status
);
2273 static BOOL
CheckVentoyDisk(DWORD DiskNum
)
2277 UINT8 SectorBuf
[512];
2279 UINT8 check
[8] = { 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44 };
2281 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\PhysicalDrive%d", DiskNum
);
2282 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
2283 if (Handle
== INVALID_HANDLE_VALUE
)
2285 Log("Could not open the disk<%s>, error:%u", PhyPath
, GetLastError());
2289 if (!ReadFile(Handle
, SectorBuf
, sizeof(SectorBuf
), &dwSize
, NULL
))
2291 Log("ReadFile failed, dwSize:%u error:%u", dwSize
, GetLastError());
2292 CloseHandle(Handle
);
2296 CloseHandle(Handle
);
2298 if (memcmp(SectorBuf
+ 0x190, check
, 8) == 0)
2306 static BOOL
VentoyIsLenovoRecovery(CHAR
*IsoPath
, CHAR
*VTLRIPath
)
2312 WCHAR FilePathW
[MAX_PATH
];
2314 UTF8
= IsUTF8Encode(IsoPath
);
2318 Utf8ToUtf16(IsoPath
, FilePathW
);
2320 n
= (int)wcslen(FilePathW
);
2321 if (n
> 4 && _wcsicmp(FilePathW
+ n
- 4, L
".iso") == 0)
2323 FilePathW
[n
- 3] = L
'V';
2324 FilePathW
[n
- 2] = L
'T';
2325 FilePathW
[n
- 1] = L
'L';
2326 FilePathW
[n
- 0] = L
'R';
2327 FilePathW
[n
+ 1] = L
'I';
2328 FilePathW
[n
+ 2] = 0;
2330 hFile
= CreateFileW(FilePathW
, FILE_READ_EA
, FILE_SHARE_READ
, 0, OPEN_EXISTING
, 0, 0);
2331 if (hFile
!= INVALID_HANDLE_VALUE
)
2334 Attr
= GetFileAttributesW(FilePathW
);
2336 if ((Attr
& FILE_ATTRIBUTE_DIRECTORY
) == 0)
2338 Utf16ToUtf8(FilePathW
, VTLRIPath
);
2346 n
= (int)strlen(IsoPath
);
2347 if (n
> 4 && _stricmp(IsoPath
+ n
- 4, ".iso") == 0)
2350 sprintf_s(VTLRIPath
, MAX_PATH
, "%s.VTLRI", IsoPath
);
2351 IsoPath
[n
- 4] = '.';
2353 if (IsFileExist(VTLRIPath
))
2363 static int MountVTLRI(CHAR
*ImgPath
, DWORD PhyDrive
)
2366 PROCESS_INFORMATION Pi
;
2368 CHAR ImDiskPath
[256];
2370 Log("MountVTLRI <%s> %u", ImgPath
, PhyDrive
);
2372 VentoyCopyImdisk(PhyDrive
, ImDiskPath
);
2374 VentoyRunImdisk("VTLRI", ImgPath
, ImDiskPath
, "ro,rem");
2376 CopyFileA(g_prog_full_path
, "ventoy\\VTLRISRV.exe", FALSE
);
2378 sprintf_s(Cmdline
, sizeof(Cmdline
), "ventoy\\VTLRISRV.exe VTLRI_SRV %C Z", ImgPath
[0]);
2381 GetStartupInfoA(&Si
);
2382 Si
.dwFlags
|= STARTF_USESHOWWINDOW
;
2383 Si
.wShowWindow
= SW_HIDE
;
2384 CreateProcessA(NULL
, Cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
2386 Log("Process cmdline <%s>", Cmdline
);
2391 static int VentoyHook(ventoy_os_param
*param
)
2396 BOOL vtoyfind
= FALSE
;
2405 DISK_EXTENT DiskExtent
;
2406 DISK_EXTENT VtoyDiskExtent
;
2408 CHAR IsoPath
[MAX_PATH
];
2409 CHAR VTLRIPath
[MAX_PATH
];
2411 Log("VentoyHook Path:<%s>", param
->vtoy_img_path
);
2413 if (IsUTF8Encode(param
->vtoy_img_path
))
2415 Log("This file is UTF8 encoding");
2418 for (i
= 0; i
< 5; i
++)
2421 Drives
= GetLogicalDrives();
2422 Log("Logic Drives: 0x%x", Drives
);
2428 sprintf_s(IsoPath
, sizeof(IsoPath
), "%C:\\%s", Letter
, param
->vtoy_img_path
);
2429 if (IsFileExist("%s", IsoPath
))
2431 Log("File exist under %C:", Letter
);
2432 memset(UUID
, 0, sizeof(UUID
));
2433 memset(&DiskExtent
, 0, sizeof(DiskExtent
));
2434 if (GetPhyDiskUUID(Letter
, UUID
, NULL
, &DiskExtent
) == 0)
2436 if (memcmp(UUID
, param
->vtoy_disk_guid
, 16) == 0)
2438 Log("Disk UUID match");
2446 Log("File NOT exist under %C:", Letter
);
2460 Log("Now wait and retry ...");
2467 Log("Failed to find ISO file");
2471 Log("Find ISO file <%s>", IsoPath
);
2473 //Find VtoyLetter in Vlnk Mode
2474 if (g_os_param_reserved
[6] == 1)
2476 memcpy(&VtoySig
, g_os_param_reserved
+ 7, 4);
2477 for (i
= 0; i
< 5; i
++)
2480 Drives
= GetLogicalDrives();
2481 Log("Logic Drives: 0x%x VentoySig:%08X", Drives
, VtoySig
);
2487 memset(UUID
, 0, sizeof(UUID
));
2488 memset(&VtoyDiskExtent
, 0, sizeof(VtoyDiskExtent
));
2490 if (GetPhyDiskUUID(VtoyLetter
, UUID
, &DiskSig
, &VtoyDiskExtent
) == 0)
2492 Log("DiskSig=%08X PartStart=%lld", DiskSig
, VtoyDiskExtent
.StartingOffset
.QuadPart
);
2493 if (DiskSig
== VtoySig
&& VtoyDiskExtent
.StartingOffset
.QuadPart
== SIZE_1MB
)
2495 Log("Ventoy Disk Sig match");
2508 Log("Find Ventoy Letter: %C", VtoyLetter
);
2513 Log("Now wait and retry ...");
2518 if (vtoyfind
== FALSE
)
2520 Log("Failed to find ventoy disk");
2524 VtoyDiskNum
= VtoyDiskExtent
.DiskNumber
;
2528 VtoyLetter
= Letter
;
2529 Log("No vlnk mode %C", Letter
);
2531 VtoyDiskNum
= DiskExtent
.DiskNumber
;
2534 if (CheckVentoyDisk(VtoyDiskNum
))
2536 Log("Disk check OK %C: %u", VtoyLetter
, VtoyDiskNum
);
2540 Log("Failed to check ventoy disk %u", VtoyDiskNum
);
2544 g_vtoy_disk_drive
= VtoyDiskNum
;
2546 Drives
= GetLogicalDrives();
2547 Log("Drives before mount: 0x%x", Drives
);
2549 if (VentoyIsLenovoRecovery(IsoPath
, VTLRIPath
))
2551 Log("This is lenovo recovery image, mount VTLRI file.");
2552 rc
= MountVTLRI(VTLRIPath
, VtoyDiskNum
);
2556 Log("This is normal image, mount ISO file.");
2557 rc
= MountIsoFile(IsoPath
, VtoyDiskNum
);
2560 NewDrives
= GetLogicalDrives();
2561 Log("Drives after mount: 0x%x (0x%x)", NewDrives
, (NewDrives
^ Drives
));
2564 NewDrives
= (NewDrives
^ Drives
);
2567 if (NewDrives
& 0x01)
2569 if ((NewDrives
>> 1) == 0)
2571 Log("The ISO file is mounted at %C:", MntLetter
);
2575 Log("Maybe the ISO file is mounted at %C:", MntLetter
);
2584 Log("Mount ISO FILE: %s", rc
== 0 ? "SUCCESS" : "FAILED");
2586 //Windows 11 bypass check
2587 if (g_windows_data
.windows11_bypass_check
== 1 || g_windows_data
.windows11_bypass_nro
== 1)
2589 Windows11Bypass(IsoPath
, MntLetter
, g_windows_data
.windows11_bypass_check
, g_windows_data
.windows11_bypass_nro
);
2593 rc
= DeleteVentoyPart2MountPoint(VtoyDiskNum
);
2594 Log("Delete ventoy mountpoint: %s", rc
== 0 ? "SUCCESS" : "NO NEED");
2596 if (g_windows_data
.auto_install_script
[0])
2598 if (IsFileExist("%s", VTOY_AUTO_FILE
))
2600 Log("use auto install script %s...", VTOY_AUTO_FILE
);
2601 ProcessUnattendedInstallation(VTOY_AUTO_FILE
, VtoyDiskNum
);
2605 Log("auto install script %s not exist", IsoPath
);
2610 Log("auto install no need");
2613 if (g_windows_data
.injection_archive
[0])
2615 sprintf_s(IsoPath
, sizeof(IsoPath
), "%C:%s", VtoyLetter
, g_windows_data
.injection_archive
);
2616 if (IsFileExist("%s", IsoPath
))
2618 Log("decompress injection archive %s...", IsoPath
);
2619 DecompressInjectionArchive(IsoPath
, VtoyDiskNum
);
2621 if (IsFileExist("%s", AUTO_RUN_BAT
))
2624 DWORD flags
= CREATE_NO_WINDOW
;
2627 PROCESS_INFORMATION Pi
;
2628 SECURITY_ATTRIBUTES Sa
= { sizeof(SECURITY_ATTRIBUTES
), NULL
, TRUE
};
2630 Log("%s exist, now run it...", AUTO_RUN_BAT
);
2632 GetStartupInfoA(&Si
);
2634 hOut
= CreateFileA(AUTO_RUN_LOG
,
2636 FILE_SHARE_WRITE
| FILE_SHARE_READ
,
2639 FILE_ATTRIBUTE_NORMAL
,
2642 Si
.dwFlags
|= STARTF_USESTDHANDLES
;
2643 if (hOut
!= INVALID_HANDLE_VALUE
)
2645 Si
.hStdError
= hOut
;
2646 Si
.hStdOutput
= hOut
;
2649 sprintf_s(IsoPath
, sizeof(IsoPath
), "%C:\\%s", Letter
, param
->vtoy_img_path
);
2650 sprintf_s(StrBuf
, sizeof(StrBuf
), "cmd.exe /c %s \"%s\" %C", AUTO_RUN_BAT
, IsoPath
, MntLetter
);
2651 CreateProcessA(NULL
, StrBuf
, NULL
, NULL
, TRUE
, flags
, NULL
, NULL
, &Si
, &Pi
);
2652 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
2654 SAFE_CLOSE_HANDLE(hOut
);
2658 Log("%s not exist...", AUTO_RUN_BAT
);
2663 Log("injection archive %s not exist", IsoPath
);
2668 Log("no injection archive found");
2674 static int ExtractWindowsDataFile(char *databuf
)
2677 char *filedata
= NULL
;
2678 ventoy_windows_data
*pdata
= (ventoy_windows_data
*)databuf
;
2680 Log("ExtractWindowsDataFile: auto install <%s:%d>", pdata
->auto_install_script
, pdata
->auto_install_len
);
2682 filedata
= databuf
+ sizeof(ventoy_windows_data
);
2684 if (pdata
->auto_install_script
[0] && pdata
->auto_install_len
> 0)
2686 SaveBuffer2File(VTOY_AUTO_FILE
, filedata
, pdata
->auto_install_len
);
2687 filedata
+= pdata
->auto_install_len
;
2688 len
= pdata
->auto_install_len
;
2694 static int ventoy_check_create_directory(void)
2696 if (IsDirExist("ventoy"))
2698 Log("ventoy directory already exist");
2702 Log("ventoy directory not exist, now create it.");
2703 if (!CreateDirectoryA("ventoy", NULL
))
2705 Log("Failed to create ventoy directory err:%u", GetLastError());
2713 int VentoyJump(INT argc
, CHAR
**argv
, CHAR
*LunchFile
)
2721 DWORD LockStatus
= 0;
2722 BYTE
*Buffer
= NULL
;
2723 CHAR ExeFileName
[MAX_PATH
];
2725 sprintf_s(ExeFileName
, sizeof(ExeFileName
), "%s", argv
[0]);
2726 if (!IsFileExist("%s", ExeFileName
))
2728 Log("File %s NOT exist, now try %s.exe", ExeFileName
, ExeFileName
);
2729 sprintf_s(ExeFileName
, sizeof(ExeFileName
), "%s.exe", argv
[0]);
2731 Log("File %s exist ? %s", ExeFileName
, IsFileExist("%s", ExeFileName
) ? "YES" : "NO");
2734 if (ReadWholeFile2Buf(ExeFileName
, (void **)&Buffer
, &FileSize
))
2739 Log("VentoyJump %dbit", g_system_bit
);
2741 MUTEX_LOCK(g_vtoyins_mutex
);
2742 stat
= ventoy_check_create_directory();
2743 MUTEX_UNLOCK(g_vtoyins_mutex
);
2750 for (PeStart
= 0; PeStart
< FileSize
; PeStart
+= 16)
2752 if (CheckOsParam((ventoy_os_param
*)(Buffer
+ PeStart
)) &&
2753 CheckPeHead(Buffer
, FileSize
, PeStart
+ sizeof(ventoy_os_param
)))
2755 Log("Find os pararm at %u", PeStart
);
2757 memcpy(&g_os_param
, Buffer
+ PeStart
, sizeof(ventoy_os_param
));
2758 memcpy(&g_windows_data
, Buffer
+ PeStart
+ sizeof(ventoy_os_param
), sizeof(ventoy_windows_data
));
2759 exlen
= ExtractWindowsDataFile(Buffer
+ PeStart
+ sizeof(ventoy_os_param
));
2760 memcpy(g_os_param_reserved
, g_os_param
.vtoy_reserved
, sizeof(g_os_param_reserved
));
2762 if (g_os_param_reserved
[0] == 1)
2764 Log("break here for debug .....");
2769 for (Pos
= 0; Pos
< sizeof(g_os_param
.vtoy_img_path
) && g_os_param
.vtoy_img_path
[Pos
]; Pos
++)
2771 if (g_os_param
.vtoy_img_path
[Pos
] == '/')
2773 g_os_param
.vtoy_img_path
[Pos
] = '\\';
2777 PeStart
+= sizeof(ventoy_os_param
) + sizeof(ventoy_windows_data
) + exlen
;
2778 sprintf_s(LunchFile
, MAX_PATH
, "ventoy\\%s", GetFileNameInPath(ExeFileName
));
2780 MUTEX_LOCK(g_vtoyins_mutex
);
2781 if (IsFileExist("%s", LunchFile
))
2783 Log("vtoyjump multiple call ...");
2785 MUTEX_UNLOCK(g_vtoyins_mutex
);
2789 SaveBuffer2File(LunchFile
, Buffer
+ PeStart
, FileSize
- PeStart
);
2790 MUTEX_UNLOCK(g_vtoyins_mutex
);
2796 if (PeStart
>= FileSize
)
2798 Log("OS param not found");
2802 if (g_os_param_reserved
[0] == 2)
2804 Log("skip hook for debug .....");
2809 rc
= VentoyHook(&g_os_param
);
2822 int real_main(int argc
, char **argv
)
2826 CHAR NewFile
[MAX_PATH
];
2827 CHAR LunchFile
[MAX_PATH
];
2828 CHAR CallParam
[1024] = { 0 };
2830 PROCESS_INFORMATION Pi
;
2832 Log("#### real_main #### argc = %d", argc
);
2833 Log("program full path: <%s>", g_prog_full_path
);
2834 Log("program dir: <%s>", g_prog_dir
);
2835 Log("program name: <%s>", g_prog_name
);
2837 Log("argc = %d", argc
);
2838 for (i
= 0; i
< argc
; i
++)
2840 Log("argv[%d]=<%s>", i
, argv
[i
]);
2843 strcat_s(CallParam
, sizeof(CallParam
), " ");
2844 strcat_s(CallParam
, sizeof(CallParam
), argv
[i
]);
2848 GetStartupInfoA(&Si
);
2849 memset(LunchFile
, 0, sizeof(LunchFile
));
2851 rc
= VentoyJump(argc
, argv
, LunchFile
);
2853 Log("LunchFile=<%s> CallParam=<%s>", LunchFile
, CallParam
);
2855 if (_stricmp(g_prog_name
, "winpeshl.exe") != 0 && IsFileExist("ventoy\\%s", g_prog_name
))
2857 sprintf_s(NewFile
, sizeof(NewFile
), "%s\\VTOYJUMP.EXE", g_prog_dir
);
2858 MoveFileA(g_prog_full_path
, NewFile
);
2859 Log("Move <%s> to <%s>", g_prog_full_path
, NewFile
);
2861 sprintf_s(NewFile
, sizeof(NewFile
), "ventoy\\%s", g_prog_name
);
2862 CopyFileA(NewFile
, g_prog_full_path
, TRUE
);
2863 Log("Copy <%s> to <%s>", NewFile
, g_prog_full_path
);
2865 sprintf_s(LunchFile
, sizeof(LunchFile
), "%s", g_prog_full_path
);
2866 Log("Final lunchFile is <%s>", LunchFile
);
2870 Log("We don't need to recover original <%s>", g_prog_name
);
2873 if (g_os_param_reserved
[0] == 3)
2875 Log("Open log for debug ...");
2876 sprintf_s(LunchFile
, sizeof(LunchFile
), "%s", "notepad.exe ventoy.log");
2882 strcat_s(LunchFile
, sizeof(LunchFile
), CallParam
);
2884 else if (NULL
== strstr(LunchFile
, "setup.exe"))
2886 Log("Not setup.exe, hide windows.");
2887 Si
.dwFlags
|= STARTF_USESHOWWINDOW
;
2888 Si
.wShowWindow
= SW_HIDE
;
2891 Log("Ventoy jump %s ...", rc
== 0 ? "success" : "failed");
2894 Log("Now launch <%s> ...", LunchFile
);
2896 if (g_os_param_reserved
[0] == 4)
2898 Log("Open cmd for debug ...");
2899 Si
.dwFlags
|= STARTF_USESHOWWINDOW
;
2900 Si
.wShowWindow
= SW_NORMAL
;
2901 sprintf_s(LunchFile
, sizeof(LunchFile
), "%s", "cmd.exe");
2904 Log("Backup log at this point");
2905 CopyFileA(LOG_FILE
, "X:\\Windows\\ventoy.backup", TRUE
);
2907 CreateProcessA(NULL
, LunchFile
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
2909 for (i
= 0; rc
&& i
< 1800; i
++)
2911 Log("Ventoy hook failed, now wait and retry ...");
2913 rc
= VentoyHook(&g_os_param
);
2916 Log("Wait process...");
2917 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
2919 Log("vtoyjump finished");
2923 static void VentoyToUpper(CHAR
*str
)
2926 for (i
= 0; str
[i
]; i
++)
2928 str
[i
] = (CHAR
)toupper(str
[i
]);
2932 static int vtoy_remove_duplicate_file(char *File
)
2934 CHAR szCmd
[MAX_PATH
];
2935 CHAR NewFile
[MAX_PATH
];
2937 PROCESS_INFORMATION Pi
;
2939 Log("<1> Copy New file", File
);
2940 sprintf_s(NewFile
, sizeof(NewFile
), "%s_NEW", File
);
2941 CopyFileA(File
, NewFile
, FALSE
);
2943 Log("<2> Remove file <%s>", File
);
2944 GetStartupInfoA(&Si
);
2945 Si
.dwFlags
|= STARTF_USESHOWWINDOW
;
2946 Si
.wShowWindow
= SW_HIDE
;
2947 sprintf_s(szCmd
, sizeof(szCmd
), "cmd.exe /c del /F /Q %s", File
);
2948 CreateProcessA(NULL
, szCmd
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
2949 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
2951 Log("<3> Copy back file <%s>", File
);
2952 MoveFileA(NewFile
, File
);
2957 static int VTLRI_ServiceMain(int argc
, char **argv
)
2965 PROCESS_INFORMATION Pi
;
2968 //XXX.exe VTLRI_SRV D Z
2969 Log("VTLRI_ServiceMain start %s %s %s ...", argv
[0], argv
[1], argv
[2]);
2971 sprintf_s(Drive
, sizeof(Drive
), "%C:\\", argv
[2][0]);
2975 bRet
= GetVolumeInformationA(Drive
, NULL
, 0, NULL
, NULL
, NULL
, FsType
, sizeof(FsType
));
2983 if (Err
== ERROR_PATH_NOT_FOUND
)
2985 Log("%s not found", Drive
);
2991 sprintf_s(Cmdline
, sizeof(Cmdline
), "ventoy\\imdisk.exe -d -m %C:", argv
[3][0]);
2992 Log("Remove disk by <%s>", Cmdline
);
2994 GetStartupInfoA(&Si
);
2995 Si
.dwFlags
|= STARTF_USESHOWWINDOW
;
2996 Si
.wShowWindow
= SW_HIDE
;
2998 CreateProcessA(NULL
, Cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
2999 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
3003 int main(int argc
, char **argv
)
3007 PROCESS_INFORMATION Pi
;
3008 CHAR CurDir
[MAX_PATH
];
3009 CHAR NewArgv0
[MAX_PATH
];
3010 CHAR CallParam
[1024] = { 0 };
3012 g_vtoylog_mutex
= CreateMutexA(NULL
, FALSE
, "VTOYLOG_LOCK");
3013 g_vtoyins_mutex
= CreateMutexA(NULL
, FALSE
, "VTOYINS_LOCK");
3015 Log("######## VentoyJump %dbit ##########", g_system_bit
);
3017 if (argc
> 1 && strcmp(argv
[1], "VTLRI_SRV") == 0)
3019 return VTLRI_ServiceMain(argc
, argv
);
3022 GetCurrentDirectoryA(sizeof(CurDir
), CurDir
);
3023 Log("Current directory is <%s>", CurDir
);
3025 GetModuleFileNameA(NULL
, g_prog_full_path
, MAX_PATH
);
3026 split_path_name(g_prog_full_path
, g_prog_dir
, g_prog_name
);
3028 Log("EXE path: <%s> dir:<%s> name:<%s>", g_prog_full_path
, g_prog_dir
, g_prog_name
);
3030 if (IsFileExist(WIMBOOT_FILE
))
3032 Log("This is wimboot mode ...");
3033 g_wimboot_mode
= TRUE
;
3035 if (!IsFileExist(WIMBOOT_DONE
))
3037 vtoy_remove_duplicate_file(g_prog_full_path
);
3038 SaveBuffer2File(WIMBOOT_DONE
, g_prog_full_path
, 1);
3043 Log("This is normal mode ...");
3046 if (_stricmp(g_prog_name
, "WinLogon.exe") == 0)
3048 Log("This time is rejump back ...");
3050 strcpy_s(g_prog_full_path
, sizeof(g_prog_full_path
), argv
[1]);
3051 split_path_name(g_prog_full_path
, g_prog_dir
, g_prog_name
);
3053 return real_main(argc
- 1, argv
+ 1);
3055 else if (_stricmp(g_prog_name
, "PECMD.exe") == 0)
3057 strcpy_s(NewArgv0
, sizeof(NewArgv0
), g_prog_dir
);
3058 VentoyToUpper(NewArgv0
);
3060 if (NULL
== strstr(NewArgv0
, "SYSTEM32") && IsFileExist(ORG_PECMD_BK_PATH
))
3062 Log("Just call original pecmd.exe");
3063 strcpy_s(CallParam
, sizeof(CallParam
), ORG_PECMD_PATH
);
3067 Log("We need to rejump for pecmd ...");
3069 ventoy_check_create_directory();
3070 CopyFileA(g_prog_full_path
, "ventoy\\WinLogon.exe", TRUE
);
3072 sprintf_s(CallParam
, sizeof(CallParam
), "ventoy\\WinLogon.exe %s", g_prog_full_path
);
3075 for (i
= 1; i
< argc
; i
++)
3077 strcat_s(CallParam
, sizeof(CallParam
), " ");
3078 strcat_s(CallParam
, sizeof(CallParam
), argv
[i
]);
3081 Log("Now rejump to <%s> ...", CallParam
);
3082 GetStartupInfoA(&Si
);
3083 CreateProcessA(NULL
, CallParam
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
3085 Log("Wait rejump process...");
3086 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
3087 Log("rejump finished");
3092 Log("We don't need to rejump ...");
3094 ventoy_check_create_directory();
3095 strcpy_s(NewArgv0
, sizeof(NewArgv0
), g_prog_full_path
);
3098 return real_main(argc
, argv
);