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 INT g_winpeshl_ini_updated
= 0;
40 static DWORD g_vtoy_disk_drive
;
42 static CHAR g_prog_full_path
[MAX_PATH
];
43 static CHAR g_prog_dir
[MAX_PATH
];
44 static CHAR g_prog_name
[MAX_PATH
];
46 #define VTOY_PECMD_PATH "X:\\Windows\\system32\\ventoy\\PECMD.EXE"
47 #define ORG_PECMD_PATH "X:\\Windows\\system32\\PECMD.EXE"
48 #define ORG_PECMD_BK_PATH "X:\\Windows\\system32\\PECMD.EXE_BACK.EXE"
50 #define AUTO_RUN_BAT "X:\\VentoyAutoRun.bat"
51 #define AUTO_RUN_LOG "X:\\VentoyAutoRun.log"
53 #define VTOY_AUTO_FILE "X:\\_vtoy_auto_install"
55 #define WINPESHL_INI "X:\\Windows\\system32\\winpeshl.ini"
57 #define LOG_FILE "X:\\Windows\\system32\\ventoy.log"
58 #define MUTEX_LOCK(hmutex) if (hmutex != NULL) LockStatus = WaitForSingleObject(hmutex, INFINITE)
59 #define MUTEX_UNLOCK(hmutex) if (hmutex != NULL && WAIT_OBJECT_0 == LockStatus) ReleaseMutex(hmutex)
61 static const char * GetFileNameInPath(const char *fullpath
)
65 if (strstr(fullpath
, ":"))
67 for (i
= (int)strlen(fullpath
); i
> 0; i
--)
69 if (fullpath
[i
- 1] == '/' || fullpath
[i
- 1] == '\\')
79 static int split_path_name(char *fullpath
, char *dir
, char *name
)
84 Pos
= (CHAR
*)GetFileNameInPath(fullpath
);
86 strcpy_s(name
, MAX_PATH
, Pos
);
90 strcpy_s(dir
, MAX_PATH
, fullpath
);
97 void Log(const char *Fmt
, ...)
104 DWORD LockStatus
= 0;
105 DWORD PID
= GetCurrentProcessId();
108 Len
+= sprintf_s(szBuf
, sizeof(szBuf
),
109 "[%4d/%02d/%02d %02d:%02d:%02d.%03d] [%u] ",
110 Sys
.wYear
, Sys
.wMonth
, Sys
.wDay
,
111 Sys
.wHour
, Sys
.wMinute
, Sys
.wSecond
,
112 Sys
.wMilliseconds
, PID
);
115 Len
+= vsnprintf_s(szBuf
+ Len
, sizeof(szBuf
)-Len
, sizeof(szBuf
)-Len
, Fmt
, Arg
);
118 MUTEX_LOCK(g_vtoylog_mutex
);
120 fopen_s(&File
, LOG_FILE
, "a+");
123 fwrite(szBuf
, 1, Len
, File
);
124 fwrite("\n", 1, 1, File
);
128 MUTEX_UNLOCK(g_vtoylog_mutex
);
132 static int LoadNtDriver(const char *DrvBinPath
)
138 SC_HANDLE hServiceMgr
;
140 char name
[256] = { 0 };
142 for (i
= (int)strlen(DrvBinPath
) - 1; i
>= 0; i
--)
144 if (DrvBinPath
[i
] == '\\' || DrvBinPath
[i
] == '/')
146 sprintf_s(name
, sizeof(name
), "%s", DrvBinPath
+ i
+ 1);
151 Log("Load NT driver: %s %s", DrvBinPath
, name
);
153 hServiceMgr
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_ALL_ACCESS
);
154 if (hServiceMgr
== NULL
)
156 Log("OpenSCManager failed Error:%u", GetLastError());
160 Log("OpenSCManager OK");
162 hService
= CreateServiceA(hServiceMgr
,
166 SERVICE_KERNEL_DRIVER
,
167 SERVICE_DEMAND_START
,
168 SERVICE_ERROR_NORMAL
,
170 NULL
, NULL
, NULL
, NULL
, NULL
);
171 if (hService
== NULL
)
173 Status
= GetLastError();
174 if (Status
!= ERROR_IO_PENDING
&& Status
!= ERROR_SERVICE_EXISTS
)
176 Log("CreateService failed v %u", Status
);
177 CloseServiceHandle(hServiceMgr
);
181 hService
= OpenServiceA(hServiceMgr
, name
, SERVICE_ALL_ACCESS
);
182 if (hService
== NULL
)
184 Log("OpenService failed %u", Status
);
185 CloseServiceHandle(hServiceMgr
);
190 Log("CreateService imdisk OK");
192 Ret
= StartServiceA(hService
, 0, NULL
);
195 Log("StartService OK");
199 Status
= GetLastError();
200 if (Status
== ERROR_SERVICE_ALREADY_RUNNING
)
206 Log("StartService error %u", Status
);
211 CloseServiceHandle(hService
);
212 CloseServiceHandle(hServiceMgr
);
214 Log("Load NT driver %s", rc
? "failed" : "success");
219 static int ReadWholeFile2Buf(const char *Fullpath
, void **Data
, DWORD
*Size
)
227 Log("ReadWholeFile2Buf <%s>", Fullpath
);
229 Handle
= CreateFileA(Fullpath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
230 if (Handle
== INVALID_HANDLE_VALUE
)
232 Log("Could not open the file<%s>, error:%u", Fullpath
, GetLastError());
236 FileSize
= SetFilePointer(Handle
, 0, NULL
, FILE_END
);
238 Buffer
= malloc(FileSize
);
241 Log("Failed to alloc memory size:%u", FileSize
);
245 SetFilePointer(Handle
, 0, NULL
, FILE_BEGIN
);
246 if (!ReadFile(Handle
, Buffer
, FileSize
, &dwSize
, NULL
))
248 Log("ReadFile failed, dwSize:%u error:%u", dwSize
, GetLastError());
255 Log("Success read file size:%u", FileSize
);
260 SAFE_CLOSE_HANDLE(Handle
);
265 static BOOL
CheckPeHead(BYTE
*Buffer
, DWORD Size
, DWORD Offset
)
270 ventoy_windows_data
*pdata
= NULL
;
272 Head
= Buffer
+ Offset
;
273 pdata
= (ventoy_windows_data
*)Head
;
274 Head
+= sizeof(ventoy_windows_data
);
276 if (pdata
->auto_install_script
[0] && pdata
->auto_install_len
> 0)
278 End
= Offset
+ sizeof(ventoy_windows_data
) + pdata
->auto_install_len
+ 60;
281 Head
+= pdata
->auto_install_len
;
285 if (Head
[0] != 'M' || Head
[1] != 'Z')
290 PeOffset
= *(UINT32
*)(Head
+ 60);
291 if (*(UINT32
*)(Head
+ PeOffset
) != 0x00004550)
300 static BOOL
CheckOsParam(ventoy_os_param
*param
)
305 if (memcmp(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
)))
310 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
312 Sum
+= *((BYTE
*)param
+ i
);
320 if (param
->vtoy_img_location_addr
% 4096)
328 static int SaveBuffer2File(const char *Fullpath
, void *Buffer
, DWORD Length
)
334 Log("SaveBuffer2File <%s> len:%u", Fullpath
, Length
);
336 Handle
= CreateFileA(Fullpath
, GENERIC_READ
| GENERIC_WRITE
,
337 FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, CREATE_NEW
, 0, 0);
338 if (Handle
== INVALID_HANDLE_VALUE
)
340 Log("Could not create new file, error:%u", GetLastError());
344 WriteFile(Handle
, Buffer
, Length
, &dwSize
, NULL
);
349 SAFE_CLOSE_HANDLE(Handle
);
354 static int IsUTF8Encode(const char *src
)
357 const UCHAR
*Byte
= (const UCHAR
*)src
;
359 for (i
= 0; i
< MAX_PATH
&& Byte
[i
]; i
++)
370 static int Utf8ToUtf16(const char* src
, WCHAR
* dst
)
372 int size
= MultiByteToWideChar(CP_UTF8
, 0, src
, -1, dst
, 0);
373 return MultiByteToWideChar(CP_UTF8
, 0, src
, -1, dst
, size
+ 1);
376 static BOOL
IsDirExist(const char *Fmt
, ...)
381 CHAR FilePathA
[MAX_PATH
];
382 WCHAR FilePathW
[MAX_PATH
];
385 vsnprintf_s(FilePathA
, sizeof(FilePathA
), sizeof(FilePathA
), Fmt
, Arg
);
388 UTF8
= IsUTF8Encode(FilePathA
);
392 Utf8ToUtf16(FilePathA
, FilePathW
);
393 Attr
= GetFileAttributesW(FilePathW
);
397 Attr
= GetFileAttributesA(FilePathA
);
400 if (Attr
!= INVALID_FILE_ATTRIBUTES
&& (Attr
& FILE_ATTRIBUTE_DIRECTORY
))
408 static BOOL
IsFileExist(const char *Fmt
, ...)
415 CHAR FilePathA
[MAX_PATH
];
416 WCHAR FilePathW
[MAX_PATH
];
419 vsnprintf_s(FilePathA
, sizeof(FilePathA
), sizeof(FilePathA
), Fmt
, Arg
);
422 UTF8
= IsUTF8Encode(FilePathA
);
426 Utf8ToUtf16(FilePathA
, FilePathW
);
427 hFile
= CreateFileW(FilePathW
, FILE_READ_EA
, FILE_SHARE_READ
, 0, OPEN_EXISTING
, 0, 0);
431 hFile
= CreateFileA(FilePathA
, FILE_READ_EA
, FILE_SHARE_READ
, 0, OPEN_EXISTING
, 0, 0);
433 if (INVALID_HANDLE_VALUE
== hFile
)
442 Attr
= GetFileAttributesW(FilePathW
);
446 Attr
= GetFileAttributesA(FilePathA
);
449 if (Attr
& FILE_ATTRIBUTE_DIRECTORY
)
457 Log("File <%s> %s", FilePathA
, (bRet
? "exist" : "NOT exist"));
461 static int GetPhyDiskUUID(const char LogicalDrive
, UINT8
*UUID
, UINT32
*DiskSig
, DISK_EXTENT
*DiskExtent
)
466 VOLUME_DISK_EXTENTS DiskExtents
;
468 UINT8 SectorBuf
[512];
470 Log("GetPhyDiskUUID %C", LogicalDrive
);
472 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\%C:", LogicalDrive
);
473 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
474 if (Handle
== INVALID_HANDLE_VALUE
)
476 Log("Could not open the disk<%s>, error:%u", PhyPath
, GetLastError());
480 Ret
= DeviceIoControl(Handle
,
481 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
485 (DWORD
)(sizeof(DiskExtents
)),
488 if (!Ret
|| DiskExtents
.NumberOfDiskExtents
== 0)
490 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed, error:%u", GetLastError());
496 memcpy(DiskExtent
, DiskExtents
.Extents
, sizeof(DISK_EXTENT
));
497 Log("%C: is in PhysicalDrive%d Offset:%llu", LogicalDrive
, DiskExtents
.Extents
[0].DiskNumber
,
498 (ULONGLONG
)(DiskExtents
.Extents
[0].StartingOffset
.QuadPart
));
500 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\PhysicalDrive%d", DiskExtents
.Extents
[0].DiskNumber
);
501 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
502 if (Handle
== INVALID_HANDLE_VALUE
)
504 Log("Could not open the disk<%s>, error:%u", PhyPath
, GetLastError());
508 if (!ReadFile(Handle
, SectorBuf
, sizeof(SectorBuf
), &dwSize
, NULL
))
510 Log("ReadFile failed, dwSize:%u error:%u", dwSize
, GetLastError());
515 memcpy(UUID
, SectorBuf
+ 0x180, 16);
518 memcpy(DiskSig
, SectorBuf
+ 0x1B8, 4);
525 static int VentoyMountAnywhere(HANDLE Handle
)
528 ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters
;
530 Log("VentoyMountAnywhere");
532 memset(&AttachParameters
, 0, sizeof(AttachParameters
));
533 AttachParameters
.Version
= ATTACH_VIRTUAL_DISK_VERSION_1
;
535 Status
= AttachVirtualDisk(Handle
, NULL
, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY
| ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME
, 0, &AttachParameters
, NULL
);
536 if (Status
!= ERROR_SUCCESS
)
538 Log("Failed to attach virtual disk ErrorCode:%u", Status
);
545 int VentoyMountY(HANDLE Handle
)
550 DWORD physicalDriveNameSize
;
552 WCHAR physicalDriveName
[MAX_PATH
];
553 CHAR physicalDriveNameA
[MAX_PATH
];
554 CHAR cdromDriveName
[MAX_PATH
];
555 ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters
;
559 memset(&AttachParameters
, 0, sizeof(AttachParameters
));
560 AttachParameters
.Version
= ATTACH_VIRTUAL_DISK_VERSION_1
;
562 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
);
563 if (Status
!= ERROR_SUCCESS
)
565 Log("Failed to attach virtual disk ErrorCode:%u", Status
);
569 memset(physicalDriveName
, 0, sizeof(physicalDriveName
));
570 memset(physicalDriveNameA
, 0, sizeof(physicalDriveNameA
));
572 physicalDriveNameSize
= MAX_PATH
;
573 Status
= GetVirtualDiskPhysicalPath(Handle
, &physicalDriveNameSize
, physicalDriveName
);
574 if (Status
!= ERROR_SUCCESS
)
576 Log("Failed GetVirtualDiskPhysicalPath ErrorCode:%u", Status
);
580 for (i
= 0; physicalDriveName
[i
]; i
++)
582 physicalDriveNameA
[i
] = (CHAR
)toupper((CHAR
)(physicalDriveName
[i
]));
585 Log("physicalDriveNameA=<%s>", physicalDriveNameA
);
587 Pos
= strstr(physicalDriveNameA
, "CDROM");
590 Log("Not cdrom phy drive");
594 sprintf_s(cdromDriveName
, sizeof(cdromDriveName
), "\\Device\\%s", Pos
);
595 Log("cdromDriveName=<%s>", cdromDriveName
);
597 for (i
= 0; i
< 3 && (bRet
== FALSE
); i
++)
600 bRet
= DefineDosDeviceA(DDD_RAW_TARGET_PATH
, "Y:", cdromDriveName
);
601 Log("DefineDosDeviceA %s", bRet
? "success" : "failed");
607 static BOOL
VentoyAPINeedMountY(const char *IsoPath
)
615 static int VentoyAttachVirtualDisk(HANDLE Handle
, const char *IsoPath
)
620 Drives
= GetLogicalDrives();
621 if ((1 << 24) & Drives
)
623 Log("Y: is occupied");
628 Log("Y: is free now");
632 if (DriveYFree
&& VentoyAPINeedMountY(IsoPath
))
634 return VentoyMountY(Handle
);
638 return VentoyMountAnywhere(Handle
);
642 int VentoyMountISOByAPI(const char *IsoPath
)
647 WCHAR wFilePath
[512] = { 0 };
648 VIRTUAL_STORAGE_TYPE StorageType
;
649 OPEN_VIRTUAL_DISK_PARAMETERS OpenParameters
;
651 Log("VentoyMountISOByAPI <%s>", IsoPath
);
653 if (IsUTF8Encode(IsoPath
))
655 Log("This is UTF8 encoding");
656 MultiByteToWideChar(CP_UTF8
, 0, IsoPath
, (int)strlen(IsoPath
), wFilePath
, (int)(sizeof(wFilePath
) / sizeof(WCHAR
)));
660 Log("This is ANSI encoding");
661 MultiByteToWideChar(CP_ACP
, 0, IsoPath
, (int)strlen(IsoPath
), wFilePath
, (int)(sizeof(wFilePath
) / sizeof(WCHAR
)));
664 memset(&StorageType
, 0, sizeof(StorageType
));
665 memset(&OpenParameters
, 0, sizeof(OpenParameters
));
667 OpenParameters
.Version
= OPEN_VIRTUAL_DISK_VERSION_1
;
669 for (i
= 0; i
< 10; i
++)
671 Status
= OpenVirtualDisk(&StorageType
, wFilePath
, VIRTUAL_DISK_ACCESS_READ
, 0, &OpenParameters
, &Handle
);
672 if (ERROR_FILE_NOT_FOUND
== Status
|| ERROR_PATH_NOT_FOUND
== Status
)
674 Log("OpenVirtualDisk ErrorCode:%u, now wait and retry...", Status
);
679 if (ERROR_SUCCESS
== Status
)
681 Log("OpenVirtualDisk success");
683 else if (ERROR_VIRTDISK_PROVIDER_NOT_FOUND
== Status
)
685 Log("VirtualDisk for ISO file is not supported in current system");
689 Log("Failed to open virtual disk ErrorCode:%u", Status
);
695 if (Status
!= ERROR_SUCCESS
)
700 Log("OpenVirtualDisk success");
702 Status
= VentoyAttachVirtualDisk(Handle
, IsoPath
);
703 if (Status
!= ERROR_SUCCESS
)
705 Log("Failed to attach virtual disk ErrorCode:%u", Status
);
710 Log("VentoyAttachVirtualDisk success");
717 static HANDLE g_FatPhyDrive
;
718 static UINT64 g_Part2StartSec
;
720 static int CopyFileFromFatDisk(const CHAR
* SrcFile
, const CHAR
*DstFile
)
727 Log("CopyFileFromFatDisk (%s)==>(%s)", SrcFile
, DstFile
);
729 flfile
= fl_fopen(SrcFile
, "rb");
732 fl_fseek(flfile
, 0, SEEK_END
);
733 size
= (int)fl_ftell(flfile
);
734 fl_fseek(flfile
, 0, SEEK_SET
);
736 buf
= (char *)malloc(size
);
739 fl_fread(buf
, 1, size
, flfile
);
742 SaveBuffer2File(DstFile
, buf
, size
);
752 static int VentoyFatDiskRead(uint32 Sector
, uint8
*Buffer
, uint32 SectorCount
)
757 LARGE_INTEGER liCurrentPosition
;
759 liCurrentPosition
.QuadPart
= Sector
+ g_Part2StartSec
;
760 liCurrentPosition
.QuadPart
*= 512;
761 SetFilePointerEx(g_FatPhyDrive
, liCurrentPosition
, &liCurrentPosition
, FILE_BEGIN
);
763 ReadSize
= (DWORD
)(SectorCount
* 512);
765 bRet
= ReadFile(g_FatPhyDrive
, Buffer
, ReadSize
, &dwSize
, NULL
);
766 if (bRet
== FALSE
|| dwSize
!= ReadSize
)
768 Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u", bRet
, ReadSize
, dwSize
, GetLastError());
774 static BOOL
Is2K10PE(void)
780 fopen_s(&fp
, "X:\\Windows\\System32\\PECMD.INI", "r");
786 memset(szLine
, 0, sizeof(szLine
));
787 while (fgets(szLine
, sizeof(szLine
) - 1, fp
))
789 if (strstr(szLine
, "2k10\\"))
800 static CHAR
GetIMDiskMountLogicalDrive(void)
804 DWORD Mask
= 0x1000000;
806 // fixed use M as mountpoint for 2K10 PE
809 Log("Use M: for 2K10 PE");
813 Drives
= GetLogicalDrives();
814 Log("Drives=0x%x", Drives
);
818 if ((Drives
& Mask
) == 0)
830 UINT64
GetVentoyEfiPartStartSector(HANDLE hDrive
)
835 VTOY_GPT_INFO
*pGpt
= NULL
;
836 UINT64 StartSector
= 0;
838 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
840 bRet
= ReadFile(hDrive
, &MBR
, sizeof(MBR
), &dwSize
, NULL
);
841 Log("Read MBR Ret:%u Size:%u code:%u", bRet
, dwSize
, LASTERR
);
843 if ((!bRet
) || (dwSize
!= sizeof(MBR
)))
848 if (MBR
.PartTbl
[0].FsFlag
== 0xEE)
850 Log("GPT partition style");
852 pGpt
= malloc(sizeof(VTOY_GPT_INFO
));
858 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
859 bRet
= ReadFile(hDrive
, pGpt
, sizeof(VTOY_GPT_INFO
), &dwSize
, NULL
);
860 if ((!bRet
) || (dwSize
!= sizeof(VTOY_GPT_INFO
)))
862 Log("Failed to read gpt info %d %u %d", bRet
, dwSize
, LASTERR
);
866 StartSector
= pGpt
->PartTbl
[1].StartLBA
;
871 Log("MBR partition style");
872 StartSector
= MBR
.PartTbl
[1].StartSectorId
;
875 Log("GetVentoyEfiPart StartSector: %llu", StartSector
);
879 static int VentoyRunImdisk(const char *IsoPath
, const char *imdiskexe
)
884 PROCESS_INFORMATION Pi
;
886 Log("VentoyRunImdisk <%s> <%s>", IsoPath
, imdiskexe
);
888 Letter
= GetIMDiskMountLogicalDrive();
889 sprintf_s(Cmdline
, sizeof(Cmdline
), "%s -a -o ro -f \"%s\" -m %C:", imdiskexe
, IsoPath
, Letter
);
890 Log("mount iso to %C: use imdisk cmd <%s>", Letter
, Cmdline
);
892 if (IsUTF8Encode(IsoPath
))
895 GetStartupInfoW(&Si
);
896 Si
.dwFlags
|= STARTF_USESHOWWINDOW
;
897 Si
.wShowWindow
= SW_HIDE
;
899 Utf8ToUtf16(Cmdline
, CmdlineW
);
900 CreateProcessW(NULL
, CmdlineW
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
902 Log("This is UTF8 encoding");
907 GetStartupInfoA(&Si
);
908 Si
.dwFlags
|= STARTF_USESHOWWINDOW
;
909 Si
.wShowWindow
= SW_HIDE
;
911 CreateProcessA(NULL
, Cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
913 Log("This is ANSI encoding");
916 Log("Wait for imdisk process ...");
917 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
918 Log("imdisk process finished");
923 int VentoyMountISOByImdisk(const char *IsoPath
, DWORD PhyDrive
)
929 CHAR PhyPath
[MAX_PATH
];
930 GET_LENGTH_INFORMATION LengthInfo
;
932 Log("VentoyMountISOByImdisk %s", IsoPath
);
934 if (IsFileExist("X:\\Windows\\System32\\imdisk.exe"))
936 Log("imdisk.exe exist, use it directly...");
937 VentoyRunImdisk(IsoPath
, "imdisk.exe");
941 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\PhysicalDrive%d", PhyDrive
);
942 hDrive
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
943 if (hDrive
== INVALID_HANDLE_VALUE
)
945 Log("Could not open the disk<%s>, error:%u", PhyPath
, GetLastError());
949 bRet
= DeviceIoControl(hDrive
, IOCTL_DISK_GET_LENGTH_INFO
, NULL
, 0, &LengthInfo
, sizeof(LengthInfo
), &dwBytes
, NULL
);
952 Log("Could not get phy disk %s size, error:%u", PhyPath
, GetLastError());
956 g_FatPhyDrive
= hDrive
;
957 g_Part2StartSec
= GetVentoyEfiPartStartSector(hDrive
);
959 Log("Parse FAT fs...");
963 if (0 == fl_attach_media(VentoyFatDiskRead
, NULL
))
965 if (g_system_bit
== 64)
967 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.sys", "ventoy\\imdisk.sys");
968 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.exe", "ventoy\\imdisk.exe");
969 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.cpl", "ventoy\\imdisk.cpl");
973 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.sys", "ventoy\\imdisk.sys");
974 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.exe", "ventoy\\imdisk.exe");
975 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.cpl", "ventoy\\imdisk.cpl");
978 GetCurrentDirectoryA(sizeof(PhyPath
), PhyPath
);
979 strcat_s(PhyPath
, sizeof(PhyPath
), "\\ventoy\\imdisk.sys");
981 if (LoadNtDriver(PhyPath
) == 0)
983 VentoyRunImdisk(IsoPath
, "ventoy\\imdisk.exe");
991 SAFE_CLOSE_HANDLE(hDrive
);
996 static int MountIsoFile(CONST CHAR
*IsoPath
, DWORD PhyDrive
)
998 if (IsWindows8OrGreater())
1000 Log("This is Windows 8 or latter...");
1001 if (VentoyMountISOByAPI(IsoPath
) == 0)
1003 Log("Mount iso by API success");
1008 Log("Mount iso by API failed, maybe not supported, try imdisk");
1009 return VentoyMountISOByImdisk(IsoPath
, PhyDrive
);
1014 Log("This is before Windows 8 ...");
1015 if (VentoyMountISOByImdisk(IsoPath
, PhyDrive
) == 0)
1017 Log("Mount iso by imdisk success");
1022 return VentoyMountISOByAPI(IsoPath
);
1027 static int GetPhyDriveByLogicalDrive(int DriveLetter
)
1032 VOLUME_DISK_EXTENTS DiskExtents
;
1035 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\%C:", (CHAR
)DriveLetter
);
1037 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
1038 if (Handle
== INVALID_HANDLE_VALUE
)
1040 Log("Could not open the disk<%s>, error:%u", PhyPath
, GetLastError());
1044 Ret
= DeviceIoControl(Handle
,
1045 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
1049 (DWORD
)(sizeof(DiskExtents
)),
1053 if (!Ret
|| DiskExtents
.NumberOfDiskExtents
== 0)
1055 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath
, GetLastError());
1056 SAFE_CLOSE_HANDLE(Handle
);
1059 SAFE_CLOSE_HANDLE(Handle
);
1061 Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",
1063 DiskExtents
.Extents
[0].DiskNumber
,
1064 DiskExtents
.Extents
[0].StartingOffset
.QuadPart
,
1065 DiskExtents
.Extents
[0].ExtentLength
.QuadPart
1068 return (int)DiskExtents
.Extents
[0].DiskNumber
;
1072 static int DeleteVentoyPart2MountPoint(DWORD PhyDrive
)
1077 CHAR DriveName
[] = "?:\\";
1079 Log("DeleteVentoyPart2MountPoint Phy%u ...", PhyDrive
);
1081 Drives
= GetLogicalDrives();
1084 if ((Drives
& 0x01) && IsFileExist("%C:\\ventoy\\ventoy.cpio", Letter
))
1086 Log("File %C:\\ventoy\\ventoy.cpio exist", Letter
);
1088 PhyDisk
= GetPhyDriveByLogicalDrive(Letter
);
1089 Log("PhyDisk=%u for %C", PhyDisk
, Letter
);
1091 if (PhyDisk
== PhyDrive
)
1093 DriveName
[0] = Letter
;
1094 DeleteVolumeMountPointA(DriveName
);
1106 static BOOL
check_tar_archive(const char *archive
, CHAR
*tarName
)
1110 const char *pos
= archive
;
1111 const char *slash
= archive
;
1115 if (*pos
== '\\' || *pos
== '/')
1122 len
= (int)strlen(slash
);
1124 if (len
> 7 && (strncmp(slash
+ len
- 7, ".tar.gz", 7) == 0 || strncmp(slash
+ len
- 7, ".tar.xz", 7) == 0))
1126 nameLen
= (int)sprintf_s(tarName
, MAX_PATH
, "X:%s", slash
);
1127 tarName
[nameLen
- 3] = 0;
1130 else if (len
> 8 && strncmp(slash
+ len
- 8, ".tar.bz2", 8) == 0)
1132 nameLen
= (int)sprintf_s(tarName
, MAX_PATH
, "X:%s", slash
);
1133 tarName
[nameLen
- 4] = 0;
1136 else if (len
> 9 && strncmp(slash
+ len
- 9, ".tar.lzma", 9) == 0)
1138 nameLen
= (int)sprintf_s(tarName
, MAX_PATH
, "X:%s", slash
);
1139 tarName
[nameLen
- 5] = 0;
1146 static UCHAR
*g_unxz_buffer
= NULL
;
1147 static int g_unxz_len
= 0;
1149 static void unxz_error(char *x
)
1154 static int unxz_flush(void *src
, unsigned int size
)
1156 memcpy(g_unxz_buffer
+ g_unxz_len
, src
, size
);
1157 g_unxz_len
+= (int)size
;
1162 static int DecompressInjectionArchive(const char *archive
, DWORD PhyDrive
)
1166 UCHAR
*Buffer
= NULL
;
1167 UCHAR
*RawBuffer
= NULL
;
1173 DWORD flags
= CREATE_NO_WINDOW
;
1174 CHAR StrBuf
[MAX_PATH
];
1175 CHAR tarName
[MAX_PATH
];
1177 PROCESS_INFORMATION Pi
;
1178 PROCESS_INFORMATION NewPi
;
1179 GET_LENGTH_INFORMATION LengthInfo
;
1180 SECURITY_ATTRIBUTES Sa
= { sizeof(SECURITY_ATTRIBUTES
), NULL
, TRUE
};
1182 Log("DecompressInjectionArchive %s", archive
);
1184 sprintf_s(StrBuf
, sizeof(StrBuf
), "\\\\.\\PhysicalDrive%d", PhyDrive
);
1185 hDrive
= CreateFileA(StrBuf
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
1186 if (hDrive
== INVALID_HANDLE_VALUE
)
1188 Log("Could not open the disk<%s>, error:%u", StrBuf
, GetLastError());
1192 bRet
= DeviceIoControl(hDrive
, IOCTL_DISK_GET_LENGTH_INFO
, NULL
, 0, &LengthInfo
, sizeof(LengthInfo
), &dwBytes
, NULL
);
1195 Log("Could not get phy disk %s size, error:%u", StrBuf
, GetLastError());
1199 g_FatPhyDrive
= hDrive
;
1200 g_Part2StartSec
= GetVentoyEfiPartStartSector(hDrive
);
1202 Log("Parse FAT fs...");
1206 if (0 == fl_attach_media(VentoyFatDiskRead
, NULL
))
1208 if (g_system_bit
== 64)
1210 CopyFileFromFatDisk("/ventoy/7z/64/7za.xz", "ventoy\\7za.xz");
1214 CopyFileFromFatDisk("/ventoy/7z/32/7za.xz", "ventoy\\7za.xz");
1217 ReadWholeFile2Buf("ventoy\\7za.xz", &Buffer
, &dwSize
);
1218 Log("7za.xz file size:%u", dwSize
);
1220 RawBuffer
= malloc(SIZE_1MB
* 4);
1223 g_unxz_buffer
= RawBuffer
;
1225 unxz(Buffer
, (int)dwSize
, NULL
, unxz_flush
, NULL
, &writelen
, unxz_error
);
1226 if (writelen
== (int)dwSize
)
1228 Log("Decompress success 7za.xz(%u) ---> 7za.exe(%d)", dwSize
, g_unxz_len
);
1232 Log("Decompress failed 7za.xz(%u) ---> 7za.exe(%u)", dwSize
, dwSize
);
1235 SaveBuffer2File("ventoy\\7za.exe", RawBuffer
, (DWORD
)g_unxz_len
);
1237 g_unxz_buffer
= NULL
;
1243 Log("Failed to alloc 4MB memory");
1246 sprintf_s(StrBuf
, sizeof(StrBuf
), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", archive
);
1248 Log("extract inject to X:");
1249 Log("cmdline:<%s>", StrBuf
);
1251 GetStartupInfoA(&Si
);
1253 hOut
= CreateFileA("ventoy\\7z.log",
1255 FILE_SHARE_WRITE
| FILE_SHARE_READ
,
1258 FILE_ATTRIBUTE_NORMAL
,
1261 Si
.dwFlags
|= STARTF_USESTDHANDLES
;
1263 if (hOut
!= INVALID_HANDLE_VALUE
)
1265 Si
.hStdError
= hOut
;
1266 Si
.hStdOutput
= hOut
;
1269 CreateProcessA(NULL
, StrBuf
, NULL
, NULL
, TRUE
, flags
, NULL
, NULL
, &Si
, &Pi
);
1270 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
1273 // decompress tar archive, for tar.gz/tar.xz/tar.bz2
1275 if (check_tar_archive(archive
, tarName
))
1277 Log("Decompress tar archive...<%s>", tarName
);
1279 sprintf_s(StrBuf
, sizeof(StrBuf
), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", tarName
);
1281 CreateProcessA(NULL
, StrBuf
, NULL
, NULL
, TRUE
, flags
, NULL
, NULL
, &Si
, &NewPi
);
1282 WaitForSingleObject(NewPi
.hProcess
, INFINITE
);
1284 Log("Now delete %s", tarName
);
1285 DeleteFileA(tarName
);
1288 SAFE_CLOSE_HANDLE(hOut
);
1294 SAFE_CLOSE_HANDLE(hDrive
);
1299 static int UnattendNeedVarExpand(const char *script
)
1304 fopen_s(&fp
, script
, "r");
1310 szLine
[0] = szLine
[4095] = 0;
1312 while (fgets(szLine
, sizeof(szLine
) - 1, fp
))
1314 if (strstr(szLine
, "$$VT_"))
1320 szLine
[0] = szLine
[4095] = 0;
1327 static int ExpandSingleVar(VarDiskInfo
*pDiskInfo
, int DiskNum
, const char *var
, char *value
, int len
)
1333 UINT64 uiMaxSize
= 0;
1334 UINT64 uiMaxDelta
= ULLONG_MAX
;
1338 if (strcmp(var
, "VT_WINDOWS_DISK_1ST_NONVTOY") == 0)
1340 for (i
= 0; i
< DiskNum
; i
++)
1342 if (pDiskInfo
[i
].Capacity
> 0 && i
!= g_vtoy_disk_drive
)
1344 Log("%s=<PhyDrive%d>", var
, i
);
1345 sprintf_s(value
, len
, "%d", i
);
1350 else if (strcmp(var
, "VT_WINDOWS_DISK_1ST_NONUSB") == 0)
1352 for (i
= 0; i
< DiskNum
; i
++)
1354 if (pDiskInfo
[i
].Capacity
> 0 && pDiskInfo
[i
].BusType
!= BusTypeUsb
)
1356 Log("%s=<PhyDrive%d>", var
, i
);
1357 sprintf_s(value
, len
, "%d", i
);
1362 else if (strcmp(var
, "VT_WINDOWS_DISK_MAX_SIZE") == 0)
1364 for (i
= 0; i
< DiskNum
; i
++)
1366 if (pDiskInfo
[i
].Capacity
> 0 && pDiskInfo
[i
].Capacity
> uiMaxSize
)
1369 uiMaxSize
= pDiskInfo
[i
].Capacity
;
1373 Log("%s=<PhyDrive%d>", var
, index
);
1374 sprintf_s(value
, len
, "%d", index
);
1376 else if (strncmp(var
, "VT_WINDOWS_DISK_CLOSEST_", 24) == 0)
1378 uiDst
= strtoul(var
+ 24, NULL
, 10);
1379 uiDst
= uiDst
* (1024ULL * 1024ULL * 1024ULL);
1381 for (i
= 0; i
< DiskNum
; i
++)
1383 if (pDiskInfo
[i
].Capacity
== 0)
1388 if (pDiskInfo
[i
].Capacity
> uiDst
)
1390 uiDelta
= pDiskInfo
[i
].Capacity
- uiDst
;
1394 uiDelta
= uiDst
- pDiskInfo
[i
].Capacity
;
1397 if (uiDelta
< uiMaxDelta
)
1399 uiMaxDelta
= uiDelta
;
1404 Log("%s=<PhyDrive%d>", var
, index
);
1405 sprintf_s(value
, len
, "%d", index
);
1409 Log("Invalid var name <%s>", var
);
1410 sprintf_s(value
, len
, "$$%s$$", var
);
1415 sprintf_s(value
, len
, "$$%s$$", var
);
1421 static void TrimString(CHAR
*String
)
1423 CHAR
*Pos1
= String
;
1424 CHAR
*Pos2
= String
;
1425 size_t Len
= strlen(String
);
1429 if (String
[Len
- 1] != ' ' && String
[Len
- 1] != '\t')
1433 String
[Len
- 1] = 0;
1437 while (*Pos1
== ' ' || *Pos1
== '\t')
1451 static int GetRegDwordValue(HKEY Key
, LPCSTR SubKey
, LPCSTR ValueName
, DWORD
*pValue
)
1459 lRet
= RegOpenKeyExA(Key
, SubKey
, 0, KEY_QUERY_VALUE
, &hKey
);
1460 Log("RegOpenKeyExA <%s> Ret:%ld", SubKey
, lRet
);
1462 if (ERROR_SUCCESS
== lRet
)
1464 Size
= sizeof(Value
);
1465 lRet
= RegQueryValueExA(hKey
, ValueName
, NULL
, &Type
, (LPBYTE
)&Value
, &Size
);
1466 Log("RegQueryValueExA <%s> ret:%u Size:%u Value:%u", ValueName
, lRet
, Size
, Value
);
1479 static const CHAR
* GetBusTypeString(int Type
)
1483 case BusTypeUnknown
: return "unknown";
1484 case BusTypeScsi
: return "SCSI";
1485 case BusTypeAtapi
: return "Atapi";
1486 case BusTypeAta
: return "ATA";
1487 case BusType1394
: return "1394";
1488 case BusTypeSsa
: return "SSA";
1489 case BusTypeFibre
: return "Fibre";
1490 case BusTypeUsb
: return "USB";
1491 case BusTypeRAID
: return "RAID";
1492 case BusTypeiScsi
: return "iSCSI";
1493 case BusTypeSas
: return "SAS";
1494 case BusTypeSata
: return "SATA";
1495 case BusTypeSd
: return "SD";
1496 case BusTypeMmc
: return "MMC";
1497 case BusTypeVirtual
: return "Virtual";
1498 case BusTypeFileBackedVirtual
: return "FileBackedVirtual";
1499 case BusTypeSpaces
: return "Spaces";
1500 case BusTypeNvme
: return "Nvme";
1505 static int GetHumanReadableGBSize(UINT64 SizeBytes
)
1510 double GB
= SizeBytes
* 1.0 / 1000 / 1000 / 1000;
1512 if ((SizeBytes
% 1073741824) == 0)
1514 return (int)(SizeBytes
/ 1073741824);
1517 for (i
= 0; i
< 12; i
++)
1521 Delta
= (Pow2
- GB
) / Pow2
;
1525 Delta
= (GB
- Pow2
) / Pow2
;
1539 static int EnumerateAllDisk(VarDiskInfo
**ppDiskInfo
, int *pDiskNum
)
1546 VarDiskInfo
*pDiskInfo
= NULL
;
1547 HANDLE Handle
= INVALID_HANDLE_VALUE
;
1549 GET_LENGTH_INFORMATION LengthInfo
;
1550 STORAGE_PROPERTY_QUERY Query
;
1551 STORAGE_DESCRIPTOR_HEADER DevDescHeader
;
1552 STORAGE_DEVICE_DESCRIPTOR
*pDevDesc
;
1554 if (GetRegDwordValue(HKEY_LOCAL_MACHINE
, "SYSTEM\\CurrentControlSet\\Services\\disk\\Enum", "Count", &Value
) == 0)
1556 DiskNum
= (int)Value
;
1560 Log("Failed to read disk count");
1564 Log("Current phy disk count:%d", DiskNum
);
1570 pDiskInfo
= malloc(DiskNum
* sizeof(VarDiskInfo
));
1573 Log("Failed to alloc");
1576 memset(pDiskInfo
, 0, DiskNum
* sizeof(VarDiskInfo
));
1578 for (i
= 0; i
< DiskNum
; i
++)
1580 SAFE_CLOSE_HANDLE(Handle
);
1582 safe_sprintf(PhyDrive
, "\\\\.\\PhysicalDrive%d", i
);
1583 Handle
= CreateFileA(PhyDrive
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
1584 Log("Create file Handle:%p %s status:%u", Handle
, PhyDrive
, LASTERR
);
1586 if (Handle
== INVALID_HANDLE_VALUE
)
1591 bRet
= DeviceIoControl(Handle
,
1592 IOCTL_DISK_GET_LENGTH_INFO
, NULL
,
1600 Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR
);
1604 Log("PHYSICALDRIVE%d size %llu bytes", i
, (ULONGLONG
)LengthInfo
.Length
.QuadPart
);
1606 Query
.PropertyId
= StorageDeviceProperty
;
1607 Query
.QueryType
= PropertyStandardQuery
;
1609 bRet
= DeviceIoControl(Handle
,
1610 IOCTL_STORAGE_QUERY_PROPERTY
,
1614 sizeof(STORAGE_DESCRIPTOR_HEADER
),
1619 Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR
, dwBytes
);
1623 if (DevDescHeader
.Size
< sizeof(STORAGE_DEVICE_DESCRIPTOR
))
1625 Log("Invalid DevDescHeader.Size:%u", DevDescHeader
.Size
);
1629 pDevDesc
= (STORAGE_DEVICE_DESCRIPTOR
*)malloc(DevDescHeader
.Size
);
1632 Log("failed to malloc error:%u len:%u", LASTERR
, DevDescHeader
.Size
);
1636 bRet
= DeviceIoControl(Handle
,
1637 IOCTL_STORAGE_QUERY_PROPERTY
,
1646 Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR
, dwBytes
);
1651 pDiskInfo
[i
].RemovableMedia
= pDevDesc
->RemovableMedia
;
1652 pDiskInfo
[i
].BusType
= pDevDesc
->BusType
;
1653 pDiskInfo
[i
].DeviceType
= pDevDesc
->DeviceType
;
1654 pDiskInfo
[i
].Capacity
= LengthInfo
.Length
.QuadPart
;
1656 if (pDevDesc
->VendorIdOffset
)
1658 safe_strcpy(pDiskInfo
[i
].VendorId
, (char *)pDevDesc
+ pDevDesc
->VendorIdOffset
);
1659 TrimString(pDiskInfo
[i
].VendorId
);
1662 if (pDevDesc
->ProductIdOffset
)
1664 safe_strcpy(pDiskInfo
[i
].ProductId
, (char *)pDevDesc
+ pDevDesc
->ProductIdOffset
);
1665 TrimString(pDiskInfo
[i
].ProductId
);
1668 if (pDevDesc
->ProductRevisionOffset
)
1670 safe_strcpy(pDiskInfo
[i
].ProductRev
, (char *)pDevDesc
+ pDevDesc
->ProductRevisionOffset
);
1671 TrimString(pDiskInfo
[i
].ProductRev
);
1674 if (pDevDesc
->SerialNumberOffset
)
1676 safe_strcpy(pDiskInfo
[i
].SerialNumber
, (char *)pDevDesc
+ pDevDesc
->SerialNumberOffset
);
1677 TrimString(pDiskInfo
[i
].SerialNumber
);
1681 SAFE_CLOSE_HANDLE(Handle
);
1684 Log("########## DUMP DISK BEGIN ##########");
1685 for (i
= 0; i
< DiskNum
; i
++)
1687 Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s",
1688 i
, GetBusTypeString(pDiskInfo
[i
].BusType
), pDiskInfo
[i
].RemovableMedia
,
1689 GetHumanReadableGBSize(pDiskInfo
[i
].Capacity
), pDiskInfo
[i
].Capacity
,
1690 pDiskInfo
[i
].VendorId
, pDiskInfo
[i
].ProductId
);
1692 Log("Ventoy disk is PhyDvr%d", g_vtoy_disk_drive
);
1693 Log("########## DUMP DISK END ##########");
1695 *ppDiskInfo
= pDiskInfo
;
1696 *pDiskNum
= DiskNum
;
1700 static int UnattendVarExpand(const char *script
, const char *tmpfile
)
1709 VarDiskInfo
*pDiskInfo
= NULL
;
1711 Log("UnattendVarExpand ...");
1713 if (EnumerateAllDisk(&pDiskInfo
, &DiskNum
))
1715 Log("Failed to EnumerateAllDisk");
1719 fopen_s(&fp
, script
, "r");
1726 fopen_s(&fout
, tmpfile
, "w+");
1734 szLine
[0] = szLine
[4095] = 0;
1736 while (fgets(szLine
, sizeof(szLine
) - 1, fp
))
1738 start
= strstr(szLine
, "$$VT_");
1741 end
= strstr(start
+ 5, "$$");
1747 fprintf(fout
, "%s", szLine
);
1750 ExpandSingleVar(pDiskInfo
, DiskNum
, start
+ 2, szValue
, sizeof(szValue
) - 1);
1751 fprintf(fout
, "%s", szValue
);
1753 fprintf(fout
, "%s", end
+ 2);
1757 fprintf(fout
, "%s", szLine
);
1760 szLine
[0] = szLine
[4095] = 0;
1769 //#define VAR_DEBUG 1
1771 static int ProcessUnattendedInstallation(const char *script
)
1777 CHAR TmpFile
[MAX_PATH
];
1778 CHAR CurDir
[MAX_PATH
];
1780 Log("Copy unattended XML ...");
1782 GetCurrentDirectory(sizeof(CurDir
), CurDir
);
1784 if ((Letter
>= 'A' && Letter
<= 'Z') || (Letter
>= 'a' && Letter
<= 'z'))
1786 Log("Current Drive Letter: %C", Letter
);
1794 sprintf_s(CurDir
, sizeof(CurDir
), "%C:\\AutounattendXXX.xml", Letter
);
1796 sprintf_s(CurDir
, sizeof(CurDir
), "%C:\\Autounattend.xml", Letter
);
1799 if (UnattendNeedVarExpand(script
))
1801 sprintf_s(TmpFile
, sizeof(TmpFile
), "%C:\\__Autounattend", Letter
);
1802 UnattendVarExpand(script
, TmpFile
);
1804 Log("Expand Copy file <%s> --> <%s>", script
, CurDir
);
1805 CopyFile(TmpFile
, CurDir
, FALSE
);
1809 Log("No var expand copy file <%s> --> <%s>", script
, CurDir
);
1810 CopyFile(script
, CurDir
, FALSE
);
1814 Ret
= RegCreateKeyEx(HKEY_LOCAL_MACHINE
, "System\\Setup", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hKey
, &dw
);
1815 if (ERROR_SUCCESS
== Ret
)
1817 Ret
= RegSetValueEx(hKey
, "UnattendFile", 0, REG_SZ
, CurDir
, (DWORD
)(strlen(CurDir
) + 1));
1824 static int Windows11BypassCheck(const char *isofile
, const char MntLetter
)
1831 CHAR
*Buffer
= NULL
;
1832 VS_FIXEDFILEINFO
* VerInfo
= NULL
;
1833 CHAR CheckFile
[MAX_PATH
];
1834 UINT16 Major
, Minor
, Build
, Revision
;
1836 Log("Windows11BypassCheck for <%s> %C:", isofile
, MntLetter
);
1838 if (FALSE
== IsFileExist("%C:\\sources\\boot.wim", MntLetter
) ||
1839 FALSE
== IsFileExist("%C:\\sources\\compatresources.dll", MntLetter
))
1841 Log("boot.wim/compatresources.dll not exist, this is not a windows install media.");
1845 if (FALSE
== IsFileExist("%C:\\sources\\install.wim", MntLetter
) &&
1846 FALSE
== IsFileExist("%C:\\sources\\install.esd", MntLetter
))
1848 Log("install.wim/install.esd not exist, this is not a windows install media.");
1852 sprintf_s(CheckFile
, sizeof(CheckFile
), "%C:\\sources\\compatresources.dll", MntLetter
);
1853 dwSize
= GetFileVersionInfoSizeA(CheckFile
, &dwHandle
);
1856 Log("Failed to get file version info size: %u", LASTERR
);
1860 Buffer
= malloc(dwSize
);
1866 if (FALSE
== GetFileVersionInfoA(CheckFile
, dwHandle
, dwSize
, Buffer
))
1868 Log("Failed to get file version info : %u", LASTERR
);
1872 if (VerQueryValueA(Buffer
, "\\", (LPVOID
)&VerInfo
, &VerLen
) && VerLen
!= 0)
1874 if (VerInfo
->dwSignature
== VS_FFI_SIGNATURE
)
1876 Major
= HIWORD(VerInfo
->dwFileVersionMS
);
1877 Minor
= LOWORD(VerInfo
->dwFileVersionMS
);
1878 Build
= HIWORD(VerInfo
->dwFileVersionLS
);
1879 Revision
= LOWORD(VerInfo
->dwFileVersionLS
);
1881 Log("FileVersionze: <%u %u %u %u>", Major
, Minor
, Build
, Revision
);
1883 if (Major
== 10 && Build
> 20000)
1890 Log("This is not Windows 11, not need to bypass.", Major
);
1896 //Now we really need to bypass windows 11 check. create registry
1898 HKEY hSubKey
= NULL
;
1901 Status
= RegCreateKeyExA(HKEY_LOCAL_MACHINE
, "System\\Setup", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hKey
, &dwSize
);
1902 if (ERROR_SUCCESS
!= Status
)
1904 Log("Failed to create reg key System\\Setup %u %u", LASTERR
, Status
);
1908 Status
= RegCreateKeyExA(hKey
, "LabConfig", 0, NULL
, 0, KEY_SET_VALUE
| KEY_QUERY_VALUE
| KEY_CREATE_SUB_KEY
, NULL
, &hSubKey
, &dwSize
);
1909 if (ERROR_SUCCESS
!= Status
)
1911 Log("Failed to create LabConfig reg %u %u", LASTERR
, Status
);
1916 Status
+= RegSetValueExA(hSubKey
, "BypassRAMCheck", 0, REG_DWORD
, (LPBYTE
)&dwValue
, sizeof(DWORD
));
1917 Status
+= RegSetValueExA(hSubKey
, "BypassTPMCheck", 0, REG_DWORD
, (LPBYTE
)&dwValue
, sizeof(DWORD
));
1918 Status
+= RegSetValueExA(hSubKey
, "BypassSecureBootCheck", 0, REG_DWORD
, (LPBYTE
)&dwValue
, sizeof(DWORD
));
1919 Status
+= RegSetValueExA(hSubKey
, "BypassStorageCheck", 0, REG_DWORD
, (LPBYTE
)&dwValue
, sizeof(DWORD
));
1920 Status
+= RegSetValueExA(hSubKey
, "BypassCPUCheck", 0, REG_DWORD
, (LPBYTE
)&dwValue
, sizeof(DWORD
));
1922 Log("Create bypass registry %s %u", (Status
== ERROR_SUCCESS
) ? "SUCCESS" : "FAILED", Status
);
1935 static BOOL
CheckVentoyDisk(DWORD DiskNum
)
1939 UINT8 SectorBuf
[512];
1941 UINT8 check
[8] = { 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44 };
1943 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\PhysicalDrive%d", DiskNum
);
1944 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
1945 if (Handle
== INVALID_HANDLE_VALUE
)
1947 Log("Could not open the disk<%s>, error:%u", PhyPath
, GetLastError());
1951 if (!ReadFile(Handle
, SectorBuf
, sizeof(SectorBuf
), &dwSize
, NULL
))
1953 Log("ReadFile failed, dwSize:%u error:%u", dwSize
, GetLastError());
1954 CloseHandle(Handle
);
1958 CloseHandle(Handle
);
1960 if (memcmp(SectorBuf
+ 0x190, check
, 8) == 0)
1968 static int GetWinpeshlIniFileAttr(WinpeshlIniAttr
*pAttr
)
1973 hFile
= CreateFileA(WINPESHL_INI
, FILE_READ_EA
, FILE_SHARE_READ
, 0, OPEN_EXISTING
, 0, 0);
1974 if (hFile
== INVALID_HANDLE_VALUE
)
1976 Log("Could not open the file<%s>, error:%u", WINPESHL_INI
, GetLastError());
1980 pAttr
->FileSize
= (INT
)GetFileSize(hFile
, NULL
);
1981 GetFileTime(hFile
, &pAttr
->CreateTime
, &pAttr
->LastAccessTime
, &pAttr
->LastWriteTime
);
1983 FileTimeToSystemTime(&pAttr
->LastWriteTime
, &systime
);
1984 Log("Winpeshl.ini size:%d LastWriteTime:<%04u/%02u/%02u %02u:%02u:%02u.%03u>",
1986 systime
.wYear
, systime
.wMonth
, systime
.wDay
,
1987 systime
.wHour
, systime
.wMinute
, systime
.wSecond
,
1988 systime
.wMilliseconds
);
1994 static int VentoyHook(ventoy_os_param
*param
)
1999 BOOL vtoyfind
= FALSE
;
2008 DISK_EXTENT DiskExtent
;
2009 DISK_EXTENT VtoyDiskExtent
;
2011 CHAR IsoPath
[MAX_PATH
];
2013 Log("VentoyHook Path:<%s>", param
->vtoy_img_path
);
2015 g_winpeshl_ini_updated
= 0;
2017 if (IsUTF8Encode(param
->vtoy_img_path
))
2019 Log("This file is UTF8 encoding");
2022 for (i
= 0; i
< 5; i
++)
2025 Drives
= GetLogicalDrives();
2026 Log("Logic Drives: 0x%x", Drives
);
2032 sprintf_s(IsoPath
, sizeof(IsoPath
), "%C:\\%s", Letter
, param
->vtoy_img_path
);
2033 if (IsFileExist("%s", IsoPath
))
2035 Log("File exist under %C:", Letter
);
2036 memset(UUID
, 0, sizeof(UUID
));
2037 memset(&DiskExtent
, 0, sizeof(DiskExtent
));
2038 if (GetPhyDiskUUID(Letter
, UUID
, NULL
, &DiskExtent
) == 0)
2040 if (memcmp(UUID
, param
->vtoy_disk_guid
, 16) == 0)
2042 Log("Disk UUID match");
2050 Log("File NOT exist under %C:", Letter
);
2064 Log("Now wait and retry ...");
2071 Log("Failed to find ISO file");
2075 Log("Find ISO file <%s>", IsoPath
);
2077 //Find VtoyLetter in Vlnk Mode
2078 if (g_os_param_reserved
[6] == 1)
2080 memcpy(&VtoySig
, g_os_param_reserved
+ 7, 4);
2081 for (i
= 0; i
< 5; i
++)
2084 Drives
= GetLogicalDrives();
2085 Log("Logic Drives: 0x%x VentoySig:%08X", Drives
, VtoySig
);
2091 memset(UUID
, 0, sizeof(UUID
));
2092 memset(&VtoyDiskExtent
, 0, sizeof(VtoyDiskExtent
));
2094 if (GetPhyDiskUUID(VtoyLetter
, UUID
, &DiskSig
, &VtoyDiskExtent
) == 0)
2096 Log("DiskSig=%08X PartStart=%lld", DiskSig
, VtoyDiskExtent
.StartingOffset
.QuadPart
);
2097 if (DiskSig
== VtoySig
&& VtoyDiskExtent
.StartingOffset
.QuadPart
== SIZE_1MB
)
2099 Log("Ventoy Disk Sig match");
2112 Log("Find Ventoy Letter: %C", VtoyLetter
);
2117 Log("Now wait and retry ...");
2122 if (vtoyfind
== FALSE
)
2124 Log("Failed to find ventoy disk");
2128 VtoyDiskNum
= VtoyDiskExtent
.DiskNumber
;
2132 VtoyLetter
= Letter
;
2133 Log("No vlnk mode %C", Letter
);
2135 VtoyDiskNum
= DiskExtent
.DiskNumber
;
2138 if (CheckVentoyDisk(VtoyDiskNum
))
2140 Log("Disk check OK %C: %u", VtoyLetter
, VtoyDiskNum
);
2144 Log("Failed to check ventoy disk %u", VtoyDiskNum
);
2148 g_vtoy_disk_drive
= VtoyDiskNum
;
2150 Drives
= GetLogicalDrives();
2151 Log("Drives before mount: 0x%x", Drives
);
2153 rc
= MountIsoFile(IsoPath
, VtoyDiskNum
);
2155 NewDrives
= GetLogicalDrives();
2156 Log("Drives after mount: 0x%x (0x%x)", NewDrives
, (NewDrives
^ Drives
));
2159 NewDrives
= (NewDrives
^ Drives
);
2162 if (NewDrives
& 0x01)
2164 if ((NewDrives
>> 1) == 0)
2166 Log("The ISO file is mounted at %C:", MntLetter
);
2170 Log("Maybe the ISO file is mounted at %C:", MntLetter
);
2179 Log("Mount ISO FILE: %s", rc
== 0 ? "SUCCESS" : "FAILED");
2181 //Windows 11 bypass check
2182 if (g_windows_data
.windows11_bypass_check
== 1)
2184 Windows11BypassCheck(IsoPath
, MntLetter
);
2188 rc
= DeleteVentoyPart2MountPoint(VtoyDiskNum
);
2189 Log("Delete ventoy mountpoint: %s", rc
== 0 ? "SUCCESS" : "NO NEED");
2191 if (g_windows_data
.auto_install_script
[0])
2193 if (IsFileExist("%s", VTOY_AUTO_FILE
))
2195 Log("use auto install script %s...", VTOY_AUTO_FILE
);
2196 ProcessUnattendedInstallation(VTOY_AUTO_FILE
);
2200 Log("auto install script %s not exist", IsoPath
);
2205 Log("auto install no need");
2208 if (g_windows_data
.injection_archive
[0])
2210 sprintf_s(IsoPath
, sizeof(IsoPath
), "%C:%s", VtoyLetter
, g_windows_data
.injection_archive
);
2211 if (IsFileExist("%s", IsoPath
))
2213 int rc1
= -1, rc2
= -1;
2214 WinpeshlIniAttr Attr1
, Attr2
;
2215 memset(&Attr1
, 0, sizeof(Attr1
));
2216 memset(&Attr2
, 0, sizeof(Attr2
));
2218 Log("decompress injection archive %s...", IsoPath
);
2220 if (IsFileExist(WINPESHL_INI
))
2222 rc1
= GetWinpeshlIniFileAttr(&Attr1
);
2225 DecompressInjectionArchive(IsoPath
, VtoyDiskNum
);
2227 if (IsFileExist(WINPESHL_INI
))
2229 rc2
= GetWinpeshlIniFileAttr(&Attr2
);
2230 if (rc1
== rc2
&& rc1
== 0)
2232 if (Attr1
.FileSize
!= Attr2
.FileSize
||
2233 Attr1
.LastWriteTime
.dwHighDateTime
!= Attr2
.LastWriteTime
.dwHighDateTime
||
2234 Attr1
.LastWriteTime
.dwLowDateTime
!= Attr2
.LastWriteTime
.dwLowDateTime
)
2236 Log("winpeshl.ini file updated");
2237 g_winpeshl_ini_updated
= 1;
2242 if (IsFileExist("%s", AUTO_RUN_BAT
))
2245 DWORD flags
= CREATE_NO_WINDOW
;
2248 PROCESS_INFORMATION Pi
;
2249 SECURITY_ATTRIBUTES Sa
= { sizeof(SECURITY_ATTRIBUTES
), NULL
, TRUE
};
2251 Log("%s exist, now run it...", AUTO_RUN_BAT
);
2253 GetStartupInfoA(&Si
);
2255 hOut
= CreateFileA(AUTO_RUN_LOG
,
2257 FILE_SHARE_WRITE
| FILE_SHARE_READ
,
2260 FILE_ATTRIBUTE_NORMAL
,
2263 Si
.dwFlags
|= STARTF_USESTDHANDLES
;
2264 if (hOut
!= INVALID_HANDLE_VALUE
)
2266 Si
.hStdError
= hOut
;
2267 Si
.hStdOutput
= hOut
;
2270 sprintf_s(IsoPath
, sizeof(IsoPath
), "%C:\\%s", Letter
, param
->vtoy_img_path
);
2271 sprintf_s(StrBuf
, sizeof(StrBuf
), "cmd.exe /c %s \"%s\" %C", AUTO_RUN_BAT
, IsoPath
, MntLetter
);
2272 CreateProcessA(NULL
, StrBuf
, NULL
, NULL
, TRUE
, flags
, NULL
, NULL
, &Si
, &Pi
);
2273 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
2275 SAFE_CLOSE_HANDLE(hOut
);
2279 Log("%s not exist...", AUTO_RUN_BAT
);
2284 Log("injection archive %s not exist", IsoPath
);
2289 Log("no injection archive found");
2295 static int ExtractWindowsDataFile(char *databuf
)
2298 char *filedata
= NULL
;
2299 ventoy_windows_data
*pdata
= (ventoy_windows_data
*)databuf
;
2301 Log("ExtractWindowsDataFile: auto install <%s:%d>", pdata
->auto_install_script
, pdata
->auto_install_len
);
2303 filedata
= databuf
+ sizeof(ventoy_windows_data
);
2305 if (pdata
->auto_install_script
[0] && pdata
->auto_install_len
> 0)
2307 SaveBuffer2File(VTOY_AUTO_FILE
, filedata
, pdata
->auto_install_len
);
2308 filedata
+= pdata
->auto_install_len
;
2309 len
= pdata
->auto_install_len
;
2315 int VentoyJumpWimboot(INT argc
, CHAR
**argv
, CHAR
*LunchFile
)
2322 Log("VentoyJumpWimboot %dbit", g_system_bit
);
2324 sprintf_s(LunchFile
, MAX_PATH
, "X:\\setup.exe");
2326 ReadWholeFile2Buf("wimboot.data", &buf
, &size
);
2327 Log("wimboot.data size:%d", size
);
2329 memcpy(&g_os_param
, buf
, sizeof(ventoy_os_param
));
2330 memcpy(&g_windows_data
, buf
+ sizeof(ventoy_os_param
), sizeof(ventoy_windows_data
));
2331 ExtractWindowsDataFile(buf
+ sizeof(ventoy_os_param
));
2332 memcpy(g_os_param_reserved
, g_os_param
.vtoy_reserved
, sizeof(g_os_param_reserved
));
2334 if (g_os_param_reserved
[0] == 1)
2336 Log("break here for debug .....");
2341 for (Pos
= 0; Pos
< sizeof(g_os_param
.vtoy_img_path
) && g_os_param
.vtoy_img_path
[Pos
]; Pos
++)
2343 if (g_os_param
.vtoy_img_path
[Pos
] == '/')
2345 g_os_param
.vtoy_img_path
[Pos
] = '\\';
2349 if (g_os_param_reserved
[0] == 2)
2351 Log("skip hook for debug .....");
2356 rc
= VentoyHook(&g_os_param
);
2368 static int ventoy_check_create_directory(void)
2370 if (IsDirExist("ventoy"))
2372 Log("ventoy directory already exist");
2376 Log("ventoy directory not exist, now create it.");
2377 if (!CreateDirectoryA("ventoy", NULL
))
2379 Log("Failed to create ventoy directory err:%u", GetLastError());
2387 int VentoyJump(INT argc
, CHAR
**argv
, CHAR
*LunchFile
)
2395 DWORD LockStatus
= 0;
2396 BYTE
*Buffer
= NULL
;
2397 CHAR ExeFileName
[MAX_PATH
];
2399 sprintf_s(ExeFileName
, sizeof(ExeFileName
), "%s", argv
[0]);
2400 if (!IsFileExist("%s", ExeFileName
))
2402 Log("File %s NOT exist, now try %s.exe", ExeFileName
, ExeFileName
);
2403 sprintf_s(ExeFileName
, sizeof(ExeFileName
), "%s.exe", argv
[0]);
2405 Log("File %s exist ? %s", ExeFileName
, IsFileExist("%s", ExeFileName
) ? "YES" : "NO");
2408 if (ReadWholeFile2Buf(ExeFileName
, (void **)&Buffer
, &FileSize
))
2413 Log("VentoyJump %dbit", g_system_bit
);
2415 MUTEX_LOCK(g_vtoyins_mutex
);
2416 stat
= ventoy_check_create_directory();
2417 MUTEX_UNLOCK(g_vtoyins_mutex
);
2424 for (PeStart
= 0; PeStart
< FileSize
; PeStart
+= 16)
2426 if (CheckOsParam((ventoy_os_param
*)(Buffer
+ PeStart
)) &&
2427 CheckPeHead(Buffer
, FileSize
, PeStart
+ sizeof(ventoy_os_param
)))
2429 Log("Find os pararm at %u", PeStart
);
2431 memcpy(&g_os_param
, Buffer
+ PeStart
, sizeof(ventoy_os_param
));
2432 memcpy(&g_windows_data
, Buffer
+ PeStart
+ sizeof(ventoy_os_param
), sizeof(ventoy_windows_data
));
2433 exlen
= ExtractWindowsDataFile(Buffer
+ PeStart
+ sizeof(ventoy_os_param
));
2434 memcpy(g_os_param_reserved
, g_os_param
.vtoy_reserved
, sizeof(g_os_param_reserved
));
2436 if (g_os_param_reserved
[0] == 1)
2438 Log("break here for debug .....");
2443 for (Pos
= 0; Pos
< sizeof(g_os_param
.vtoy_img_path
) && g_os_param
.vtoy_img_path
[Pos
]; Pos
++)
2445 if (g_os_param
.vtoy_img_path
[Pos
] == '/')
2447 g_os_param
.vtoy_img_path
[Pos
] = '\\';
2451 PeStart
+= sizeof(ventoy_os_param
) + sizeof(ventoy_windows_data
) + exlen
;
2452 sprintf_s(LunchFile
, MAX_PATH
, "ventoy\\%s", GetFileNameInPath(ExeFileName
));
2454 MUTEX_LOCK(g_vtoyins_mutex
);
2455 if (IsFileExist("%s", LunchFile
))
2457 Log("vtoyjump multiple call ...");
2459 MUTEX_UNLOCK(g_vtoyins_mutex
);
2463 SaveBuffer2File(LunchFile
, Buffer
+ PeStart
, FileSize
- PeStart
);
2464 MUTEX_UNLOCK(g_vtoyins_mutex
);
2470 if (PeStart
>= FileSize
)
2472 Log("OS param not found");
2476 if (g_os_param_reserved
[0] == 2)
2478 Log("skip hook for debug .....");
2483 rc
= VentoyHook(&g_os_param
);
2496 int real_main(int argc
, char **argv
)
2501 CHAR NewFile
[MAX_PATH
];
2502 CHAR LunchFile
[MAX_PATH
];
2503 CHAR CallParam
[1024] = { 0 };
2505 PROCESS_INFORMATION Pi
;
2507 Log("#### real_main #### argc = %d", argc
);
2508 Log("program full path: <%s>", g_prog_full_path
);
2509 Log("program dir: <%s>", g_prog_dir
);
2510 Log("program name:: <%s>", g_prog_name
);
2512 Log("argc = %d", argc
);
2513 for (i
= 0; i
< argc
; i
++)
2515 Log("argv[%d]=<%s>", i
, argv
[i
]);
2518 strcat_s(CallParam
, sizeof(CallParam
), " ");
2519 strcat_s(CallParam
, sizeof(CallParam
), argv
[i
]);
2523 GetStartupInfoA(&Si
);
2524 memset(LunchFile
, 0, sizeof(LunchFile
));
2526 if (strstr(argv
[0], "vtoyjump.exe"))
2529 rc
= VentoyJumpWimboot(argc
, argv
, LunchFile
);
2533 rc
= VentoyJump(argc
, argv
, LunchFile
);
2536 Log("LunchFile=<%s> CallParam=<%s>", LunchFile
, CallParam
);
2538 if (_stricmp(g_prog_name
, "winpeshl.exe") != 0 && IsFileExist("ventoy\\%s", g_prog_name
))
2540 sprintf_s(NewFile
, sizeof(NewFile
), "%s_BACK.EXE", g_prog_full_path
);
2541 MoveFileA(g_prog_full_path
, NewFile
);
2542 Log("Move <%s> to <%s>", g_prog_full_path
, NewFile
);
2544 sprintf_s(NewFile
, sizeof(NewFile
), "ventoy\\%s", g_prog_name
);
2545 CopyFileA(NewFile
, g_prog_full_path
, TRUE
);
2546 Log("Copy <%s> to <%s>", NewFile
, g_prog_full_path
);
2548 sprintf_s(LunchFile
, sizeof(LunchFile
), "%s", g_prog_full_path
);
2549 Log("Final lunchFile is <%s>", LunchFile
);
2551 else if (wimboot
&& g_winpeshl_ini_updated
)
2553 sprintf_s(LunchFile
, MAX_PATH
, "X:\\Windows\\system32\\winpeshl.exe");
2554 Log("Recall winpeshl.exe");
2558 Log("We don't need to recover original <%s>", g_prog_name
);
2561 if (g_os_param_reserved
[0] == 3)
2563 Log("Open log for debug ...");
2564 sprintf_s(LunchFile
, sizeof(LunchFile
), "%s", "notepad.exe ventoy.log");
2570 strcat_s(LunchFile
, sizeof(LunchFile
), CallParam
);
2572 else if (NULL
== strstr(LunchFile
, "setup.exe"))
2574 Log("Not setup.exe, hide windows.");
2575 Si
.dwFlags
|= STARTF_USESHOWWINDOW
;
2576 Si
.wShowWindow
= SW_HIDE
;
2579 Log("Ventoy jump %s ...", rc
== 0 ? "success" : "failed");
2582 Log("Now launch <%s> ...", LunchFile
);
2584 if (g_os_param_reserved
[0] == 4)
2586 Log("Open cmd for debug ...");
2587 sprintf_s(LunchFile
, sizeof(LunchFile
), "%s", "cmd.exe");
2590 Log("Backup log at this point");
2591 CopyFileA(LOG_FILE
, "X:\\Windows\\ventoy.backup", TRUE
);
2593 CreateProcessA(NULL
, LunchFile
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
2595 for (i
= 0; rc
&& i
< 1800; i
++)
2597 Log("Ventoy hook failed, now wait and retry ...");
2599 rc
= VentoyHook(&g_os_param
);
2602 Log("Wait process...");
2603 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
2605 Log("vtoyjump finished");
2609 static void VentoyToUpper(CHAR
*str
)
2612 for (i
= 0; str
[i
]; i
++)
2614 str
[i
] = (CHAR
)toupper(str
[i
]);
2618 int main(int argc
, char **argv
)
2622 PROCESS_INFORMATION Pi
;
2623 CHAR CurDir
[MAX_PATH
];
2624 CHAR NewArgv0
[MAX_PATH
];
2625 CHAR CallParam
[1024] = { 0 };
2627 g_vtoylog_mutex
= CreateMutexA(NULL
, FALSE
, "VTOYLOG_LOCK");
2628 g_vtoyins_mutex
= CreateMutexA(NULL
, FALSE
, "VTOYINS_LOCK");
2630 Log("######## VentoyJump %dbit ##########", g_system_bit
);
2632 GetCurrentDirectoryA(sizeof(CurDir
), CurDir
);
2633 Log("Current directory is <%s>", CurDir
);
2635 GetModuleFileNameA(NULL
, g_prog_full_path
, MAX_PATH
);
2636 split_path_name(g_prog_full_path
, g_prog_dir
, g_prog_name
);
2638 Log("EXE path: <%s> dir:<%s> name:<%s>", g_prog_full_path
, g_prog_dir
, g_prog_name
);
2640 if (_stricmp(g_prog_name
, "WinLogon.exe") == 0)
2642 Log("This time is rejump back ...");
2644 strcpy_s(g_prog_full_path
, sizeof(g_prog_full_path
), argv
[1]);
2645 split_path_name(g_prog_full_path
, g_prog_dir
, g_prog_name
);
2647 return real_main(argc
- 1, argv
+ 1);
2649 else if (_stricmp(g_prog_name
, "PECMD.exe") == 0)
2651 strcpy_s(NewArgv0
, sizeof(NewArgv0
), g_prog_dir
);
2652 VentoyToUpper(NewArgv0
);
2654 if (NULL
== strstr(NewArgv0
, "SYSTEM32") && IsFileExist(ORG_PECMD_BK_PATH
))
2656 Log("Just call original pecmd.exe");
2657 strcpy_s(CallParam
, sizeof(CallParam
), ORG_PECMD_PATH
);
2661 Log("We need to rejump for pecmd ...");
2663 ventoy_check_create_directory();
2664 CopyFileA(g_prog_full_path
, "ventoy\\WinLogon.exe", TRUE
);
2666 sprintf_s(CallParam
, sizeof(CallParam
), "ventoy\\WinLogon.exe %s", g_prog_full_path
);
2669 for (i
= 1; i
< argc
; i
++)
2671 strcat_s(CallParam
, sizeof(CallParam
), " ");
2672 strcat_s(CallParam
, sizeof(CallParam
), argv
[i
]);
2675 Log("Now rejump to <%s> ...", CallParam
);
2676 GetStartupInfoA(&Si
);
2677 CreateProcessA(NULL
, CallParam
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
2679 Log("Wait rejump process...");
2680 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
2681 Log("rejump finished");
2686 Log("We don't need to rejump ...");
2688 ventoy_check_create_directory();
2689 strcpy_s(NewArgv0
, sizeof(NewArgv0
), g_prog_full_path
);
2692 return real_main(argc
, argv
);