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 CHAR g_prog_full_path
[MAX_PATH
];
40 static CHAR g_prog_dir
[MAX_PATH
];
41 static CHAR g_prog_name
[MAX_PATH
];
43 #define VTOY_PECMD_PATH "X:\\Windows\\system32\\ventoy\\PECMD.EXE"
44 #define ORG_PECMD_PATH "X:\\Windows\\system32\\PECMD.EXE"
45 #define ORG_PECMD_BK_PATH "X:\\Windows\\system32\\PECMD.EXE_BACK.EXE"
47 #define AUTO_RUN_BAT "X:\\VentoyAutoRun.bat"
48 #define AUTO_RUN_LOG "X:\\VentoyAutoRun.log"
50 #define VTOY_AUTO_FILE "X:\\_vtoy_auto_install"
52 #define LOG_FILE "X:\\Windows\\system32\\ventoy.log"
53 #define MUTEX_LOCK(hmutex) if (hmutex != NULL) LockStatus = WaitForSingleObject(hmutex, INFINITE)
54 #define MUTEX_UNLOCK(hmutex) if (hmutex != NULL && WAIT_OBJECT_0 == LockStatus) ReleaseMutex(hmutex)
56 static const char * GetFileNameInPath(const char *fullpath
)
60 if (strstr(fullpath
, ":"))
62 for (i
= (int)strlen(fullpath
); i
> 0; i
--)
64 if (fullpath
[i
- 1] == '/' || fullpath
[i
- 1] == '\\')
74 static int split_path_name(char *fullpath
, char *dir
, char *name
)
79 Pos
= (CHAR
*)GetFileNameInPath(fullpath
);
81 strcpy_s(name
, MAX_PATH
, Pos
);
85 strcpy_s(dir
, MAX_PATH
, fullpath
);
92 void Log(const char *Fmt
, ...)
100 DWORD PID
= GetCurrentProcessId();
103 Len
+= sprintf_s(szBuf
, sizeof(szBuf
),
104 "[%4d/%02d/%02d %02d:%02d:%02d.%03d] [%u] ",
105 Sys
.wYear
, Sys
.wMonth
, Sys
.wDay
,
106 Sys
.wHour
, Sys
.wMinute
, Sys
.wSecond
,
107 Sys
.wMilliseconds
, PID
);
110 Len
+= vsnprintf_s(szBuf
+ Len
, sizeof(szBuf
)-Len
, sizeof(szBuf
)-Len
, Fmt
, Arg
);
113 MUTEX_LOCK(g_vtoylog_mutex
);
115 fopen_s(&File
, LOG_FILE
, "a+");
118 fwrite(szBuf
, 1, Len
, File
);
119 fwrite("\n", 1, 1, File
);
123 MUTEX_UNLOCK(g_vtoylog_mutex
);
127 static int LoadNtDriver(const char *DrvBinPath
)
133 SC_HANDLE hServiceMgr
;
135 char name
[256] = { 0 };
137 for (i
= (int)strlen(DrvBinPath
) - 1; i
>= 0; i
--)
139 if (DrvBinPath
[i
] == '\\' || DrvBinPath
[i
] == '/')
141 sprintf_s(name
, sizeof(name
), "%s", DrvBinPath
+ i
+ 1);
146 Log("Load NT driver: %s %s", DrvBinPath
, name
);
148 hServiceMgr
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_ALL_ACCESS
);
149 if (hServiceMgr
== NULL
)
151 Log("OpenSCManager failed Error:%u", GetLastError());
155 Log("OpenSCManager OK");
157 hService
= CreateServiceA(hServiceMgr
,
161 SERVICE_KERNEL_DRIVER
,
162 SERVICE_DEMAND_START
,
163 SERVICE_ERROR_NORMAL
,
165 NULL
, NULL
, NULL
, NULL
, NULL
);
166 if (hService
== NULL
)
168 Status
= GetLastError();
169 if (Status
!= ERROR_IO_PENDING
&& Status
!= ERROR_SERVICE_EXISTS
)
171 Log("CreateService failed v %u", Status
);
172 CloseServiceHandle(hServiceMgr
);
176 hService
= OpenServiceA(hServiceMgr
, name
, SERVICE_ALL_ACCESS
);
177 if (hService
== NULL
)
179 Log("OpenService failed %u", Status
);
180 CloseServiceHandle(hServiceMgr
);
185 Log("CreateService imdisk OK");
187 Ret
= StartServiceA(hService
, 0, NULL
);
190 Log("StartService OK");
194 Status
= GetLastError();
195 if (Status
== ERROR_SERVICE_ALREADY_RUNNING
)
201 Log("StartService error %u", Status
);
206 CloseServiceHandle(hService
);
207 CloseServiceHandle(hServiceMgr
);
209 Log("Load NT driver %s", rc
? "failed" : "success");
214 static int ReadWholeFile2Buf(const char *Fullpath
, void **Data
, DWORD
*Size
)
222 Log("ReadWholeFile2Buf <%s>", Fullpath
);
224 Handle
= CreateFileA(Fullpath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
225 if (Handle
== INVALID_HANDLE_VALUE
)
227 Log("Could not open the file<%s>, error:%u", Fullpath
, GetLastError());
231 FileSize
= SetFilePointer(Handle
, 0, NULL
, FILE_END
);
233 Buffer
= malloc(FileSize
);
236 Log("Failed to alloc memory size:%u", FileSize
);
240 SetFilePointer(Handle
, 0, NULL
, FILE_BEGIN
);
241 if (!ReadFile(Handle
, Buffer
, FileSize
, &dwSize
, NULL
))
243 Log("ReadFile failed, dwSize:%u error:%u", dwSize
, GetLastError());
250 Log("Success read file size:%u", FileSize
);
255 SAFE_CLOSE_HANDLE(Handle
);
260 static BOOL
CheckPeHead(BYTE
*Buffer
, DWORD Size
, DWORD Offset
)
265 ventoy_windows_data
*pdata
= NULL
;
267 Head
= Buffer
+ Offset
;
268 pdata
= (ventoy_windows_data
*)Head
;
269 Head
+= sizeof(ventoy_windows_data
);
271 if (pdata
->auto_install_script
[0] && pdata
->auto_install_len
> 0)
273 End
= Offset
+ sizeof(ventoy_windows_data
) + pdata
->auto_install_len
+ 60;
276 Head
+= pdata
->auto_install_len
;
280 if (Head
[0] != 'M' || Head
[1] != 'Z')
285 PeOffset
= *(UINT32
*)(Head
+ 60);
286 if (*(UINT32
*)(Head
+ PeOffset
) != 0x00004550)
295 static BOOL
CheckOsParam(ventoy_os_param
*param
)
300 if (memcmp(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
)))
305 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
307 Sum
+= *((BYTE
*)param
+ i
);
315 if (param
->vtoy_img_location_addr
% 4096)
323 static int SaveBuffer2File(const char *Fullpath
, void *Buffer
, DWORD Length
)
329 Log("SaveBuffer2File <%s> len:%u", Fullpath
, Length
);
331 Handle
= CreateFileA(Fullpath
, GENERIC_READ
| GENERIC_WRITE
,
332 FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, CREATE_NEW
, 0, 0);
333 if (Handle
== INVALID_HANDLE_VALUE
)
335 Log("Could not create new file, error:%u", GetLastError());
339 WriteFile(Handle
, Buffer
, Length
, &dwSize
, NULL
);
344 SAFE_CLOSE_HANDLE(Handle
);
349 static int IsUTF8Encode(const char *src
)
352 const UCHAR
*Byte
= (const UCHAR
*)src
;
354 for (i
= 0; i
< MAX_PATH
&& Byte
[i
]; i
++)
365 static int Utf8ToUtf16(const char* src
, WCHAR
* dst
)
367 int size
= MultiByteToWideChar(CP_UTF8
, 0, src
, -1, dst
, 0);
368 return MultiByteToWideChar(CP_UTF8
, 0, src
, -1, dst
, size
+ 1);
371 static BOOL
IsDirExist(const char *Fmt
, ...)
376 CHAR FilePathA
[MAX_PATH
];
377 WCHAR FilePathW
[MAX_PATH
];
380 vsnprintf_s(FilePathA
, sizeof(FilePathA
), sizeof(FilePathA
), Fmt
, Arg
);
383 UTF8
= IsUTF8Encode(FilePathA
);
387 Utf8ToUtf16(FilePathA
, FilePathW
);
388 Attr
= GetFileAttributesW(FilePathW
);
392 Attr
= GetFileAttributesA(FilePathA
);
395 if (Attr
!= INVALID_FILE_ATTRIBUTES
&& (Attr
& FILE_ATTRIBUTE_DIRECTORY
))
403 static BOOL
IsFileExist(const char *Fmt
, ...)
410 CHAR FilePathA
[MAX_PATH
];
411 WCHAR FilePathW
[MAX_PATH
];
414 vsnprintf_s(FilePathA
, sizeof(FilePathA
), sizeof(FilePathA
), Fmt
, Arg
);
417 UTF8
= IsUTF8Encode(FilePathA
);
421 Utf8ToUtf16(FilePathA
, FilePathW
);
422 hFile
= CreateFileW(FilePathW
, FILE_READ_EA
, FILE_SHARE_READ
, 0, OPEN_EXISTING
, 0, 0);
426 hFile
= CreateFileA(FilePathA
, FILE_READ_EA
, FILE_SHARE_READ
, 0, OPEN_EXISTING
, 0, 0);
428 if (INVALID_HANDLE_VALUE
== hFile
)
437 Attr
= GetFileAttributesW(FilePathW
);
441 Attr
= GetFileAttributesA(FilePathA
);
444 if (Attr
& FILE_ATTRIBUTE_DIRECTORY
)
452 Log("File <%s> %s", FilePathA
, (bRet
? "exist" : "NOT exist"));
456 static int GetPhyDiskUUID(const char LogicalDrive
, UINT8
*UUID
, UINT32
*DiskSig
, DISK_EXTENT
*DiskExtent
)
461 VOLUME_DISK_EXTENTS DiskExtents
;
463 UINT8 SectorBuf
[512];
465 Log("GetPhyDiskUUID %C", LogicalDrive
);
467 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\%C:", LogicalDrive
);
468 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
469 if (Handle
== INVALID_HANDLE_VALUE
)
471 Log("Could not open the disk<%s>, error:%u", PhyPath
, GetLastError());
475 Ret
= DeviceIoControl(Handle
,
476 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
480 (DWORD
)(sizeof(DiskExtents
)),
483 if (!Ret
|| DiskExtents
.NumberOfDiskExtents
== 0)
485 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed, error:%u", GetLastError());
491 memcpy(DiskExtent
, DiskExtents
.Extents
, sizeof(DISK_EXTENT
));
492 Log("%C: is in PhysicalDrive%d Offset:%llu", LogicalDrive
, DiskExtents
.Extents
[0].DiskNumber
,
493 (ULONGLONG
)(DiskExtents
.Extents
[0].StartingOffset
.QuadPart
));
495 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\PhysicalDrive%d", DiskExtents
.Extents
[0].DiskNumber
);
496 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
497 if (Handle
== INVALID_HANDLE_VALUE
)
499 Log("Could not open the disk<%s>, error:%u", PhyPath
, GetLastError());
503 if (!ReadFile(Handle
, SectorBuf
, sizeof(SectorBuf
), &dwSize
, NULL
))
505 Log("ReadFile failed, dwSize:%u error:%u", dwSize
, GetLastError());
510 memcpy(UUID
, SectorBuf
+ 0x180, 16);
513 memcpy(DiskSig
, SectorBuf
+ 0x1B8, 4);
520 static int VentoyMountAnywhere(HANDLE Handle
)
523 ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters
;
525 Log("VentoyMountAnywhere");
527 memset(&AttachParameters
, 0, sizeof(AttachParameters
));
528 AttachParameters
.Version
= ATTACH_VIRTUAL_DISK_VERSION_1
;
530 Status
= AttachVirtualDisk(Handle
, NULL
, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY
| ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME
, 0, &AttachParameters
, NULL
);
531 if (Status
!= ERROR_SUCCESS
)
533 Log("Failed to attach virtual disk ErrorCode:%u", Status
);
540 int VentoyMountY(HANDLE Handle
)
545 DWORD physicalDriveNameSize
;
547 WCHAR physicalDriveName
[MAX_PATH
];
548 CHAR physicalDriveNameA
[MAX_PATH
];
549 CHAR cdromDriveName
[MAX_PATH
];
550 ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters
;
554 memset(&AttachParameters
, 0, sizeof(AttachParameters
));
555 AttachParameters
.Version
= ATTACH_VIRTUAL_DISK_VERSION_1
;
557 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
);
558 if (Status
!= ERROR_SUCCESS
)
560 Log("Failed to attach virtual disk ErrorCode:%u", Status
);
564 memset(physicalDriveName
, 0, sizeof(physicalDriveName
));
565 memset(physicalDriveNameA
, 0, sizeof(physicalDriveNameA
));
567 physicalDriveNameSize
= MAX_PATH
;
568 Status
= GetVirtualDiskPhysicalPath(Handle
, &physicalDriveNameSize
, physicalDriveName
);
569 if (Status
!= ERROR_SUCCESS
)
571 Log("Failed GetVirtualDiskPhysicalPath ErrorCode:%u", Status
);
575 for (i
= 0; physicalDriveName
[i
]; i
++)
577 physicalDriveNameA
[i
] = (CHAR
)toupper((CHAR
)(physicalDriveName
[i
]));
580 Log("physicalDriveNameA=<%s>", physicalDriveNameA
);
582 Pos
= strstr(physicalDriveNameA
, "CDROM");
585 Log("Not cdrom phy drive");
589 sprintf_s(cdromDriveName
, sizeof(cdromDriveName
), "\\Device\\%s", Pos
);
590 Log("cdromDriveName=<%s>", cdromDriveName
);
592 for (i
= 0; i
< 3 && (bRet
== FALSE
); i
++)
595 bRet
= DefineDosDeviceA(DDD_RAW_TARGET_PATH
, "Y:", cdromDriveName
);
596 Log("DefineDosDeviceA %s", bRet
? "success" : "failed");
602 static BOOL
VentoyAPINeedMountY(const char *IsoPath
)
610 static int VentoyAttachVirtualDisk(HANDLE Handle
, const char *IsoPath
)
615 Drives
= GetLogicalDrives();
616 if ((1 << 24) & Drives
)
618 Log("Y: is occupied");
623 Log("Y: is free now");
627 if (DriveYFree
&& VentoyAPINeedMountY(IsoPath
))
629 return VentoyMountY(Handle
);
633 return VentoyMountAnywhere(Handle
);
637 int VentoyMountISOByAPI(const char *IsoPath
)
642 WCHAR wFilePath
[512] = { 0 };
643 VIRTUAL_STORAGE_TYPE StorageType
;
644 OPEN_VIRTUAL_DISK_PARAMETERS OpenParameters
;
646 Log("VentoyMountISOByAPI <%s>", IsoPath
);
648 if (IsUTF8Encode(IsoPath
))
650 Log("This is UTF8 encoding");
651 MultiByteToWideChar(CP_UTF8
, 0, IsoPath
, (int)strlen(IsoPath
), wFilePath
, (int)(sizeof(wFilePath
) / sizeof(WCHAR
)));
655 Log("This is ANSI encoding");
656 MultiByteToWideChar(CP_ACP
, 0, IsoPath
, (int)strlen(IsoPath
), wFilePath
, (int)(sizeof(wFilePath
) / sizeof(WCHAR
)));
659 memset(&StorageType
, 0, sizeof(StorageType
));
660 memset(&OpenParameters
, 0, sizeof(OpenParameters
));
662 OpenParameters
.Version
= OPEN_VIRTUAL_DISK_VERSION_1
;
664 for (i
= 0; i
< 10; i
++)
666 Status
= OpenVirtualDisk(&StorageType
, wFilePath
, VIRTUAL_DISK_ACCESS_READ
, 0, &OpenParameters
, &Handle
);
667 if (ERROR_FILE_NOT_FOUND
== Status
|| ERROR_PATH_NOT_FOUND
== Status
)
669 Log("OpenVirtualDisk ErrorCode:%u, now wait and retry...", Status
);
674 if (ERROR_SUCCESS
== Status
)
676 Log("OpenVirtualDisk success");
678 else if (ERROR_VIRTDISK_PROVIDER_NOT_FOUND
== Status
)
680 Log("VirtualDisk for ISO file is not supported in current system");
684 Log("Failed to open virtual disk ErrorCode:%u", Status
);
690 if (Status
!= ERROR_SUCCESS
)
695 Log("OpenVirtualDisk success");
697 Status
= VentoyAttachVirtualDisk(Handle
, IsoPath
);
698 if (Status
!= ERROR_SUCCESS
)
700 Log("Failed to attach virtual disk ErrorCode:%u", Status
);
705 Log("VentoyAttachVirtualDisk success");
712 static HANDLE g_FatPhyDrive
;
713 static UINT64 g_Part2StartSec
;
715 static int CopyFileFromFatDisk(const CHAR
* SrcFile
, const CHAR
*DstFile
)
722 Log("CopyFileFromFatDisk (%s)==>(%s)", SrcFile
, DstFile
);
724 flfile
= fl_fopen(SrcFile
, "rb");
727 fl_fseek(flfile
, 0, SEEK_END
);
728 size
= (int)fl_ftell(flfile
);
729 fl_fseek(flfile
, 0, SEEK_SET
);
731 buf
= (char *)malloc(size
);
734 fl_fread(buf
, 1, size
, flfile
);
737 SaveBuffer2File(DstFile
, buf
, size
);
747 static int VentoyFatDiskRead(uint32 Sector
, uint8
*Buffer
, uint32 SectorCount
)
752 LARGE_INTEGER liCurrentPosition
;
754 liCurrentPosition
.QuadPart
= Sector
+ g_Part2StartSec
;
755 liCurrentPosition
.QuadPart
*= 512;
756 SetFilePointerEx(g_FatPhyDrive
, liCurrentPosition
, &liCurrentPosition
, FILE_BEGIN
);
758 ReadSize
= (DWORD
)(SectorCount
* 512);
760 bRet
= ReadFile(g_FatPhyDrive
, Buffer
, ReadSize
, &dwSize
, NULL
);
761 if (bRet
== FALSE
|| dwSize
!= ReadSize
)
763 Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet
, ReadSize
, dwSize
, GetLastError());
769 static BOOL
Is2K10PE(void)
775 fopen_s(&fp
, "X:\\Windows\\System32\\PECMD.INI", "r");
781 memset(szLine
, 0, sizeof(szLine
));
782 while (fgets(szLine
, sizeof(szLine
) - 1, fp
))
784 if (strstr(szLine
, "2k10\\"))
795 static CHAR
GetIMDiskMountLogicalDrive(void)
799 DWORD Mask
= 0x1000000;
801 // fixed use M as mountpoint for 2K10 PE
804 Log("Use M: for 2K10 PE");
808 Drives
= GetLogicalDrives();
809 Log("Drives=0x%x", Drives
);
813 if ((Drives
& Mask
) == 0)
825 UINT64
GetVentoyEfiPartStartSector(HANDLE hDrive
)
830 VTOY_GPT_INFO
*pGpt
= NULL
;
831 UINT64 StartSector
= 0;
833 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
835 bRet
= ReadFile(hDrive
, &MBR
, sizeof(MBR
), &dwSize
, NULL
);
836 Log("Read MBR Ret:%u Size:%u code:%u", bRet
, dwSize
, LASTERR
);
838 if ((!bRet
) || (dwSize
!= sizeof(MBR
)))
843 if (MBR
.PartTbl
[0].FsFlag
== 0xEE)
845 Log("GPT partition style");
847 pGpt
= malloc(sizeof(VTOY_GPT_INFO
));
853 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
854 bRet
= ReadFile(hDrive
, pGpt
, sizeof(VTOY_GPT_INFO
), &dwSize
, NULL
);
855 if ((!bRet
) || (dwSize
!= sizeof(VTOY_GPT_INFO
)))
857 Log("Failed to read gpt info %d %u %d", bRet
, dwSize
, LASTERR
);
861 StartSector
= pGpt
->PartTbl
[1].StartLBA
;
866 Log("MBR partition style");
867 StartSector
= MBR
.PartTbl
[1].StartSectorId
;
870 Log("GetVentoyEfiPart StartSector: %llu", StartSector
);
874 static int VentoyRunImdisk(const char *IsoPath
, const char *imdiskexe
)
879 PROCESS_INFORMATION Pi
;
881 Log("VentoyRunImdisk <%s> <%s>", IsoPath
, imdiskexe
);
883 Letter
= GetIMDiskMountLogicalDrive();
884 sprintf_s(Cmdline
, sizeof(Cmdline
), "%s -a -o ro -f \"%s\" -m %C:", imdiskexe
, IsoPath
, Letter
);
885 Log("mount iso to %C: use imdisk cmd <%s>", Letter
, Cmdline
);
887 if (IsUTF8Encode(IsoPath
))
890 GetStartupInfoW(&Si
);
891 Si
.dwFlags
|= STARTF_USESHOWWINDOW
;
892 Si
.wShowWindow
= SW_HIDE
;
894 Utf8ToUtf16(Cmdline
, CmdlineW
);
895 CreateProcessW(NULL
, CmdlineW
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
897 Log("This is UTF8 encoding");
902 GetStartupInfoA(&Si
);
903 Si
.dwFlags
|= STARTF_USESHOWWINDOW
;
904 Si
.wShowWindow
= SW_HIDE
;
906 CreateProcessA(NULL
, Cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
908 Log("This is ANSI encoding");
911 Log("Wait for imdisk process ...");
912 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
913 Log("imdisk process finished");
918 int VentoyMountISOByImdisk(const char *IsoPath
, DWORD PhyDrive
)
924 CHAR PhyPath
[MAX_PATH
];
925 GET_LENGTH_INFORMATION LengthInfo
;
927 Log("VentoyMountISOByImdisk %s", IsoPath
);
929 if (IsFileExist("X:\\Windows\\System32\\imdisk.exe"))
931 Log("imdisk.exe exist, use it directly...");
932 VentoyRunImdisk(IsoPath
, "imdisk.exe");
936 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\PhysicalDrive%d", PhyDrive
);
937 hDrive
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
938 if (hDrive
== INVALID_HANDLE_VALUE
)
940 Log("Could not open the disk<%s>, error:%u", PhyPath
, GetLastError());
944 bRet
= DeviceIoControl(hDrive
, IOCTL_DISK_GET_LENGTH_INFO
, NULL
, 0, &LengthInfo
, sizeof(LengthInfo
), &dwBytes
, NULL
);
947 Log("Could not get phy disk %s size, error:%u", PhyPath
, GetLastError());
951 g_FatPhyDrive
= hDrive
;
952 g_Part2StartSec
= GetVentoyEfiPartStartSector(hDrive
);
954 Log("Parse FAT fs...");
958 if (0 == fl_attach_media(VentoyFatDiskRead
, NULL
))
960 if (g_system_bit
== 64)
962 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.sys", "ventoy\\imdisk.sys");
963 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.exe", "ventoy\\imdisk.exe");
964 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.cpl", "ventoy\\imdisk.cpl");
968 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.sys", "ventoy\\imdisk.sys");
969 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.exe", "ventoy\\imdisk.exe");
970 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.cpl", "ventoy\\imdisk.cpl");
973 GetCurrentDirectoryA(sizeof(PhyPath
), PhyPath
);
974 strcat_s(PhyPath
, sizeof(PhyPath
), "\\ventoy\\imdisk.sys");
976 if (LoadNtDriver(PhyPath
) == 0)
978 VentoyRunImdisk(IsoPath
, "ventoy\\imdisk.exe");
986 SAFE_CLOSE_HANDLE(hDrive
);
991 static int MountIsoFile(CONST CHAR
*IsoPath
, DWORD PhyDrive
)
993 if (IsWindows8OrGreater())
995 Log("This is Windows 8 or latter...");
996 if (VentoyMountISOByAPI(IsoPath
) == 0)
998 Log("Mount iso by API success");
1003 Log("Mount iso by API failed, maybe not supported, try imdisk");
1004 return VentoyMountISOByImdisk(IsoPath
, PhyDrive
);
1009 Log("This is before Windows 8 ...");
1010 if (VentoyMountISOByImdisk(IsoPath
, PhyDrive
) == 0)
1012 Log("Mount iso by imdisk success");
1017 return VentoyMountISOByAPI(IsoPath
);
1022 static int GetPhyDriveByLogicalDrive(int DriveLetter
)
1027 VOLUME_DISK_EXTENTS DiskExtents
;
1030 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\%C:", (CHAR
)DriveLetter
);
1032 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
1033 if (Handle
== INVALID_HANDLE_VALUE
)
1035 Log("Could not open the disk<%s>, error:%u", PhyPath
, GetLastError());
1039 Ret
= DeviceIoControl(Handle
,
1040 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
1044 (DWORD
)(sizeof(DiskExtents
)),
1048 if (!Ret
|| DiskExtents
.NumberOfDiskExtents
== 0)
1050 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath
, GetLastError());
1051 SAFE_CLOSE_HANDLE(Handle
);
1054 SAFE_CLOSE_HANDLE(Handle
);
1056 Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",
1058 DiskExtents
.Extents
[0].DiskNumber
,
1059 DiskExtents
.Extents
[0].StartingOffset
.QuadPart
,
1060 DiskExtents
.Extents
[0].ExtentLength
.QuadPart
1063 return (int)DiskExtents
.Extents
[0].DiskNumber
;
1067 static int DeleteVentoyPart2MountPoint(DWORD PhyDrive
)
1072 CHAR DriveName
[] = "?:\\";
1074 Log("DeleteVentoyPart2MountPoint Phy%u ...", PhyDrive
);
1076 Drives
= GetLogicalDrives();
1079 if ((Drives
& 0x01) && IsFileExist("%C:\\ventoy\\ventoy.cpio", Letter
))
1081 Log("File %C:\\ventoy\\ventoy.cpio exist", Letter
);
1083 PhyDisk
= GetPhyDriveByLogicalDrive(Letter
);
1084 Log("PhyDisk=%u for %C", PhyDisk
, Letter
);
1086 if (PhyDisk
== PhyDrive
)
1088 DriveName
[0] = Letter
;
1089 DeleteVolumeMountPointA(DriveName
);
1101 static BOOL
check_tar_archive(const char *archive
, CHAR
*tarName
)
1105 const char *pos
= archive
;
1106 const char *slash
= archive
;
1110 if (*pos
== '\\' || *pos
== '/')
1117 len
= (int)strlen(slash
);
1119 if (len
> 7 && (strncmp(slash
+ len
- 7, ".tar.gz", 7) == 0 || strncmp(slash
+ len
- 7, ".tar.xz", 7) == 0))
1121 nameLen
= (int)sprintf_s(tarName
, MAX_PATH
, "X:%s", slash
);
1122 tarName
[nameLen
- 3] = 0;
1125 else if (len
> 8 && strncmp(slash
+ len
- 8, ".tar.bz2", 8) == 0)
1127 nameLen
= (int)sprintf_s(tarName
, MAX_PATH
, "X:%s", slash
);
1128 tarName
[nameLen
- 4] = 0;
1131 else if (len
> 9 && strncmp(slash
+ len
- 9, ".tar.lzma", 9) == 0)
1133 nameLen
= (int)sprintf_s(tarName
, MAX_PATH
, "X:%s", slash
);
1134 tarName
[nameLen
- 5] = 0;
1141 static UCHAR
*g_unxz_buffer
= NULL
;
1142 static int g_unxz_len
= 0;
1144 static void unxz_error(char *x
)
1149 static int unxz_flush(void *src
, unsigned int size
)
1151 memcpy(g_unxz_buffer
+ g_unxz_len
, src
, size
);
1152 g_unxz_len
+= (int)size
;
1157 static int DecompressInjectionArchive(const char *archive
, DWORD PhyDrive
)
1161 UCHAR
*Buffer
= NULL
;
1162 UCHAR
*RawBuffer
= NULL
;
1168 DWORD flags
= CREATE_NO_WINDOW
;
1169 CHAR StrBuf
[MAX_PATH
];
1170 CHAR tarName
[MAX_PATH
];
1172 PROCESS_INFORMATION Pi
;
1173 PROCESS_INFORMATION NewPi
;
1174 GET_LENGTH_INFORMATION LengthInfo
;
1175 SECURITY_ATTRIBUTES Sa
= { sizeof(SECURITY_ATTRIBUTES
), NULL
, TRUE
};
1177 Log("DecompressInjectionArchive %s", archive
);
1179 sprintf_s(StrBuf
, sizeof(StrBuf
), "\\\\.\\PhysicalDrive%d", PhyDrive
);
1180 hDrive
= CreateFileA(StrBuf
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
1181 if (hDrive
== INVALID_HANDLE_VALUE
)
1183 Log("Could not open the disk<%s>, error:%u", StrBuf
, GetLastError());
1187 bRet
= DeviceIoControl(hDrive
, IOCTL_DISK_GET_LENGTH_INFO
, NULL
, 0, &LengthInfo
, sizeof(LengthInfo
), &dwBytes
, NULL
);
1190 Log("Could not get phy disk %s size, error:%u", StrBuf
, GetLastError());
1194 g_FatPhyDrive
= hDrive
;
1195 g_Part2StartSec
= GetVentoyEfiPartStartSector(hDrive
);
1197 Log("Parse FAT fs...");
1201 if (0 == fl_attach_media(VentoyFatDiskRead
, NULL
))
1203 if (g_system_bit
== 64)
1205 CopyFileFromFatDisk("/ventoy/7z/64/7za.xz", "ventoy\\7za.xz");
1209 CopyFileFromFatDisk("/ventoy/7z/32/7za.xz", "ventoy\\7za.xz");
1212 ReadWholeFile2Buf("ventoy\\7za.xz", &Buffer
, &dwSize
);
1213 Log("7za.xz file size:%u", dwSize
);
1215 RawBuffer
= malloc(SIZE_1MB
* 4);
1218 g_unxz_buffer
= RawBuffer
;
1220 unxz(Buffer
, (int)dwSize
, NULL
, unxz_flush
, NULL
, &writelen
, unxz_error
);
1221 if (writelen
== (int)dwSize
)
1223 Log("Decompress success 7za.xz(%u) ---> 7za.exe(%d)", dwSize
, g_unxz_len
);
1227 Log("Decompress failed 7za.xz(%u) ---> 7za.exe(%u)", dwSize
, dwSize
);
1230 SaveBuffer2File("ventoy\\7za.exe", RawBuffer
, (DWORD
)g_unxz_len
);
1232 g_unxz_buffer
= NULL
;
1238 Log("Failed to alloc 4MB memory");
1241 sprintf_s(StrBuf
, sizeof(StrBuf
), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", archive
);
1243 Log("extract inject to X:");
1244 Log("cmdline:<%s>", StrBuf
);
1246 GetStartupInfoA(&Si
);
1248 hOut
= CreateFileA("ventoy\\7z.log",
1250 FILE_SHARE_WRITE
| FILE_SHARE_READ
,
1253 FILE_ATTRIBUTE_NORMAL
,
1256 Si
.dwFlags
|= STARTF_USESTDHANDLES
;
1258 if (hOut
!= INVALID_HANDLE_VALUE
)
1260 Si
.hStdError
= hOut
;
1261 Si
.hStdOutput
= hOut
;
1264 CreateProcessA(NULL
, StrBuf
, NULL
, NULL
, TRUE
, flags
, NULL
, NULL
, &Si
, &Pi
);
1265 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
1268 // decompress tar archive, for tar.gz/tar.xz/tar.bz2
1270 if (check_tar_archive(archive
, tarName
))
1272 Log("Decompress tar archive...<%s>", tarName
);
1274 sprintf_s(StrBuf
, sizeof(StrBuf
), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", tarName
);
1276 CreateProcessA(NULL
, StrBuf
, NULL
, NULL
, TRUE
, flags
, NULL
, NULL
, &Si
, &NewPi
);
1277 WaitForSingleObject(NewPi
.hProcess
, INFINITE
);
1279 Log("Now delete %s", tarName
);
1280 DeleteFileA(tarName
);
1283 SAFE_CLOSE_HANDLE(hOut
);
1289 SAFE_CLOSE_HANDLE(hDrive
);
1294 static int ProcessUnattendedInstallation(const char *script
)
1300 CHAR CurDir
[MAX_PATH
];
1302 Log("Copy unattended XML ...");
1304 GetCurrentDirectory(sizeof(CurDir
), CurDir
);
1306 if ((Letter
>= 'A' && Letter
<= 'Z') || (Letter
>= 'a' && Letter
<= 'z'))
1308 Log("Current Drive Letter: %C", Letter
);
1315 sprintf_s(CurDir
, sizeof(CurDir
), "%C:\\Autounattend.xml", Letter
);
1316 Log("Copy file <%s> --> <%s>", script
, CurDir
);
1317 CopyFile(script
, CurDir
, FALSE
);
1319 Ret
= RegCreateKeyEx(HKEY_LOCAL_MACHINE
, "System\\Setup", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hKey
, &dw
);
1320 if (ERROR_SUCCESS
== Ret
)
1322 Ret
= RegSetValueEx(hKey
, "UnattendFile", 0, REG_SZ
, CurDir
, (DWORD
)(strlen(CurDir
) + 1));
1328 static int Windows11BypassCheck(const char *isofile
, const char MntLetter
)
1335 CHAR
*Buffer
= NULL
;
1336 VS_FIXEDFILEINFO
* VerInfo
= NULL
;
1337 CHAR CheckFile
[MAX_PATH
];
1338 UINT16 Major
, Minor
, Build
, Revision
;
1340 Log("Windows11BypassCheck for <%s> %C:", isofile
, MntLetter
);
1342 if (FALSE
== IsFileExist("%C:\\sources\\boot.wim", MntLetter
) ||
1343 FALSE
== IsFileExist("%C:\\sources\\compatresources.dll", MntLetter
))
1345 Log("boot.wim/compatresources.dll not exist, this is not a windows install media.");
1349 if (FALSE
== IsFileExist("%C:\\sources\\install.wim", MntLetter
) &&
1350 FALSE
== IsFileExist("%C:\\sources\\install.esd", MntLetter
))
1352 Log("install.wim/install.esd not exist, this is not a windows install media.");
1356 sprintf_s(CheckFile
, sizeof(CheckFile
), "%C:\\sources\\compatresources.dll", MntLetter
);
1357 dwSize
= GetFileVersionInfoSizeA(CheckFile
, &dwHandle
);
1360 Log("Failed to get file version info size: %u", LASTERR
);
1364 Buffer
= malloc(dwSize
);
1370 if (FALSE
== GetFileVersionInfoA(CheckFile
, dwHandle
, dwSize
, Buffer
))
1372 Log("Failed to get file version info : %u", LASTERR
);
1376 if (VerQueryValueA(Buffer
, "\\", (LPVOID
)&VerInfo
, &VerLen
) && VerLen
!= 0)
1378 if (VerInfo
->dwSignature
== VS_FFI_SIGNATURE
)
1380 Major
= HIWORD(VerInfo
->dwFileVersionMS
);
1381 Minor
= LOWORD(VerInfo
->dwFileVersionMS
);
1382 Build
= HIWORD(VerInfo
->dwFileVersionLS
);
1383 Revision
= LOWORD(VerInfo
->dwFileVersionLS
);
1385 Log("FileVersionze: <%u %u %u %u>", Major
, Minor
, Build
, Revision
);
1387 if (Major
== 10 && Build
> 20000)
1394 Log("This is not Windows 11, not need to bypass.", Major
);
1400 //Now we really need to bypass windows 11 check. create registry
1402 HKEY hSubKey
= NULL
;
1405 Status
= RegCreateKeyExA(HKEY_LOCAL_MACHINE
, "System\\Setup", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hKey
, &dwSize
);
1406 if (ERROR_SUCCESS
!= Status
)
1408 Log("Failed to create reg key System\\Setup %u %u", LASTERR
, Status
);
1412 Status
= RegCreateKeyExA(hKey
, "LabConfig", 0, NULL
, 0, KEY_SET_VALUE
| KEY_QUERY_VALUE
| KEY_CREATE_SUB_KEY
, NULL
, &hSubKey
, &dwSize
);
1413 if (ERROR_SUCCESS
!= Status
)
1415 Log("Failed to create LabConfig reg %u %u", LASTERR
, Status
);
1420 Status
+= RegSetValueExA(hSubKey
, "BypassRAMCheck", 0, REG_DWORD
, (LPBYTE
)&dwValue
, sizeof(DWORD
));
1421 Status
+= RegSetValueExA(hSubKey
, "BypassTPMCheck", 0, REG_DWORD
, (LPBYTE
)&dwValue
, sizeof(DWORD
));
1422 Status
+= RegSetValueExA(hSubKey
, "BypassSecureBootCheck", 0, REG_DWORD
, (LPBYTE
)&dwValue
, sizeof(DWORD
));
1423 Status
+= RegSetValueExA(hSubKey
, "BypassStorageCheck", 0, REG_DWORD
, (LPBYTE
)&dwValue
, sizeof(DWORD
));
1424 Status
+= RegSetValueExA(hSubKey
, "BypassCPUCheck", 0, REG_DWORD
, (LPBYTE
)&dwValue
, sizeof(DWORD
));
1426 Log("Create bypass registry %s %u", (Status
== ERROR_SUCCESS
) ? "SUCCESS" : "FAILED", Status
);
1439 static BOOL
CheckVentoyDisk(DWORD DiskNum
)
1443 UINT8 SectorBuf
[512];
1445 UINT8 check
[8] = { 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44 };
1447 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\PhysicalDrive%d", DiskNum
);
1448 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
1449 if (Handle
== INVALID_HANDLE_VALUE
)
1451 Log("Could not open the disk<%s>, error:%u", PhyPath
, GetLastError());
1455 if (!ReadFile(Handle
, SectorBuf
, sizeof(SectorBuf
), &dwSize
, NULL
))
1457 Log("ReadFile failed, dwSize:%u error:%u", dwSize
, GetLastError());
1458 CloseHandle(Handle
);
1462 CloseHandle(Handle
);
1464 if (memcmp(SectorBuf
+ 0x190, check
, 8) == 0)
1473 static int VentoyHook(ventoy_os_param
*param
)
1478 BOOL vtoyfind
= FALSE
;
1487 DISK_EXTENT DiskExtent
;
1488 DISK_EXTENT VtoyDiskExtent
;
1490 CHAR IsoPath
[MAX_PATH
];
1492 Log("VentoyHook Path:<%s>", param
->vtoy_img_path
);
1494 if (IsUTF8Encode(param
->vtoy_img_path
))
1496 Log("This file is UTF8 encoding\n");
1499 for (i
= 0; i
< 5; i
++)
1502 Drives
= GetLogicalDrives();
1503 Log("Logic Drives: 0x%x", Drives
);
1509 sprintf_s(IsoPath
, sizeof(IsoPath
), "%C:\\%s", Letter
, param
->vtoy_img_path
);
1510 if (IsFileExist("%s", IsoPath
))
1512 Log("File exist under %C:", Letter
);
1513 memset(UUID
, 0, sizeof(UUID
));
1514 memset(&DiskExtent
, 0, sizeof(DiskExtent
));
1515 if (GetPhyDiskUUID(Letter
, UUID
, NULL
, &DiskExtent
) == 0)
1517 if (memcmp(UUID
, param
->vtoy_disk_guid
, 16) == 0)
1519 Log("Disk UUID match");
1527 Log("File NOT exist under %C:", Letter
);
1541 Log("Now wait and retry ...");
1548 Log("Failed to find ISO file");
1552 Log("Find ISO file <%s>", IsoPath
);
1554 //Find VtoyLetter in Vlnk Mode
1555 if (g_os_param_reserved
[6] == 1)
1557 memcpy(&VtoySig
, g_os_param_reserved
+ 7, 4);
1558 for (i
= 0; i
< 5; i
++)
1561 Drives
= GetLogicalDrives();
1562 Log("Logic Drives: 0x%x VentoySig:%08X", Drives
, VtoySig
);
1568 memset(UUID
, 0, sizeof(UUID
));
1569 memset(&VtoyDiskExtent
, 0, sizeof(VtoyDiskExtent
));
1571 if (GetPhyDiskUUID(VtoyLetter
, UUID
, &DiskSig
, &VtoyDiskExtent
) == 0)
1573 Log("DiskSig=%08X PartStart=%lld", DiskSig
, VtoyDiskExtent
.StartingOffset
.QuadPart
);
1574 if (DiskSig
== VtoySig
&& VtoyDiskExtent
.StartingOffset
.QuadPart
== SIZE_1MB
)
1576 Log("Ventoy Disk Sig match");
1589 Log("Find Ventoy Letter: %C", VtoyLetter
);
1594 Log("Now wait and retry ...");
1599 if (vtoyfind
== FALSE
)
1601 Log("Failed to find ventoy disk");
1605 VtoyDiskNum
= VtoyDiskExtent
.DiskNumber
;
1609 VtoyLetter
= Letter
;
1610 Log("No vlnk mode %C", Letter
);
1612 VtoyDiskNum
= DiskExtent
.DiskNumber
;
1615 if (CheckVentoyDisk(VtoyDiskNum
))
1617 Log("Disk check OK %C: %u", VtoyLetter
, VtoyDiskNum
);
1621 Log("Failed to check ventoy disk %u", VtoyDiskNum
);
1625 Drives
= GetLogicalDrives();
1626 Log("Drives before mount: 0x%x", Drives
);
1628 rc
= MountIsoFile(IsoPath
, VtoyDiskNum
);
1630 NewDrives
= GetLogicalDrives();
1631 Log("Drives after mount: 0x%x (0x%x)", NewDrives
, (NewDrives
^ Drives
));
1634 NewDrives
= (NewDrives
^ Drives
);
1637 if (NewDrives
& 0x01)
1639 if ((NewDrives
>> 1) == 0)
1641 Log("The ISO file is mounted at %C:", MntLetter
);
1645 Log("Maybe the ISO file is mounted at %C:", MntLetter
);
1654 Log("Mount ISO FILE: %s", rc
== 0 ? "SUCCESS" : "FAILED");
1656 //Windows 11 bypass check
1657 if (g_windows_data
.windows11_bypass_check
== 1)
1659 Windows11BypassCheck(IsoPath
, MntLetter
);
1663 rc
= DeleteVentoyPart2MountPoint(VtoyDiskNum
);
1664 Log("Delete ventoy mountpoint: %s", rc
== 0 ? "SUCCESS" : "NO NEED");
1666 if (g_windows_data
.auto_install_script
[0])
1668 if (IsFileExist("%s", VTOY_AUTO_FILE
))
1670 Log("use auto install script %s...", VTOY_AUTO_FILE
);
1671 ProcessUnattendedInstallation(VTOY_AUTO_FILE
);
1675 Log("auto install script %s not exist", IsoPath
);
1680 Log("auto install no need");
1683 if (g_windows_data
.injection_archive
[0])
1685 sprintf_s(IsoPath
, sizeof(IsoPath
), "%C:%s", VtoyLetter
, g_windows_data
.injection_archive
);
1686 if (IsFileExist("%s", IsoPath
))
1688 Log("decompress injection archive %s...", IsoPath
);
1689 DecompressInjectionArchive(IsoPath
, VtoyDiskNum
);
1691 if (IsFileExist("%s", AUTO_RUN_BAT
))
1694 DWORD flags
= CREATE_NO_WINDOW
;
1697 PROCESS_INFORMATION Pi
;
1698 SECURITY_ATTRIBUTES Sa
= { sizeof(SECURITY_ATTRIBUTES
), NULL
, TRUE
};
1700 Log("%s exist, now run it...", AUTO_RUN_BAT
);
1702 GetStartupInfoA(&Si
);
1704 hOut
= CreateFileA(AUTO_RUN_LOG
,
1706 FILE_SHARE_WRITE
| FILE_SHARE_READ
,
1709 FILE_ATTRIBUTE_NORMAL
,
1712 Si
.dwFlags
|= STARTF_USESTDHANDLES
;
1713 if (hOut
!= INVALID_HANDLE_VALUE
)
1715 Si
.hStdError
= hOut
;
1716 Si
.hStdOutput
= hOut
;
1719 sprintf_s(IsoPath
, sizeof(IsoPath
), "%C:\\%s", Letter
, param
->vtoy_img_path
);
1720 sprintf_s(StrBuf
, sizeof(StrBuf
), "cmd.exe /c %s \"%s\" %C", AUTO_RUN_BAT
, IsoPath
, MntLetter
);
1721 CreateProcessA(NULL
, StrBuf
, NULL
, NULL
, TRUE
, flags
, NULL
, NULL
, &Si
, &Pi
);
1722 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
1724 SAFE_CLOSE_HANDLE(hOut
);
1728 Log("%s not exist...", AUTO_RUN_BAT
);
1733 Log("injection archive %s not exist", IsoPath
);
1738 Log("no injection archive found");
1744 static int ExtractWindowsDataFile(char *databuf
)
1747 char *filedata
= NULL
;
1748 ventoy_windows_data
*pdata
= (ventoy_windows_data
*)databuf
;
1750 Log("ExtractWindowsDataFile: auto install <%s:%d>", pdata
->auto_install_script
, pdata
->auto_install_len
);
1752 filedata
= databuf
+ sizeof(ventoy_windows_data
);
1754 if (pdata
->auto_install_script
[0] && pdata
->auto_install_len
> 0)
1756 SaveBuffer2File(VTOY_AUTO_FILE
, filedata
, pdata
->auto_install_len
);
1757 filedata
+= pdata
->auto_install_len
;
1758 len
= pdata
->auto_install_len
;
1764 int VentoyJumpWimboot(INT argc
, CHAR
**argv
, CHAR
*LunchFile
)
1771 Log("VentoyJumpWimboot %dbit", g_system_bit
);
1773 sprintf_s(LunchFile
, MAX_PATH
, "X:\\setup.exe");
1775 ReadWholeFile2Buf("wimboot.data", &buf
, &size
);
1776 Log("wimboot.data size:%d", size
);
1778 memcpy(&g_os_param
, buf
, sizeof(ventoy_os_param
));
1779 memcpy(&g_windows_data
, buf
+ sizeof(ventoy_os_param
), sizeof(ventoy_windows_data
));
1780 ExtractWindowsDataFile(buf
+ sizeof(ventoy_os_param
));
1781 memcpy(g_os_param_reserved
, g_os_param
.vtoy_reserved
, sizeof(g_os_param_reserved
));
1783 if (g_os_param_reserved
[0] == 1)
1785 Log("break here for debug .....");
1790 for (Pos
= 0; Pos
< sizeof(g_os_param
.vtoy_img_path
) && g_os_param
.vtoy_img_path
[Pos
]; Pos
++)
1792 if (g_os_param
.vtoy_img_path
[Pos
] == '/')
1794 g_os_param
.vtoy_img_path
[Pos
] = '\\';
1798 if (g_os_param_reserved
[0] == 2)
1800 Log("skip hook for debug .....");
1805 rc
= VentoyHook(&g_os_param
);
1817 static int ventoy_check_create_directory(void)
1819 if (IsDirExist("ventoy"))
1821 Log("ventoy directory already exist");
1825 Log("ventoy directory not exist, now create it.");
1826 if (!CreateDirectoryA("ventoy", NULL
))
1828 Log("Failed to create ventoy directory err:%u", GetLastError());
1836 int VentoyJump(INT argc
, CHAR
**argv
, CHAR
*LunchFile
)
1844 DWORD LockStatus
= 0;
1845 BYTE
*Buffer
= NULL
;
1846 CHAR ExeFileName
[MAX_PATH
];
1848 sprintf_s(ExeFileName
, sizeof(ExeFileName
), "%s", argv
[0]);
1849 if (!IsFileExist("%s", ExeFileName
))
1851 Log("File %s NOT exist, now try %s.exe", ExeFileName
, ExeFileName
);
1852 sprintf_s(ExeFileName
, sizeof(ExeFileName
), "%s.exe", argv
[0]);
1854 Log("File %s exist ? %s", ExeFileName
, IsFileExist("%s", ExeFileName
) ? "YES" : "NO");
1857 if (ReadWholeFile2Buf(ExeFileName
, (void **)&Buffer
, &FileSize
))
1862 Log("VentoyJump %dbit", g_system_bit
);
1864 MUTEX_LOCK(g_vtoyins_mutex
);
1865 stat
= ventoy_check_create_directory();
1866 MUTEX_UNLOCK(g_vtoyins_mutex
);
1873 for (PeStart
= 0; PeStart
< FileSize
; PeStart
+= 16)
1875 if (CheckOsParam((ventoy_os_param
*)(Buffer
+ PeStart
)) &&
1876 CheckPeHead(Buffer
, FileSize
, PeStart
+ sizeof(ventoy_os_param
)))
1878 Log("Find os pararm at %u", PeStart
);
1880 memcpy(&g_os_param
, Buffer
+ PeStart
, sizeof(ventoy_os_param
));
1881 memcpy(&g_windows_data
, Buffer
+ PeStart
+ sizeof(ventoy_os_param
), sizeof(ventoy_windows_data
));
1882 exlen
= ExtractWindowsDataFile(Buffer
+ PeStart
+ sizeof(ventoy_os_param
));
1883 memcpy(g_os_param_reserved
, g_os_param
.vtoy_reserved
, sizeof(g_os_param_reserved
));
1885 if (g_os_param_reserved
[0] == 1)
1887 Log("break here for debug .....");
1892 for (Pos
= 0; Pos
< sizeof(g_os_param
.vtoy_img_path
) && g_os_param
.vtoy_img_path
[Pos
]; Pos
++)
1894 if (g_os_param
.vtoy_img_path
[Pos
] == '/')
1896 g_os_param
.vtoy_img_path
[Pos
] = '\\';
1900 PeStart
+= sizeof(ventoy_os_param
) + sizeof(ventoy_windows_data
) + exlen
;
1901 sprintf_s(LunchFile
, MAX_PATH
, "ventoy\\%s", GetFileNameInPath(ExeFileName
));
1903 MUTEX_LOCK(g_vtoyins_mutex
);
1904 if (IsFileExist("%s", LunchFile
))
1906 Log("vtoyjump multiple call ...");
1908 MUTEX_UNLOCK(g_vtoyins_mutex
);
1912 SaveBuffer2File(LunchFile
, Buffer
+ PeStart
, FileSize
- PeStart
);
1913 MUTEX_UNLOCK(g_vtoyins_mutex
);
1919 if (PeStart
>= FileSize
)
1921 Log("OS param not found");
1925 if (g_os_param_reserved
[0] == 2)
1927 Log("skip hook for debug .....");
1932 rc
= VentoyHook(&g_os_param
);
1945 int real_main(int argc
, char **argv
)
1949 CHAR NewFile
[MAX_PATH
];
1950 CHAR LunchFile
[MAX_PATH
];
1951 CHAR CallParam
[1024] = { 0 };
1953 PROCESS_INFORMATION Pi
;
1955 Log("#### real_main #### argc = %d", argc
);
1956 Log("program full path: <%s>", g_prog_full_path
);
1957 Log("program dir: <%s>", g_prog_dir
);
1958 Log("program name:: <%s>", g_prog_name
);
1960 Log("argc = %d", argc
);
1961 for (i
= 0; i
< argc
; i
++)
1963 Log("argv[%d]=<%s>", i
, argv
[i
]);
1966 strcat_s(CallParam
, sizeof(CallParam
), " ");
1967 strcat_s(CallParam
, sizeof(CallParam
), argv
[i
]);
1971 GetStartupInfoA(&Si
);
1972 memset(LunchFile
, 0, sizeof(LunchFile
));
1974 if (strstr(argv
[0], "vtoyjump.exe"))
1976 rc
= VentoyJumpWimboot(argc
, argv
, LunchFile
);
1980 rc
= VentoyJump(argc
, argv
, LunchFile
);
1983 Log("LunchFile=<%s> CallParam=<%s>", LunchFile
, CallParam
);
1985 if (_stricmp(g_prog_name
, "winpeshl.exe") != 0 && IsFileExist("ventoy\\%s", g_prog_name
))
1987 sprintf_s(NewFile
, sizeof(NewFile
), "%s_BACK.EXE", g_prog_full_path
);
1988 MoveFileA(g_prog_full_path
, NewFile
);
1989 Log("Move <%s> to <%s>", g_prog_full_path
, NewFile
);
1991 sprintf_s(NewFile
, sizeof(NewFile
), "ventoy\\%s", g_prog_name
);
1992 CopyFileA(NewFile
, g_prog_full_path
, TRUE
);
1993 Log("Copy <%s> to <%s>", NewFile
, g_prog_full_path
);
1995 sprintf_s(LunchFile
, sizeof(LunchFile
), "%s", g_prog_full_path
);
1996 Log("Final lunchFile is <%s>", LunchFile
);
2000 Log("We don't need to recover original <%s>", g_prog_name
);
2003 if (g_os_param_reserved
[0] == 3)
2005 Log("Open log for debug ...");
2006 sprintf_s(LunchFile
, sizeof(LunchFile
), "%s", "notepad.exe ventoy.log");
2012 strcat_s(LunchFile
, sizeof(LunchFile
), CallParam
);
2014 else if (NULL
== strstr(LunchFile
, "setup.exe"))
2016 Log("Not setup.exe, hide windows.");
2017 Si
.dwFlags
|= STARTF_USESHOWWINDOW
;
2018 Si
.wShowWindow
= SW_HIDE
;
2021 Log("Ventoy jump %s ...", rc
== 0 ? "success" : "failed");
2024 Log("Now launch <%s> ...", LunchFile
);
2026 if (g_os_param_reserved
[0] == 4)
2028 Log("Open cmd for debug ...");
2029 sprintf_s(LunchFile
, sizeof(LunchFile
), "%s", "cmd.exe");
2032 Log("Backup log at this point");
2033 CopyFileA(LOG_FILE
, "X:\\Windows\\ventoy.backup", TRUE
);
2035 CreateProcessA(NULL
, LunchFile
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
2037 for (i
= 0; rc
&& i
< 1800; i
++)
2039 Log("Ventoy hook failed, now wait and retry ...");
2041 rc
= VentoyHook(&g_os_param
);
2044 Log("Wait process...");
2045 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
2047 Log("vtoyjump finished");
2051 static void VentoyToUpper(CHAR
*str
)
2054 for (i
= 0; str
[i
]; i
++)
2056 str
[i
] = (CHAR
)toupper(str
[i
]);
2060 int main(int argc
, char **argv
)
2064 PROCESS_INFORMATION Pi
;
2065 CHAR CurDir
[MAX_PATH
];
2066 CHAR NewArgv0
[MAX_PATH
];
2067 CHAR CallParam
[1024] = { 0 };
2069 g_vtoylog_mutex
= CreateMutexA(NULL
, FALSE
, "VTOYLOG_LOCK");
2070 g_vtoyins_mutex
= CreateMutexA(NULL
, FALSE
, "VTOYINS_LOCK");
2072 Log("######## VentoyJump %dbit ##########", g_system_bit
);
2074 GetCurrentDirectoryA(sizeof(CurDir
), CurDir
);
2075 Log("Current directory is <%s>", CurDir
);
2077 GetModuleFileNameA(NULL
, g_prog_full_path
, MAX_PATH
);
2078 split_path_name(g_prog_full_path
, g_prog_dir
, g_prog_name
);
2080 Log("EXE path: <%s> dir:<%s> name:<%s>", g_prog_full_path
, g_prog_dir
, g_prog_name
);
2082 if (_stricmp(g_prog_name
, "WinLogon.exe") == 0)
2084 Log("This time is rejump back ...");
2086 strcpy_s(g_prog_full_path
, sizeof(g_prog_full_path
), argv
[1]);
2087 split_path_name(g_prog_full_path
, g_prog_dir
, g_prog_name
);
2089 return real_main(argc
- 1, argv
+ 1);
2091 else if (_stricmp(g_prog_name
, "PECMD.exe") == 0)
2093 strcpy_s(NewArgv0
, sizeof(NewArgv0
), g_prog_dir
);
2094 VentoyToUpper(NewArgv0
);
2096 if (NULL
== strstr(NewArgv0
, "SYSTEM32") && IsFileExist(ORG_PECMD_BK_PATH
))
2098 Log("Just call original pecmd.exe");
2099 strcpy_s(CallParam
, sizeof(CallParam
), ORG_PECMD_PATH
);
2103 Log("We need to rejump for pecmd ...");
2105 ventoy_check_create_directory();
2106 CopyFileA(g_prog_full_path
, "ventoy\\WinLogon.exe", TRUE
);
2108 sprintf_s(CallParam
, sizeof(CallParam
), "ventoy\\WinLogon.exe %s", g_prog_full_path
);
2111 for (i
= 1; i
< argc
; i
++)
2113 strcat_s(CallParam
, sizeof(CallParam
), " ");
2114 strcat_s(CallParam
, sizeof(CallParam
), argv
[i
]);
2117 Log("Now rejump to <%s> ...", CallParam
);
2118 GetStartupInfoA(&Si
);
2119 CreateProcessA(NULL
, CallParam
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
2121 Log("Wait rejump process...");
2122 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
2123 Log("rejump finished");
2128 Log("We don't need to rejump ...");
2130 strcpy_s(NewArgv0
, sizeof(NewArgv0
), g_prog_full_path
);
2133 return real_main(argc
, argv
);