1 /******************************************************************************
4 * Copyright (c) 2020, 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 BOOL g_64bit_system
= FALSE
;
35 static ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
37 void Log(const char *Fmt
, ...)
46 Len
+= sprintf_s(szBuf
, sizeof(szBuf
),
47 "[%4d/%02d/%02d %02d:%02d:%02d.%03d] ",
48 Sys
.wYear
, Sys
.wMonth
, Sys
.wDay
,
49 Sys
.wHour
, Sys
.wMinute
, Sys
.wSecond
,
53 Len
+= vsnprintf_s(szBuf
+ Len
, sizeof(szBuf
)-Len
, sizeof(szBuf
)-Len
, Fmt
, Arg
);
56 fopen_s(&File
, "ventoy.log", "a+");
59 fwrite(szBuf
, 1, Len
, File
);
60 fwrite("\n", 1, 1, File
);
66 static int LoadNtDriver(const char *DrvBinPath
)
72 SC_HANDLE hServiceMgr
;
74 char name
[256] = { 0 };
76 for (i
= (int)strlen(DrvBinPath
) - 1; i
>= 0; i
--)
78 if (DrvBinPath
[i
] == '\\' || DrvBinPath
[i
] == '/')
80 sprintf_s(name
, sizeof(name
), "%s", DrvBinPath
+ i
+ 1);
85 Log("Load NT driver: %s %s", DrvBinPath
, name
);
87 hServiceMgr
= OpenSCManagerA(NULL
, NULL
, SC_MANAGER_ALL_ACCESS
);
88 if (hServiceMgr
== NULL
)
90 Log("OpenSCManager failed Error:%u", GetLastError());
94 Log("OpenSCManager OK");
96 hService
= CreateServiceA(hServiceMgr
,
100 SERVICE_KERNEL_DRIVER
,
101 SERVICE_DEMAND_START
,
102 SERVICE_ERROR_NORMAL
,
104 NULL
, NULL
, NULL
, NULL
, NULL
);
105 if (hService
== NULL
)
107 Status
= GetLastError();
108 if (Status
!= ERROR_IO_PENDING
&& Status
!= ERROR_SERVICE_EXISTS
)
110 Log("CreateService failed v %u", Status
);
111 CloseServiceHandle(hServiceMgr
);
115 hService
= OpenServiceA(hServiceMgr
, name
, SERVICE_ALL_ACCESS
);
116 if (hService
== NULL
)
118 Log("OpenService failed %u", Status
);
119 CloseServiceHandle(hServiceMgr
);
124 Log("CreateService imdisk OK");
126 Ret
= StartServiceA(hService
, 0, NULL
);
129 Log("StartService OK");
133 Status
= GetLastError();
134 if (Status
== ERROR_SERVICE_ALREADY_RUNNING
)
140 Log("StartService error %u", Status
);
145 CloseServiceHandle(hService
);
146 CloseServiceHandle(hServiceMgr
);
148 Log("Load NT driver %s", rc
? "failed" : "success");
153 static int ReadWholeFile2Buf(const char *Fullpath
, void **Data
, DWORD
*Size
)
161 Log("ReadWholeFile2Buf <%s>", Fullpath
);
163 Handle
= CreateFileA(Fullpath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
164 if (Handle
== INVALID_HANDLE_VALUE
)
166 Log("Could not open the file<%s>, error:%u", Fullpath
, GetLastError());
170 FileSize
= SetFilePointer(Handle
, 0, NULL
, FILE_END
);
172 Buffer
= malloc(FileSize
);
175 Log("Failed to alloc memory size:%u", FileSize
);
179 SetFilePointer(Handle
, 0, NULL
, FILE_BEGIN
);
180 if (!ReadFile(Handle
, Buffer
, FileSize
, &dwSize
, NULL
))
182 Log("ReadFile failed, dwSize:%u error:%u", dwSize
, GetLastError());
189 Log("Success read file size:%u", FileSize
);
194 SAFE_CLOSE_HANDLE(Handle
);
199 static BOOL
CheckPeHead(BYTE
*Head
)
203 if (Head
[0] != 'M' || Head
[1] != 'Z')
208 PeOffset
= *(UINT32
*)(Head
+ 60);
209 if (*(UINT32
*)(Head
+ PeOffset
) != 0x00004550)
217 static BOOL
IsPe64(BYTE
*buffer
)
221 if (!CheckPeHead(buffer
))
226 pe_off
= *(UINT32
*)(buffer
+ 60);
227 if (*(UINT16
*)(buffer
+ pe_off
+ 24) == 0x020b)
236 static BOOL
CheckOsParam(ventoy_os_param
*param
)
241 if (memcmp(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
)))
246 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
248 Sum
+= *((BYTE
*)param
+ i
);
256 if (param
->vtoy_img_location_addr
% 4096)
264 static int SaveBuffer2File(const char *Fullpath
, void *Buffer
, DWORD Length
)
270 Log("SaveBuffer2File <%s> len:%u", Fullpath
, Length
);
272 Handle
= CreateFileA(Fullpath
, GENERIC_READ
| GENERIC_WRITE
,
273 FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, CREATE_NEW
, 0, 0);
274 if (Handle
== INVALID_HANDLE_VALUE
)
276 Log("Could not create new file, error:%u", GetLastError());
280 WriteFile(Handle
, Buffer
, Length
, &dwSize
, NULL
);
285 SAFE_CLOSE_HANDLE(Handle
);
290 static int IsUTF8Encode(const char *src
)
293 const UCHAR
*Byte
= (const UCHAR
*)src
;
295 for (i
= 0; i
< MAX_PATH
&& Byte
[i
]; i
++)
306 static int Utf8ToUtf16(const char* src
, WCHAR
* dst
)
308 int size
= MultiByteToWideChar(CP_UTF8
, 0, src
, -1, dst
, 0);
309 return MultiByteToWideChar(CP_UTF8
, 0, src
, -1, dst
, size
+ 1);
312 static BOOL
IsDirExist(const char *Fmt
, ...)
317 CHAR FilePathA
[MAX_PATH
];
318 WCHAR FilePathW
[MAX_PATH
];
321 vsnprintf_s(FilePathA
, sizeof(FilePathA
), sizeof(FilePathA
), Fmt
, Arg
);
324 UTF8
= IsUTF8Encode(FilePathA
);
328 Utf8ToUtf16(FilePathA
, FilePathW
);
329 Attr
= GetFileAttributesW(FilePathW
);
333 Attr
= GetFileAttributesA(FilePathA
);
336 if (Attr
!= INVALID_FILE_ATTRIBUTES
&& (Attr
& FILE_ATTRIBUTE_DIRECTORY
))
344 static BOOL
IsFileExist(const char *Fmt
, ...)
351 CHAR FilePathA
[MAX_PATH
];
352 WCHAR FilePathW
[MAX_PATH
];
355 vsnprintf_s(FilePathA
, sizeof(FilePathA
), sizeof(FilePathA
), Fmt
, Arg
);
358 UTF8
= IsUTF8Encode(FilePathA
);
362 Utf8ToUtf16(FilePathA
, FilePathW
);
363 hFile
= CreateFileW(FilePathW
, FILE_READ_EA
, FILE_SHARE_READ
, 0, OPEN_EXISTING
, 0, 0);
367 hFile
= CreateFileA(FilePathA
, FILE_READ_EA
, FILE_SHARE_READ
, 0, OPEN_EXISTING
, 0, 0);
369 if (INVALID_HANDLE_VALUE
== hFile
)
378 Attr
= GetFileAttributesW(FilePathW
);
382 Attr
= GetFileAttributesA(FilePathA
);
385 if (Attr
& FILE_ATTRIBUTE_DIRECTORY
)
393 Log("File <%s> %s", FilePathA
, (bRet
? "exist" : "NOT exist"));
397 static int GetPhyDiskUUID(const char LogicalDrive
, UINT8
*UUID
, DISK_EXTENT
*DiskExtent
)
402 VOLUME_DISK_EXTENTS DiskExtents
;
404 UINT8 SectorBuf
[512];
406 Log("GetPhyDiskUUID %C", LogicalDrive
);
408 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\%C:", LogicalDrive
);
409 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
410 if (Handle
== INVALID_HANDLE_VALUE
)
412 Log("Could not open the disk<%s>, error:%u", PhyPath
, GetLastError());
416 Ret
= DeviceIoControl(Handle
,
417 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
421 (DWORD
)(sizeof(DiskExtents
)),
424 if (!Ret
|| DiskExtents
.NumberOfDiskExtents
== 0)
426 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed, error:%u", GetLastError());
432 memcpy(DiskExtent
, DiskExtents
.Extents
, sizeof(DiskExtent
));
433 Log("%C: is in PhysicalDrive%d ", LogicalDrive
, DiskExtents
.Extents
[0].DiskNumber
);
435 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\PhysicalDrive%d", DiskExtents
.Extents
[0].DiskNumber
);
436 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
437 if (Handle
== INVALID_HANDLE_VALUE
)
439 Log("Could not open the disk<%s>, error:%u", PhyPath
, GetLastError());
443 if (!ReadFile(Handle
, SectorBuf
, sizeof(SectorBuf
), &dwSize
, NULL
))
445 Log("ReadFile failed, dwSize:%u error:%u", dwSize
, GetLastError());
450 memcpy(UUID
, SectorBuf
+ 0x180, 16);
455 static int VentoyMountAnywhere(HANDLE Handle
)
458 ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters
;
460 Log("VentoyMountAnywhere");
462 memset(&AttachParameters
, 0, sizeof(AttachParameters
));
463 AttachParameters
.Version
= ATTACH_VIRTUAL_DISK_VERSION_1
;
465 Status
= AttachVirtualDisk(Handle
, NULL
, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY
| ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME
, 0, &AttachParameters
, NULL
);
466 if (Status
!= ERROR_SUCCESS
)
468 Log("Failed to attach virtual disk ErrorCode:%u", Status
);
475 int VentoyMountY(HANDLE Handle
)
480 DWORD physicalDriveNameSize
;
482 WCHAR physicalDriveName
[MAX_PATH
];
483 CHAR physicalDriveNameA
[MAX_PATH
];
484 CHAR cdromDriveName
[MAX_PATH
];
485 ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters
;
489 memset(&AttachParameters
, 0, sizeof(AttachParameters
));
490 AttachParameters
.Version
= ATTACH_VIRTUAL_DISK_VERSION_1
;
492 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
);
493 if (Status
!= ERROR_SUCCESS
)
495 Log("Failed to attach virtual disk ErrorCode:%u", Status
);
499 memset(physicalDriveName
, 0, sizeof(physicalDriveName
));
500 memset(physicalDriveNameA
, 0, sizeof(physicalDriveNameA
));
502 physicalDriveNameSize
= MAX_PATH
;
503 Status
= GetVirtualDiskPhysicalPath(Handle
, &physicalDriveNameSize
, physicalDriveName
);
504 if (Status
!= ERROR_SUCCESS
)
506 Log("Failed GetVirtualDiskPhysicalPath ErrorCode:%u", Status
);
510 for (i
= 0; physicalDriveName
[i
]; i
++)
512 physicalDriveNameA
[i
] = toupper((CHAR
)(physicalDriveName
[i
]));
515 Log("physicalDriveNameA=<%s>", physicalDriveNameA
);
517 Pos
= strstr(physicalDriveNameA
, "CDROM");
520 Log("Not cdrom phy drive");
524 sprintf_s(cdromDriveName
, sizeof(cdromDriveName
), "\\Device\\%s", Pos
);
525 Log("cdromDriveName=<%s>", cdromDriveName
);
527 for (i
= 0; i
< 3 && (bRet
== FALSE
); i
++)
530 bRet
= DefineDosDeviceA(DDD_RAW_TARGET_PATH
, "Y:", cdromDriveName
);
531 Log("DefineDosDeviceA %s", bRet
? "success" : "failed");
537 static BOOL
VentoyNeedMountY(const char *IsoPath
)
543 static int VentoyAttachVirtualDisk(HANDLE Handle
, const char *IsoPath
)
548 Drives
= GetLogicalDrives();
549 if ((1 << 24) & Drives
)
551 Log("Y: is occupied");
556 Log("Y: is free now");
560 if (DriveYFree
&& VentoyNeedMountY(IsoPath
))
562 return VentoyMountY(Handle
);
566 return VentoyMountAnywhere(Handle
);
570 int VentoyMountISOByAPI(const char *IsoPath
)
574 WCHAR wFilePath
[512] = { 0 };
575 VIRTUAL_STORAGE_TYPE StorageType
;
576 OPEN_VIRTUAL_DISK_PARAMETERS OpenParameters
;
578 Log("VentoyMountISOByAPI <%s>", IsoPath
);
580 if (IsUTF8Encode(IsoPath
))
582 MultiByteToWideChar(CP_UTF8
, 0, IsoPath
, (int)strlen(IsoPath
), wFilePath
, (int)(sizeof(wFilePath
) / sizeof(WCHAR
)));
586 MultiByteToWideChar(CP_ACP
, 0, IsoPath
, (int)strlen(IsoPath
), wFilePath
, (int)(sizeof(wFilePath
) / sizeof(WCHAR
)));
589 memset(&StorageType
, 0, sizeof(StorageType
));
590 memset(&OpenParameters
, 0, sizeof(OpenParameters
));
592 OpenParameters
.Version
= OPEN_VIRTUAL_DISK_VERSION_1
;
594 Status
= OpenVirtualDisk(&StorageType
, wFilePath
, VIRTUAL_DISK_ACCESS_READ
, 0, &OpenParameters
, &Handle
);
595 if (Status
!= ERROR_SUCCESS
)
597 if (ERROR_VIRTDISK_PROVIDER_NOT_FOUND
== Status
)
599 Log("VirtualDisk for ISO file is not supported in current system");
603 Log("Failed to open virtual disk ErrorCode:%u", Status
);
608 Log("OpenVirtualDisk success");
610 Status
= VentoyAttachVirtualDisk(Handle
, IsoPath
);
611 if (Status
!= ERROR_SUCCESS
)
613 Log("Failed to attach virtual disk ErrorCode:%u", Status
);
618 Log("VentoyAttachVirtualDisk success");
625 static HANDLE g_FatPhyDrive
;
626 static UINT64 g_Part2StartSec
;
628 static int CopyFileFromFatDisk(const CHAR
* SrcFile
, const CHAR
*DstFile
)
635 Log("CopyFileFromFatDisk (%s)==>(%s)", SrcFile
, DstFile
);
637 flfile
= fl_fopen(SrcFile
, "rb");
640 fl_fseek(flfile
, 0, SEEK_END
);
641 size
= (int)fl_ftell(flfile
);
642 fl_fseek(flfile
, 0, SEEK_SET
);
644 buf
= (char *)malloc(size
);
647 fl_fread(buf
, 1, size
, flfile
);
650 SaveBuffer2File(DstFile
, buf
, size
);
660 static int VentoyFatDiskRead(uint32 Sector
, uint8
*Buffer
, uint32 SectorCount
)
665 LARGE_INTEGER liCurrentPosition
;
667 liCurrentPosition
.QuadPart
= Sector
+ g_Part2StartSec
;
668 liCurrentPosition
.QuadPart
*= 512;
669 SetFilePointerEx(g_FatPhyDrive
, liCurrentPosition
, &liCurrentPosition
, FILE_BEGIN
);
671 ReadSize
= (DWORD
)(SectorCount
* 512);
673 bRet
= ReadFile(g_FatPhyDrive
, Buffer
, ReadSize
, &dwSize
, NULL
);
674 if (bRet
== FALSE
|| dwSize
!= ReadSize
)
676 Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet
, ReadSize
, dwSize
, GetLastError());
682 static CHAR
GetMountLogicalDrive(void)
686 DWORD Mask
= 0x1000000;
688 Drives
= GetLogicalDrives();
689 Log("Drives=0x%x", Drives
);
693 if ((Drives
& Mask
) == 0)
705 UINT64
GetVentoyEfiPartStartSector(HANDLE hDrive
)
710 VTOY_GPT_INFO
*pGpt
= NULL
;
711 UINT64 StartSector
= 0;
713 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
715 bRet
= ReadFile(hDrive
, &MBR
, sizeof(MBR
), &dwSize
, NULL
);
716 Log("Read MBR Ret:%u Size:%u code:%u", bRet
, dwSize
, LASTERR
);
718 if ((!bRet
) || (dwSize
!= sizeof(MBR
)))
723 if (MBR
.PartTbl
[0].FsFlag
== 0xEE)
725 Log("GPT partition style");
727 pGpt
= malloc(sizeof(VTOY_GPT_INFO
));
733 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
734 bRet
= ReadFile(hDrive
, pGpt
, sizeof(VTOY_GPT_INFO
), &dwSize
, NULL
);
735 if ((!bRet
) || (dwSize
!= sizeof(VTOY_GPT_INFO
)))
737 Log("Failed to read gpt info %d %u %d", bRet
, dwSize
, LASTERR
);
741 StartSector
= pGpt
->PartTbl
[1].StartLBA
;
746 Log("MBR partition style");
747 StartSector
= MBR
.PartTbl
[1].StartSectorId
;
750 Log("GetVentoyEfiPart StartSector: %llu", StartSector
);
754 int VentoyMountISOByImdisk(const char *IsoPath
, DWORD PhyDrive
)
761 CHAR PhyPath
[MAX_PATH
];
762 WCHAR PhyPathW
[MAX_PATH
];
764 PROCESS_INFORMATION Pi
;
765 GET_LENGTH_INFORMATION LengthInfo
;
767 Log("VentoyMountISOByImdisk %s", IsoPath
);
769 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\PhysicalDrive%d", PhyDrive
);
770 if (IsUTF8Encode(PhyPath
))
772 Utf8ToUtf16(PhyPath
, PhyPathW
);
773 hDrive
= CreateFileW(PhyPathW
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
777 hDrive
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
780 if (hDrive
== INVALID_HANDLE_VALUE
)
782 Log("Could not open the disk<%s>, error:%u", PhyPath
, GetLastError());
786 bRet
= DeviceIoControl(hDrive
, IOCTL_DISK_GET_LENGTH_INFO
, NULL
, 0, &LengthInfo
, sizeof(LengthInfo
), &dwBytes
, NULL
);
789 Log("Could not get phy disk %s size, error:%u", PhyPath
, GetLastError());
793 g_FatPhyDrive
= hDrive
;
794 g_Part2StartSec
= GetVentoyEfiPartStartSector(hDrive
);
796 Log("Parse FAT fs...");
800 if (0 == fl_attach_media(VentoyFatDiskRead
, NULL
))
804 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.sys", "ventoy\\imdisk.sys");
805 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.exe", "ventoy\\imdisk.exe");
806 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.cpl", "ventoy\\imdisk.cpl");
810 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.sys", "ventoy\\imdisk.sys");
811 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.exe", "ventoy\\imdisk.exe");
812 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.cpl", "ventoy\\imdisk.cpl");
815 GetCurrentDirectoryA(sizeof(PhyPath
), PhyPath
);
816 strcat_s(PhyPath
, sizeof(PhyPath
), "\\ventoy\\imdisk.sys");
818 if (LoadNtDriver(PhyPath
) == 0)
822 Letter
= GetMountLogicalDrive();
823 sprintf_s(PhyPath
, sizeof(PhyPath
), "ventoy\\imdisk.exe -a -o ro -f %s -m %C:", IsoPath
, Letter
);
825 Log("mount iso to %C: use imdisk cmd <%s>", Letter
, PhyPath
);
827 GetStartupInfoA(&Si
);
829 Si
.dwFlags
|= STARTF_USESHOWWINDOW
;
830 Si
.wShowWindow
= SW_HIDE
;
832 CreateProcessA(NULL
, PhyPath
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
833 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
840 SAFE_CLOSE_HANDLE(hDrive
);
845 static int MountIsoFile(CONST CHAR
*IsoPath
, DWORD PhyDrive
)
847 if (IsWindows8OrGreater())
849 Log("This is Windows 8 or latter...");
850 if (VentoyMountISOByAPI(IsoPath
) == 0)
852 Log("Mount iso by API success");
857 Log("Mount iso by API failed, maybe not supported, try imdisk");
858 return VentoyMountISOByImdisk(IsoPath
, PhyDrive
);
863 Log("This is before Windows 8 ...");
864 if (VentoyMountISOByImdisk(IsoPath
, PhyDrive
) == 0)
866 Log("Mount iso by imdisk success");
871 return VentoyMountISOByAPI(IsoPath
);
876 static int GetPhyDriveByLogicalDrive(int DriveLetter
)
881 VOLUME_DISK_EXTENTS DiskExtents
;
884 sprintf_s(PhyPath
, sizeof(PhyPath
), "\\\\.\\%C:", (CHAR
)DriveLetter
);
886 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
887 if (Handle
== INVALID_HANDLE_VALUE
)
889 Log("Could not open the disk<%s>, error:%u", PhyPath
, GetLastError());
893 Ret
= DeviceIoControl(Handle
,
894 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
898 (DWORD
)(sizeof(DiskExtents
)),
902 if (!Ret
|| DiskExtents
.NumberOfDiskExtents
== 0)
904 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath
, GetLastError());
905 SAFE_CLOSE_HANDLE(Handle
);
908 SAFE_CLOSE_HANDLE(Handle
);
910 Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",
912 DiskExtents
.Extents
[0].DiskNumber
,
913 DiskExtents
.Extents
[0].StartingOffset
.QuadPart
,
914 DiskExtents
.Extents
[0].ExtentLength
.QuadPart
917 return (int)DiskExtents
.Extents
[0].DiskNumber
;
921 static int DeleteVentoyPart2MountPoint(DWORD PhyDrive
)
926 CHAR DriveName
[] = "?:\\";
928 Log("DeleteVentoyPart2MountPoint Phy%u ...", PhyDrive
);
930 Drives
= GetLogicalDrives();
933 if ((Drives
& 0x01) && IsFileExist("%C:\\ventoy\\ventoy.cpio", Letter
))
935 Log("File %C:\\ventoy\\ventoy.cpio exist", Letter
);
937 PhyDisk
= GetPhyDriveByLogicalDrive(Letter
);
938 Log("PhyDisk=%u for %C", PhyDisk
, Letter
);
940 if (PhyDisk
== PhyDrive
)
942 DriveName
[0] = Letter
;
943 DeleteVolumeMountPointA(DriveName
);
955 static BOOL
check_tar_archive(const char *archive
, CHAR
*tarName
)
959 const char *pos
= archive
;
960 const char *slash
= archive
;
964 if (*pos
== '\\' || *pos
== '/')
971 len
= (int)strlen(slash
);
973 if (len
> 7 && (strncmp(slash
+ len
- 7, ".tar.gz", 7) == 0 || strncmp(slash
+ len
- 7, ".tar.xz", 7) == 0))
975 nameLen
= (int)sprintf_s(tarName
, MAX_PATH
, "X:%s", slash
);
976 tarName
[nameLen
- 3] = 0;
979 else if (len
> 8 && strncmp(slash
+ len
- 8, ".tar.bz2", 8) == 0)
981 nameLen
= (int)sprintf_s(tarName
, MAX_PATH
, "X:%s", slash
);
982 tarName
[nameLen
- 4] = 0;
985 else if (len
> 9 && strncmp(slash
+ len
- 9, ".tar.lzma", 9) == 0)
987 nameLen
= (int)sprintf_s(tarName
, MAX_PATH
, "X:%s", slash
);
988 tarName
[nameLen
- 5] = 0;
995 static int DecompressInjectionArchive(const char *archive
, DWORD PhyDrive
)
1002 DWORD flags
= CREATE_NO_WINDOW
;
1003 CHAR StrBuf
[MAX_PATH
];
1004 CHAR tarName
[MAX_PATH
];
1006 PROCESS_INFORMATION Pi
;
1007 PROCESS_INFORMATION NewPi
;
1008 GET_LENGTH_INFORMATION LengthInfo
;
1009 SECURITY_ATTRIBUTES Sa
= { sizeof(SECURITY_ATTRIBUTES
), NULL
, TRUE
};
1011 Log("DecompressInjectionArchive %s", archive
);
1013 sprintf_s(StrBuf
, sizeof(StrBuf
), "\\\\.\\PhysicalDrive%d", PhyDrive
);
1014 hDrive
= CreateFileA(StrBuf
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
1015 if (hDrive
== INVALID_HANDLE_VALUE
)
1017 Log("Could not open the disk<%s>, error:%u", StrBuf
, GetLastError());
1021 bRet
= DeviceIoControl(hDrive
, IOCTL_DISK_GET_LENGTH_INFO
, NULL
, 0, &LengthInfo
, sizeof(LengthInfo
), &dwBytes
, NULL
);
1024 Log("Could not get phy disk %s size, error:%u", StrBuf
, GetLastError());
1028 g_FatPhyDrive
= hDrive
;
1029 g_Part2StartSec
= GetVentoyEfiPartStartSector(hDrive
);
1031 Log("Parse FAT fs...");
1035 if (0 == fl_attach_media(VentoyFatDiskRead
, NULL
))
1039 CopyFileFromFatDisk("/ventoy/7z/64/7za.exe", "ventoy\\7za.exe");
1043 CopyFileFromFatDisk("/ventoy/7z/32/7za.exe", "ventoy\\7za.exe");
1046 sprintf_s(StrBuf
, sizeof(StrBuf
), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", archive
);
1048 Log("extract inject to X:");
1049 Log("cmdline:<%s>", StrBuf
);
1051 GetStartupInfoA(&Si
);
1053 hOut
= CreateFileA("ventoy\\7z.log",
1055 FILE_SHARE_WRITE
| FILE_SHARE_READ
,
1058 FILE_ATTRIBUTE_NORMAL
,
1061 Si
.dwFlags
|= STARTF_USESTDHANDLES
;
1063 if (hOut
!= INVALID_HANDLE_VALUE
)
1065 Si
.hStdError
= hOut
;
1066 Si
.hStdOutput
= hOut
;
1069 CreateProcessA(NULL
, StrBuf
, NULL
, NULL
, TRUE
, flags
, NULL
, NULL
, &Si
, &Pi
);
1070 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
1073 // decompress tar archive, for tar.gz/tar.xz/tar.bz2
1075 if (check_tar_archive(archive
, tarName
))
1077 Log("Decompress tar archive...<%s>", tarName
);
1079 sprintf_s(StrBuf
, sizeof(StrBuf
), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", tarName
);
1081 CreateProcessA(NULL
, StrBuf
, NULL
, NULL
, TRUE
, flags
, NULL
, NULL
, &Si
, &NewPi
);
1082 WaitForSingleObject(NewPi
.hProcess
, INFINITE
);
1084 Log("Now delete %s", tarName
);
1085 DeleteFileA(tarName
);
1088 SAFE_CLOSE_HANDLE(hOut
);
1094 SAFE_CLOSE_HANDLE(hDrive
);
1099 static int ProcessUnattendedInstallation(const char *script
)
1105 CHAR CurDir
[MAX_PATH
];
1107 Log("Copy unattended XML ...");
1109 GetCurrentDirectory(sizeof(CurDir
), CurDir
);
1111 if ((Letter
>= 'A' && Letter
<= 'Z') || (Letter
>= 'a' && Letter
<= 'z'))
1113 Log("Current Drive Letter: %C", Letter
);
1120 sprintf_s(CurDir
, sizeof(CurDir
), "%C:\\Autounattend.xml", Letter
);
1121 Log("Copy file <%s> --> <%s>", script
, CurDir
);
1122 CopyFile(script
, CurDir
, FALSE
);
1124 Ret
= RegCreateKeyEx(HKEY_LOCAL_MACHINE
, "System\\Setup", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hKey
, &dw
);
1125 if (ERROR_SUCCESS
== Ret
)
1127 Ret
= RegSetValueEx(hKey
, "UnattendFile", 0, REG_SZ
, CurDir
, (DWORD
)(strlen(CurDir
) + 1));
1133 static int VentoyHook(ventoy_os_param
*param
)
1137 DISK_EXTENT DiskExtent
;
1138 DWORD Drives
= GetLogicalDrives();
1140 CHAR IsoPath
[MAX_PATH
];
1142 Log("Logical Drives=0x%x Path:<%s>", Drives
, param
->vtoy_img_path
);
1144 if (IsUTF8Encode(param
->vtoy_img_path
))
1146 Log("This file is UTF8 encoding\n");
1153 sprintf_s(IsoPath
, sizeof(IsoPath
), "%C:\\%s", Letter
, param
->vtoy_img_path
);
1154 if (IsFileExist("%s", IsoPath
))
1156 Log("File exist under %C:", Letter
);
1157 if (GetPhyDiskUUID(Letter
, UUID
, &DiskExtent
) == 0)
1159 if (memcmp(UUID
, param
->vtoy_disk_guid
, 16) == 0)
1161 Log("Disk UUID match");
1168 Log("File NOT exist under %C:", Letter
);
1178 Log("Failed to find ISO file");
1182 Log("Find ISO file <%s>", IsoPath
);
1184 rc
= MountIsoFile(IsoPath
, DiskExtent
.DiskNumber
);
1185 Log("Mount ISO FILE: %s", rc
== 0 ? "SUCCESS" : "FAILED");
1188 rc
= DeleteVentoyPart2MountPoint(DiskExtent
.DiskNumber
);
1189 Log("Delete ventoy mountpoint: %s", rc
== 0 ? "SUCCESS" : "NO NEED");
1191 if (g_windows_data
.auto_install_script
[0])
1193 sprintf_s(IsoPath
, sizeof(IsoPath
), "%C:%s", Letter
, g_windows_data
.auto_install_script
);
1194 if (IsFileExist("%s", IsoPath
))
1196 Log("use auto install script %s...", IsoPath
);
1197 ProcessUnattendedInstallation(IsoPath
);
1201 Log("auto install script %s not exist", IsoPath
);
1206 Log("auto install no need");
1209 if (g_windows_data
.injection_archive
[0])
1211 sprintf_s(IsoPath
, sizeof(IsoPath
), "%C:%s", Letter
, g_windows_data
.injection_archive
);
1212 if (IsFileExist("%s", IsoPath
))
1214 Log("decompress injection archive %s...", IsoPath
);
1215 DecompressInjectionArchive(IsoPath
, DiskExtent
.DiskNumber
);
1219 Log("injection archive %s not exist", IsoPath
);
1224 Log("no injection archive found");
1230 const char * GetFileNameInPath(const char *fullpath
)
1233 const char *pos
= NULL
;
1235 if (strstr(fullpath
, ":"))
1237 for (i
= (int)strlen(fullpath
); i
> 0; i
--)
1239 if (fullpath
[i
- 1] == '/' || fullpath
[i
- 1] == '\\')
1241 return fullpath
+ i
;
1249 int VentoyJumpWimboot(INT argc
, CHAR
**argv
, CHAR
*LunchFile
)
1257 g_64bit_system
= FALSE
;
1259 g_64bit_system
= TRUE
;
1262 Log("VentoyJumpWimboot %dbit", g_64bit_system
? 64 : 32);
1264 sprintf_s(LunchFile
, MAX_PATH
, "X:\\setup.exe");
1266 ReadWholeFile2Buf("wimboot.data", &buf
, &size
);
1267 Log("wimboot.data size:%d", size
);
1269 memcpy(&g_os_param
, buf
, sizeof(ventoy_os_param
));
1270 memcpy(&g_windows_data
, buf
+ sizeof(ventoy_os_param
), sizeof(ventoy_windows_data
));
1271 memcpy(g_os_param_reserved
, g_os_param
.vtoy_reserved
, sizeof(g_os_param_reserved
));
1273 if (g_os_param_reserved
[0] == 1)
1275 Log("break here for debug .....");
1280 for (Pos
= 0; Pos
< sizeof(g_os_param
.vtoy_img_path
) && g_os_param
.vtoy_img_path
[Pos
]; Pos
++)
1282 if (g_os_param
.vtoy_img_path
[Pos
] == '/')
1284 g_os_param
.vtoy_img_path
[Pos
] = '\\';
1288 if (g_os_param_reserved
[0] == 2)
1290 Log("skip hook for debug .....");
1295 rc
= VentoyHook(&g_os_param
);
1307 int VentoyJump(INT argc
, CHAR
**argv
, CHAR
*LunchFile
)
1313 BYTE
*Buffer
= NULL
;
1314 CHAR ExeFileName
[MAX_PATH
];
1316 sprintf_s(ExeFileName
, sizeof(ExeFileName
), "%s", argv
[0]);
1317 if (!IsFileExist("%s", ExeFileName
))
1319 Log("File %s NOT exist, now try %s.exe", ExeFileName
, ExeFileName
);
1320 sprintf_s(ExeFileName
, sizeof(ExeFileName
), "%s.exe", argv
[0]);
1322 Log("File %s exist ? %s", ExeFileName
, IsFileExist("%s", ExeFileName
) ? "YES" : "NO");
1325 if (ReadWholeFile2Buf(ExeFileName
, (void **)&Buffer
, &FileSize
))
1330 g_64bit_system
= IsPe64(Buffer
);
1331 Log("VentoyJump %dbit", g_64bit_system
? 64 : 32);
1333 if (IsDirExist("ventoy"))
1335 Log("ventoy directory already exist");
1339 Log("ventoy directory not exist, now create it.");
1340 if (!CreateDirectoryA("ventoy", NULL
))
1342 Log("Failed to create ventoy directory err:%u", GetLastError());
1347 for (PeStart
= 0; PeStart
< FileSize
; PeStart
+= 16)
1349 if (CheckOsParam((ventoy_os_param
*)(Buffer
+ PeStart
)) &&
1350 CheckPeHead(Buffer
+ PeStart
+ sizeof(ventoy_os_param
) + sizeof(ventoy_windows_data
)))
1352 Log("Find os pararm at %u", PeStart
);
1354 memcpy(&g_os_param
, Buffer
+ PeStart
, sizeof(ventoy_os_param
));
1355 memcpy(&g_windows_data
, Buffer
+ PeStart
+ sizeof(ventoy_os_param
), sizeof(ventoy_windows_data
));
1356 memcpy(g_os_param_reserved
, g_os_param
.vtoy_reserved
, sizeof(g_os_param_reserved
));
1358 if (g_os_param_reserved
[0] == 1)
1360 Log("break here for debug .....");
1365 for (Pos
= 0; Pos
< sizeof(g_os_param
.vtoy_img_path
) && g_os_param
.vtoy_img_path
[Pos
]; Pos
++)
1367 if (g_os_param
.vtoy_img_path
[Pos
] == '/')
1369 g_os_param
.vtoy_img_path
[Pos
] = '\\';
1373 PeStart
+= sizeof(ventoy_os_param
) + sizeof(ventoy_windows_data
);
1374 sprintf_s(LunchFile
, MAX_PATH
, "ventoy\\%s", GetFileNameInPath(ExeFileName
));
1376 if (IsFileExist("%s", LunchFile
))
1378 Log("vtoyjump multiple call...");
1383 SaveBuffer2File(LunchFile
, Buffer
+ PeStart
, FileSize
- PeStart
);
1388 if (PeStart
>= FileSize
)
1390 Log("OS param not found");
1394 if (g_os_param_reserved
[0] == 2)
1396 Log("skip hook for debug .....");
1401 rc
= VentoyHook(&g_os_param
);
1413 static int GetPecmdParam(const char *argv
, char *CallParamBuf
, DWORD BufLen
)
1420 CHAR CallParam
[256] = { 0 };
1421 CHAR FileName
[MAX_PATH
];
1423 Log("GetPecmdParam <%s>", argv
);
1427 strcpy_s(FileName
, sizeof(FileName
), argv
);
1428 for (dw
= 0, Pos
= FileName
; *Pos
; Pos
++)
1431 *Pos
= toupper(*Pos
);
1434 Log("dw=%lu argv=<%s>", dw
, FileName
);
1436 if (dw
>= 9 && strcmp(FileName
+ dw
- 9, "PECMD.EXE") == 0)
1438 Log("Get parameters for pecmd.exe");
1439 Ret
= RegCreateKeyEx(HKEY_LOCAL_MACHINE
, "System\\Setup", 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hKey
, &dw
);
1440 if (ERROR_SUCCESS
== Ret
)
1442 memset(FileName
, 0, sizeof(FileName
));
1443 dw
= sizeof(FileName
);
1444 Ret
= RegQueryValueEx(hKey
, "CmdLine", NULL
, &Type
, FileName
, &dw
);
1445 if (ERROR_SUCCESS
== Ret
&& Type
== REG_SZ
)
1447 strcpy_s(CallParam
, sizeof(CallParam
), FileName
);
1448 Log("CmdLine:<%s>", CallParam
);
1450 if (_strnicmp(CallParam
, "PECMD.EXE", 9) == 0)
1452 Pos
= CallParam
+ 9;
1453 if (*Pos
== ' ' || *Pos
== '\t')
1463 Log("CmdLine2:<%s>", Pos
);
1464 sprintf_s(CallParamBuf
, BufLen
, " %s", Pos
);
1468 Log("Failed to RegQueryValueEx %lu %lu", Ret
, Type
);
1476 Log("Failed to create reg key %lu", Ret
);
1481 Log("This is NOT pecmd.exe");
1487 static int GetWpeInitParam(char **argv
, int argc
, char *CallParamBuf
, DWORD BufLen
)
1492 CHAR FileName
[MAX_PATH
];
1494 Log("GetWpeInitParam argc=%d", argc
);
1498 strcpy_s(FileName
, sizeof(FileName
), argv
[0]);
1499 for (dw
= 0, Pos
= FileName
; *Pos
; Pos
++)
1502 *Pos
= toupper(*Pos
);
1505 Log("dw=%lu argv=<%s>", dw
, FileName
);
1507 if (dw
>= 11 && strcmp(FileName
+ dw
- 11, "WPEINIT.EXE") == 0)
1509 Log("Get parameters for WPEINIT.EXE");
1510 for (i
= 1; i
< argc
; i
++)
1512 strcat_s(CallParamBuf
, BufLen
, " ");
1513 strcat_s(CallParamBuf
, BufLen
, argv
[i
]);
1520 Log("This is NOT wpeinit.exe");
1527 int main(int argc
, char **argv
)
1532 CHAR CurDir
[MAX_PATH
];
1533 CHAR LunchFile
[MAX_PATH
];
1534 CHAR CallParam
[1024] = { 0 };
1536 PROCESS_INFORMATION Pi
;
1538 if (argv
[0] && argv
[0][0] && argv
[0][1] == ':')
1540 GetCurrentDirectoryA(sizeof(CurDir
), CurDir
);
1542 strcpy_s(LunchFile
, sizeof(LunchFile
), argv
[0]);
1543 Pos
= (char *)GetFileNameInPath(LunchFile
);
1545 strcat_s(CurDir
, sizeof(CurDir
), "\\");
1546 strcat_s(CurDir
, sizeof(CurDir
), Pos
);
1548 if (_stricmp(argv
[0], CurDir
) != 0)
1551 SetCurrentDirectoryA(LunchFile
);
1555 Log("######## VentoyJump ##########");
1556 Log("argc = %d argv[0] = <%s>", argc
, argv
[0]);
1558 if (Pos
&& *Pos
== 0)
1560 Log("Old current directory = <%s>", CurDir
);
1561 Log("New current directory = <%s>", LunchFile
);
1565 GetCurrentDirectoryA(sizeof(CurDir
), CurDir
);
1566 Log("Current directory = <%s>", CurDir
);
1569 if (0 == GetWpeInitParam(argv
, argc
, CallParam
, sizeof(CallParam
)))
1571 GetPecmdParam(argv
[0], CallParam
, sizeof(CallParam
));
1574 GetStartupInfoA(&Si
);
1576 memset(LunchFile
, 0, sizeof(LunchFile
));
1578 if (strstr(argv
[0], "vtoyjump.exe"))
1580 rc
= VentoyJumpWimboot(argc
, argv
, LunchFile
);
1584 rc
= VentoyJump(argc
, argv
, LunchFile
);
1587 Log("LunchFile=<%s> CallParam=<%s>", LunchFile
, CallParam
);
1589 if (g_os_param_reserved
[0] == 3)
1591 Log("Open log for debug ...");
1592 sprintf_s(LunchFile
, sizeof(LunchFile
), "%s", "notepad.exe ventoy.log");
1598 strcat_s(LunchFile
, sizeof(LunchFile
), CallParam
);
1600 else if (NULL
== strstr(LunchFile
, "setup.exe"))
1602 Log("Not setup.exe, hide windows.");
1603 Si
.dwFlags
|= STARTF_USESHOWWINDOW
;
1604 Si
.wShowWindow
= SW_HIDE
;
1607 Log("Ventoy jump %s ...", rc
== 0 ? "success" : "failed");
1610 Log("Now launch <%s> ...", LunchFile
);
1612 //sprintf_s(LunchFile, sizeof(LunchFile), "%s", "cmd.exe");
1613 CreateProcessA(NULL
, LunchFile
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
1615 for (i
= 0; rc
&& i
< 10; i
++)
1617 Log("Ventoy hook failed, now wait and retry ...");
1619 rc
= VentoyHook(&g_os_param
);
1622 Log("Wait process...");
1623 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
1625 Log("vtoyjump finished");