-/******************************************************************************
-* vtoyjump.c
-*
-* Copyright (c) 2020, longpanda <admin@ventoy.net>
-*
-* This program is free software; you can redistribute it and/or
-* modify it under the terms of the GNU General Public License as
-* published by the Free Software Foundation; either version 3 of the
-* License, or (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful, but
-* WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-* General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, see <http://www.gnu.org/licenses/>.
-*
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <Windows.h>
-#include <virtdisk.h>
-#include <winioctl.h>
-#include <VersionHelpers.h>
-#include "vtoyjump.h"
-#include "fat_filelib.h"
-
-static ventoy_os_param g_os_param;
-static ventoy_windows_data g_windows_data;
-static UINT8 g_os_param_reserved[32];
-static BOOL g_64bit_system = FALSE;
-static ventoy_guid g_ventoy_guid = VENTOY_GUID;
-
-void Log(const char *Fmt, ...)
-{
- va_list Arg;
- int Len = 0;
- FILE *File = NULL;
- SYSTEMTIME Sys;
- char szBuf[1024];
-
- GetLocalTime(&Sys);
- Len += sprintf_s(szBuf, sizeof(szBuf),
- "[%4d/%02d/%02d %02d:%02d:%02d.%03d] ",
- Sys.wYear, Sys.wMonth, Sys.wDay,
- Sys.wHour, Sys.wMinute, Sys.wSecond,
- Sys.wMilliseconds);
-
- va_start(Arg, Fmt);
- Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len, sizeof(szBuf)-Len, Fmt, Arg);
- va_end(Arg);
-
- fopen_s(&File, "ventoy.log", "a+");
- if (File)
- {
- fwrite(szBuf, 1, Len, File);
- fwrite("\n", 1, 1, File);
- fclose(File);
- }
-}
-
-
-static int LoadNtDriver(const char *DrvBinPath)
-{
- int i;
- int rc = 0;
- BOOL Ret;
- DWORD Status;
- SC_HANDLE hServiceMgr;
- SC_HANDLE hService;
- char name[256] = { 0 };
-
- for (i = (int)strlen(DrvBinPath) - 1; i >= 0; i--)
- {
- if (DrvBinPath[i] == '\\' || DrvBinPath[i] == '/')
- {
- sprintf_s(name, sizeof(name), "%s", DrvBinPath + i + 1);
- break;
- }
- }
-
- Log("Load NT driver: %s %s", DrvBinPath, name);
-
- hServiceMgr = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
- if (hServiceMgr == NULL)
- {
- Log("OpenSCManager failed Error:%u", GetLastError());
- return 1;
- }
-
- Log("OpenSCManager OK");
-
- hService = CreateServiceA(hServiceMgr,
- name,
- name,
- SERVICE_ALL_ACCESS,
- SERVICE_KERNEL_DRIVER,
- SERVICE_DEMAND_START,
- SERVICE_ERROR_NORMAL,
- DrvBinPath,
- NULL, NULL, NULL, NULL, NULL);
- if (hService == NULL)
- {
- Status = GetLastError();
- if (Status != ERROR_IO_PENDING && Status != ERROR_SERVICE_EXISTS)
- {
- Log("CreateService failed v %u", Status);
- CloseServiceHandle(hServiceMgr);
- return 1;
- }
-
- hService = OpenServiceA(hServiceMgr, name, SERVICE_ALL_ACCESS);
- if (hService == NULL)
- {
- Log("OpenService failed %u", Status);
- CloseServiceHandle(hServiceMgr);
- return 1;
- }
- }
-
- Log("CreateService imdisk OK");
-
- Ret = StartServiceA(hService, 0, NULL);
- if (Ret)
- {
- Log("StartService OK");
- }
- else
- {
- Status = GetLastError();
- if (Status == ERROR_SERVICE_ALREADY_RUNNING)
- {
- rc = 0;
- }
- else
- {
- Log("StartService error %u", Status);
- rc = 1;
- }
- }
-
- CloseServiceHandle(hService);
- CloseServiceHandle(hServiceMgr);
-
- Log("Load NT driver %s", rc ? "failed" : "success");
-
- return rc;
-}
-
-static int ReadWholeFile2Buf(const char *Fullpath, void **Data, DWORD *Size)
-{
- int rc = 1;
- DWORD FileSize;
- DWORD dwSize;
- HANDLE Handle;
- BYTE *Buffer = NULL;
-
- Log("ReadWholeFile2Buf <%s>", Fullpath);
-
- Handle = CreateFileA(Fullpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
- if (Handle == INVALID_HANDLE_VALUE)
- {
- Log("Could not open the file<%s>, error:%u", Fullpath, GetLastError());
- goto End;
- }
-
- FileSize = SetFilePointer(Handle, 0, NULL, FILE_END);
-
- Buffer = malloc(FileSize);
- if (!Buffer)
- {
- Log("Failed to alloc memory size:%u", FileSize);
- goto End;
- }
-
- SetFilePointer(Handle, 0, NULL, FILE_BEGIN);
- if (!ReadFile(Handle, Buffer, FileSize, &dwSize, NULL))
- {
- Log("ReadFile failed, dwSize:%u error:%u", dwSize, GetLastError());
- goto End;
- }
-
- *Data = Buffer;
- *Size = FileSize;
-
- Log("Success read file size:%u", FileSize);
-
- rc = 0;
-
-End:
- SAFE_CLOSE_HANDLE(Handle);
-
- return rc;
-}
-
-static BOOL CheckPeHead(BYTE *Head)
-{
- UINT32 PeOffset;
-
- if (Head[0] != 'M' || Head[1] != 'Z')
- {
- return FALSE;
- }
-
- PeOffset = *(UINT32 *)(Head + 60);
- if (*(UINT32 *)(Head + PeOffset) != 0x00004550)
- {
- return FALSE;
- }
-
- return TRUE;
-}
-
-static BOOL IsPe64(BYTE *buffer)
-{
- DWORD pe_off;
-
- if (!CheckPeHead(buffer))
- {
- return FALSE;
- }
-
- pe_off = *(UINT32 *)(buffer + 60);
- if (*(UINT16 *)(buffer + pe_off + 24) == 0x020b)
- {
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-static BOOL CheckOsParam(ventoy_os_param *param)
-{
- UINT32 i;
- BYTE Sum = 0;
-
- if (memcmp(¶m->guid, &g_ventoy_guid, sizeof(ventoy_guid)))
- {
- return FALSE;
- }
-
- for (i = 0; i < sizeof(ventoy_os_param); i++)
- {
- Sum += *((BYTE *)param + i);
- }
-
- if (Sum)
- {
- return FALSE;
- }
-
- if (param->vtoy_img_location_addr % 4096)
- {
- return FALSE;
- }
-
- return TRUE;
-}
-
-static int SaveBuffer2File(const char *Fullpath, void *Buffer, DWORD Length)
-{
- int rc = 1;
- DWORD dwSize;
- HANDLE Handle;
-
- Log("SaveBuffer2File <%s> len:%u", Fullpath, Length);
-
- Handle = CreateFileA(Fullpath, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, 0, 0);
- if (Handle == INVALID_HANDLE_VALUE)
- {
- Log("Could not create new file, error:%u", GetLastError());
- goto End;
- }
-
- WriteFile(Handle, Buffer, Length, &dwSize, NULL);
-
- rc = 0;
-
-End:
- SAFE_CLOSE_HANDLE(Handle);
-
- return rc;
-}
-
-static BOOL IsPathExist(BOOL Dir, const char *Fmt, ...)
-{
- va_list Arg;
- HANDLE hFile;
- DWORD Attr;
- CHAR FilePath[MAX_PATH];
-
- va_start(Arg, Fmt);
- vsnprintf_s(FilePath, sizeof(FilePath), sizeof(FilePath), Fmt, Arg);
- va_end(Arg);
-
- hFile = CreateFileA(FilePath, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
- if (INVALID_HANDLE_VALUE == hFile)
- {
- return FALSE;
- }
-
- CloseHandle(hFile);
-
- Attr = GetFileAttributesA(FilePath);
-
- if (Dir)
- {
- if ((Attr & FILE_ATTRIBUTE_DIRECTORY) == 0)
- {
- return FALSE;
- }
- }
- else
- {
- if (Attr & FILE_ATTRIBUTE_DIRECTORY)
- {
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-static int GetPhyDiskUUID(const char LogicalDrive, UINT8 *UUID, DISK_EXTENT *DiskExtent)
-{
- BOOL Ret;
- DWORD dwSize;
- HANDLE Handle;
- VOLUME_DISK_EXTENTS DiskExtents;
- CHAR PhyPath[128];
- UINT8 SectorBuf[512];
-
- Log("GetPhyDiskUUID %C", LogicalDrive);
-
- sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\%C:", LogicalDrive);
- Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
- if (Handle == INVALID_HANDLE_VALUE)
- {
- Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
- return 1;
- }
-
- Ret = DeviceIoControl(Handle,
- IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
- NULL,
- 0,
- &DiskExtents,
- (DWORD)(sizeof(DiskExtents)),
- (LPDWORD)&dwSize,
- NULL);
- if (!Ret || DiskExtents.NumberOfDiskExtents == 0)
- {
- Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed, error:%u", GetLastError());
- CloseHandle(Handle);
- return 1;
- }
- CloseHandle(Handle);
-
- memcpy(DiskExtent, DiskExtents.Extents, sizeof(DiskExtent));
- Log("%C: is in PhysicalDrive%d ", LogicalDrive, DiskExtents.Extents[0].DiskNumber);
-
- sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", DiskExtents.Extents[0].DiskNumber);
- Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
- if (Handle == INVALID_HANDLE_VALUE)
- {
- Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
- return 1;
- }
-
- if (!ReadFile(Handle, SectorBuf, sizeof(SectorBuf), &dwSize, NULL))
- {
- Log("ReadFile failed, dwSize:%u error:%u", dwSize, GetLastError());
- CloseHandle(Handle);
- return 1;
- }
-
- memcpy(UUID, SectorBuf + 0x180, 16);
- CloseHandle(Handle);
- return 0;
-}
-
-int VentoyMountISOByAPI(const char *IsoPath)
-{
- HANDLE Handle;
- DWORD Status;
- WCHAR wFilePath[512] = { 0 };
- VIRTUAL_STORAGE_TYPE StorageType;
- OPEN_VIRTUAL_DISK_PARAMETERS OpenParameters;
- ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters;
-
- Log("VentoyMountISOByAPI <%s>", IsoPath);
-
- MultiByteToWideChar(CP_ACP, 0, IsoPath, (int)strlen(IsoPath), wFilePath, (int)(sizeof(wFilePath) / sizeof(WCHAR)));
-
- memset(&StorageType, 0, sizeof(StorageType));
- memset(&OpenParameters, 0, sizeof(OpenParameters));
- memset(&AttachParameters, 0, sizeof(AttachParameters));
-
- OpenParameters.Version = OPEN_VIRTUAL_DISK_VERSION_1;
- AttachParameters.Version = ATTACH_VIRTUAL_DISK_VERSION_1;
-
- Status = OpenVirtualDisk(&StorageType, wFilePath, VIRTUAL_DISK_ACCESS_READ, 0, &OpenParameters, &Handle);
- if (Status != ERROR_SUCCESS)
- {
- if (ERROR_VIRTDISK_PROVIDER_NOT_FOUND == Status)
- {
- Log("VirtualDisk for ISO file is not supported in current system");
- }
- else
- {
- Log("Failed to open virtual disk ErrorCode:%u", Status);
- }
- return 1;
- }
-
- Log("OpenVirtualDisk success");
-
- Status = AttachVirtualDisk(Handle, NULL, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY | ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME, 0, &AttachParameters, NULL);
- if (Status != ERROR_SUCCESS)
- {
- Log("Failed to attach virtual disk ErrorCode:%u", Status);
- CloseHandle(Handle);
- return 1;
- }
-
- CloseHandle(Handle);
- return 0;
-}
-
-
-static HANDLE g_FatPhyDrive;
-static UINT64 g_Part2StartSec;
-
-static int CopyFileFromFatDisk(const CHAR* SrcFile, const CHAR *DstFile)
-{
- int rc = 1;
- int size = 0;
- char *buf = NULL;
- void *flfile = NULL;
-
- Log("CopyFileFromFatDisk (%s)==>(%s)", SrcFile, DstFile);
-
- flfile = fl_fopen(SrcFile, "rb");
- if (flfile)
- {
- fl_fseek(flfile, 0, SEEK_END);
- size = (int)fl_ftell(flfile);
- fl_fseek(flfile, 0, SEEK_SET);
-
- buf = (char *)malloc(size);
- if (buf)
- {
- fl_fread(buf, 1, size, flfile);
-
- rc = 0;
- SaveBuffer2File(DstFile, buf, size);
- free(buf);
- }
-
- fl_fclose(flfile);
- }
-
- return rc;
-}
-
-static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
-{
- DWORD dwSize;
- BOOL bRet;
- DWORD ReadSize;
- LARGE_INTEGER liCurrentPosition;
-
- liCurrentPosition.QuadPart = Sector + g_Part2StartSec;
- liCurrentPosition.QuadPart *= 512;
- SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
-
- ReadSize = (DWORD)(SectorCount * 512);
-
- bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL);
- if (bRet == FALSE || dwSize != ReadSize)
- {
- Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet, ReadSize, dwSize, GetLastError());
- }
-
- return 1;
-}
-
-static CHAR GetMountLogicalDrive(void)
-{
- CHAR Letter = 'Y';
- DWORD Drives;
- DWORD Mask = 0x1000000;
-
- Drives = GetLogicalDrives();
- Log("Drives=0x%x", Drives);
-
- while (Mask)
- {
- if ((Drives & Mask) == 0)
- {
- break;
- }
-
- Letter--;
- Mask >>= 1;
- }
-
- return Letter;
-}
-
-UINT64 GetVentoyEfiPartStartSector(HANDLE hDrive)
-{
- BOOL bRet;
- DWORD dwSize;
- MBR_HEAD MBR;
- VTOY_GPT_INFO *pGpt = NULL;
- UINT64 StartSector = 0;
-
- SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
-
- bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);
- Log("Read MBR Ret:%u Size:%u code:%u", bRet, dwSize, LASTERR);
-
- if ((!bRet) || (dwSize != sizeof(MBR)))
- {
- 0;
- }
-
- if (MBR.PartTbl[0].FsFlag == 0xEE)
- {
- Log("GPT partition style");
-
- pGpt = malloc(sizeof(VTOY_GPT_INFO));
- if (!pGpt)
- {
- return 0;
- }
-
- SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
- bRet = ReadFile(hDrive, pGpt, sizeof(VTOY_GPT_INFO), &dwSize, NULL);
- if ((!bRet) || (dwSize != sizeof(VTOY_GPT_INFO)))
- {
- Log("Failed to read gpt info %d %u %d", bRet, dwSize, LASTERR);
- return 0;
- }
-
- StartSector = pGpt->PartTbl[1].StartLBA;
- free(pGpt);
- }
- else
- {
- Log("MBR partition style");
- StartSector = MBR.PartTbl[1].StartSectorId;
- }
-
- Log("GetVentoyEfiPart StartSector: %llu", StartSector);
- return StartSector;
-}
-
-int VentoyMountISOByImdisk(const char *IsoPath, DWORD PhyDrive)
-{
- int rc = 1;
- BOOL bRet;
- CHAR Letter;
- DWORD dwBytes;
- HANDLE hDrive;
- CHAR PhyPath[MAX_PATH];
- STARTUPINFOA Si;
- PROCESS_INFORMATION Pi;
- GET_LENGTH_INFORMATION LengthInfo;
-
- Log("VentoyMountISOByImdisk %s", IsoPath);
-
- sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", PhyDrive);
- hDrive = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
- if (hDrive == INVALID_HANDLE_VALUE)
- {
- Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
- goto End;
- }
-
- bRet = DeviceIoControl(hDrive, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &LengthInfo, sizeof(LengthInfo), &dwBytes, NULL);
- if (!bRet)
- {
- Log("Could not get phy disk %s size, error:%u", PhyPath, GetLastError());
- goto End;
- }
-
- g_FatPhyDrive = hDrive;
- g_Part2StartSec = GetVentoyEfiPartStartSector(hDrive);
-
- Log("Parse FAT fs...");
-
- fl_init();
-
- if (0 == fl_attach_media(VentoyFatDiskRead, NULL))
- {
- if (g_64bit_system)
- {
- CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.sys", "ventoy\\imdisk.sys");
- CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.exe", "ventoy\\imdisk.exe");
- CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.cpl", "ventoy\\imdisk.cpl");
- }
- else
- {
- CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.sys", "ventoy\\imdisk.sys");
- CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.exe", "ventoy\\imdisk.exe");
- CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.cpl", "ventoy\\imdisk.cpl");
- }
-
- GetCurrentDirectoryA(sizeof(PhyPath), PhyPath);
- strcat_s(PhyPath, sizeof(PhyPath), "\\ventoy\\imdisk.sys");
-
- if (LoadNtDriver(PhyPath) == 0)
- {
- rc = 0;
-
- Letter = GetMountLogicalDrive();
- sprintf_s(PhyPath, sizeof(PhyPath), "ventoy\\imdisk.exe -a -o ro -f %s -m %C:", IsoPath, Letter);
-
- Log("mount iso to %C: use imdisk cmd <%s>", Letter, PhyPath);
-
- GetStartupInfoA(&Si);
-
- Si.dwFlags |= STARTF_USESHOWWINDOW;
- Si.wShowWindow = SW_HIDE;
-
- CreateProcessA(NULL, PhyPath, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
- WaitForSingleObject(Pi.hProcess, INFINITE);
- }
- }
- fl_shutdown();
-
-End:
-
- SAFE_CLOSE_HANDLE(hDrive);
-
- return rc;
-}
-
-static int MountIsoFile(CONST CHAR *IsoPath, DWORD PhyDrive)
-{
- if (IsWindows8OrGreater())
- {
- Log("This is Windows 8 or latter...");
- if (VentoyMountISOByAPI(IsoPath) == 0)
- {
- Log("Mount iso by API success");
- return 0;
- }
- else
- {
- Log("Mount iso by API failed, maybe not supported, try imdisk");
- return VentoyMountISOByImdisk(IsoPath, PhyDrive);
- }
- }
- else
- {
- Log("This is before Windows 8 ...");
- if (VentoyMountISOByImdisk(IsoPath, PhyDrive) == 0)
- {
- Log("Mount iso by imdisk success");
- return 0;
- }
- else
- {
- return VentoyMountISOByAPI(IsoPath);
- }
- }
-}
-
-static int GetPhyDriveByLogicalDrive(int DriveLetter)
-{
- BOOL Ret;
- DWORD dwSize;
- HANDLE Handle;
- VOLUME_DISK_EXTENTS DiskExtents;
- CHAR PhyPath[128];
-
- sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\%C:", (CHAR)DriveLetter);
-
- Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
- if (Handle == INVALID_HANDLE_VALUE)
- {
- Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
- return -1;
- }
-
- Ret = DeviceIoControl(Handle,
- IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
- NULL,
- 0,
- &DiskExtents,
- (DWORD)(sizeof(DiskExtents)),
- (LPDWORD)&dwSize,
- NULL);
-
- if (!Ret || DiskExtents.NumberOfDiskExtents == 0)
- {
- Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath, GetLastError());
- SAFE_CLOSE_HANDLE(Handle);
- return -1;
- }
- SAFE_CLOSE_HANDLE(Handle);
-
- Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",
- PhyPath,
- DiskExtents.Extents[0].DiskNumber,
- DiskExtents.Extents[0].StartingOffset.QuadPart,
- DiskExtents.Extents[0].ExtentLength.QuadPart
- );
-
- return (int)DiskExtents.Extents[0].DiskNumber;
-}
-
-
-static int DeleteVentoyPart2MountPoint(DWORD PhyDrive)
-{
- CHAR Letter = 'A';
- DWORD Drives;
- DWORD PhyDisk;
- CHAR DriveName[] = "?:\\";
-
- Log("DeleteVentoyPart2MountPoint Phy%u ...", PhyDrive);
-
- Drives = GetLogicalDrives();
- while (Drives)
- {
- if ((Drives & 0x01) && IsPathExist(FALSE, "%C:\\ventoy\\ventoy.cpio", Letter))
- {
- Log("File %C:\\ventoy\\ventoy.cpio exist", Letter);
-
- PhyDisk = GetPhyDriveByLogicalDrive(Letter);
- Log("PhyDisk=%u for %C", PhyDisk, Letter);
-
- if (PhyDisk == PhyDrive)
- {
- DriveName[0] = Letter;
- DeleteVolumeMountPointA(DriveName);
- return 0;
- }
- }
-
- Letter++;
- Drives >>= 1;
- }
-
- return 1;
-}
-
-static BOOL check_tar_archive(const char *archive, CHAR *tarName)
-{
- int len;
- int nameLen;
- const char *pos = archive;
- const char *slash = archive;
-
- while (*pos)
- {
- if (*pos == '\\' || *pos == '/')
- {
- slash = pos;
- }
- pos++;
- }
-
- len = (int)strlen(slash);
-
- if (len > 7 && (strncmp(slash + len - 7, ".tar.gz", 7) == 0 || strncmp(slash + len - 7, ".tar.xz", 7) == 0))
- {
- nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);
- tarName[nameLen - 3] = 0;
- return TRUE;
- }
- else if (len > 8 && strncmp(slash + len - 8, ".tar.bz2", 8) == 0)
- {
- nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);
- tarName[nameLen - 4] = 0;
- return TRUE;
- }
- else if (len > 9 && strncmp(slash + len - 9, ".tar.lzma", 9) == 0)
- {
- nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);
- tarName[nameLen - 5] = 0;
- return TRUE;
- }
-
- return FALSE;
-}
-
-static int DecompressInjectionArchive(const char *archive, DWORD PhyDrive)
-{
- int rc = 1;
- BOOL bRet;
- DWORD dwBytes;
- HANDLE hDrive;
- HANDLE hOut;
- DWORD flags = CREATE_NO_WINDOW;
- CHAR StrBuf[MAX_PATH];
- CHAR tarName[MAX_PATH];
- STARTUPINFOA Si;
- PROCESS_INFORMATION Pi;
- PROCESS_INFORMATION NewPi;
- GET_LENGTH_INFORMATION LengthInfo;
- SECURITY_ATTRIBUTES Sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
-
- Log("DecompressInjectionArchive %s", archive);
-
- sprintf_s(StrBuf, sizeof(StrBuf), "\\\\.\\PhysicalDrive%d", PhyDrive);
- hDrive = CreateFileA(StrBuf, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
- if (hDrive == INVALID_HANDLE_VALUE)
- {
- Log("Could not open the disk<%s>, error:%u", StrBuf, GetLastError());
- goto End;
- }
-
- bRet = DeviceIoControl(hDrive, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &LengthInfo, sizeof(LengthInfo), &dwBytes, NULL);
- if (!bRet)
- {
- Log("Could not get phy disk %s size, error:%u", StrBuf, GetLastError());
- goto End;
- }
-
- g_FatPhyDrive = hDrive;
- g_Part2StartSec = GetVentoyEfiPartStartSector(hDrive);
-
- Log("Parse FAT fs...");
-
- fl_init();
-
- if (0 == fl_attach_media(VentoyFatDiskRead, NULL))
- {
- if (g_64bit_system)
- {
- CopyFileFromFatDisk("/ventoy/7z/64/7za.exe", "ventoy\\7za.exe");
- }
- else
- {
- CopyFileFromFatDisk("/ventoy/7z/32/7za.exe", "ventoy\\7za.exe");
- }
-
- sprintf_s(StrBuf, sizeof(StrBuf), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", archive);
-
- Log("extract inject to X:");
- Log("cmdline:<%s>", StrBuf);
-
- GetStartupInfoA(&Si);
-
- hOut = CreateFileA("ventoy\\7z.log",
- FILE_APPEND_DATA,
- FILE_SHARE_WRITE | FILE_SHARE_READ,
- &Sa,
- OPEN_ALWAYS,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
-
- Si.dwFlags |= STARTF_USESTDHANDLES;
-
- if (hOut != INVALID_HANDLE_VALUE)
- {
- Si.hStdError = hOut;
- Si.hStdOutput = hOut;
- }
-
- CreateProcessA(NULL, StrBuf, NULL, NULL, TRUE, flags, NULL, NULL, &Si, &Pi);
- WaitForSingleObject(Pi.hProcess, INFINITE);
-
- //
- // decompress tar archive, for tar.gz/tar.xz/tar.bz2
- //
- if (check_tar_archive(archive, tarName))
- {
- Log("Decompress tar archive...<%s>", tarName);
-
- sprintf_s(StrBuf, sizeof(StrBuf), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", tarName);
-
- CreateProcessA(NULL, StrBuf, NULL, NULL, TRUE, flags, NULL, NULL, &Si, &NewPi);
- WaitForSingleObject(NewPi.hProcess, INFINITE);
-
- Log("Now delete %s", tarName);
- DeleteFileA(tarName);
- }
-
- SAFE_CLOSE_HANDLE(hOut);
- }
- fl_shutdown();
-
-End:
-
- SAFE_CLOSE_HANDLE(hDrive);
-
- return rc;
-}
-
-static int ProcessUnattendedInstallation(const char *script)
-{
- DWORD dw;
- HKEY hKey;
- LSTATUS Ret;
- CHAR Letter;
- CHAR CurDir[MAX_PATH];
-
- Log("Copy unattended XML ...");
-
- GetCurrentDirectory(sizeof(CurDir), CurDir);
- Letter = CurDir[0];
- if ((Letter >= 'A' && Letter <= 'Z') || (Letter >= 'a' && Letter <= 'z'))
- {
- Log("Current Drive Letter: %C", Letter);
- }
- else
- {
- Letter = 'X';
- }
-
- sprintf_s(CurDir, sizeof(CurDir), "%C:\\Autounattend.xml", Letter);
- Log("Copy file <%s> --> <%s>", script, CurDir);
- CopyFile(script, CurDir, FALSE);
-
- Ret = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "System\\Setup", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dw);
- if (ERROR_SUCCESS == Ret)
- {
- Ret = RegSetValueEx(hKey, "UnattendFile", 0, REG_SZ, CurDir, (DWORD)(strlen(CurDir) + 1));
- }
-
- return 0;
-}
-
-static int VentoyHook(ventoy_os_param *param)
-{
- int rc;
- CHAR Letter = 'A';
- DISK_EXTENT DiskExtent;
- DWORD Drives = GetLogicalDrives();
- UINT8 UUID[16];
- CHAR IsoPath[MAX_PATH];
-
- Log("Logical Drives=0x%x Path:<%s>", Drives, param->vtoy_img_path);
-
- while (Drives)
- {
- if (Drives & 0x01)
- {
- sprintf_s(IsoPath, sizeof(IsoPath), "%C:\\%s", Letter, param->vtoy_img_path);
- if (IsPathExist(FALSE, "%s", IsoPath))
- {
- Log("File exist under %C:", Letter);
- if (GetPhyDiskUUID(Letter, UUID, &DiskExtent) == 0)
- {
- if (memcmp(UUID, param->vtoy_disk_guid, 16) == 0)
- {
- Log("Disk UUID match");
- break;
- }
- }
- }
- else
- {
- Log("File NOT exist under %C:", Letter);
- }
- }
-
- Drives >>= 1;
- Letter++;
- }
-
- if (Drives == 0)
- {
- Log("Failed to find ISO file");
- return 1;
- }
-
- Log("Find ISO file <%s>", IsoPath);
-
- rc = MountIsoFile(IsoPath, DiskExtent.DiskNumber);
- Log("Mount ISO FILE: %s", rc == 0 ? "SUCCESS" : "FAILED");
-
- // for protect
- rc = DeleteVentoyPart2MountPoint(DiskExtent.DiskNumber);
- Log("Delete ventoy mountpoint: %s", rc == 0 ? "SUCCESS" : "NO NEED");
-
- if (g_windows_data.auto_install_script[0])
- {
- sprintf_s(IsoPath, sizeof(IsoPath), "%C:%s", Letter, g_windows_data.auto_install_script);
- if (IsPathExist(FALSE, "%s", IsoPath))
- {
- Log("use auto install script %s...", IsoPath);
- ProcessUnattendedInstallation(IsoPath);
- }
- else
- {
- Log("auto install script %s not exist", IsoPath);
- }
- }
- else
- {
- Log("auto install no need");
- }
-
- if (g_windows_data.injection_archive[0])
- {
- sprintf_s(IsoPath, sizeof(IsoPath), "%C:%s", Letter, g_windows_data.injection_archive);
- if (IsPathExist(FALSE, "%s", IsoPath))
- {
- Log("decompress injection archive %s...", IsoPath);
- DecompressInjectionArchive(IsoPath, DiskExtent.DiskNumber);
- }
- else
- {
- Log("injection archive %s not exist", IsoPath);
- }
- }
- else
- {
- Log("no injection archive found");
- }
-
- return 0;
-}
-
-const char * GetFileNameInPath(const char *fullpath)
-{
- int i;
- const char *pos = NULL;
-
- if (strstr(fullpath, ":"))
- {
- for (i = (int)strlen(fullpath); i > 0; i--)
- {
- if (fullpath[i - 1] == '/' || fullpath[i - 1] == '\\')
- {
- return fullpath + i;
- }
- }
- }
-
- return fullpath;
-}
-
-int VentoyJump(INT argc, CHAR **argv, CHAR *LunchFile)
-{
- int rc = 1;
- DWORD Pos;
- DWORD PeStart;
- DWORD FileSize;
- BYTE *Buffer = NULL;
- CHAR ExeFileName[MAX_PATH];
-
- sprintf_s(ExeFileName, sizeof(ExeFileName), "%s", argv[0]);
- if (!IsPathExist(FALSE, "%s", ExeFileName))
- {
- Log("File %s NOT exist, now try %s.exe", ExeFileName, ExeFileName);
- sprintf_s(ExeFileName, sizeof(ExeFileName), "%s.exe", argv[0]);
-
- Log("File %s exist ? %s", ExeFileName, IsPathExist(FALSE, "%s", ExeFileName) ? "YES" : "NO");
- }
-
- if (ReadWholeFile2Buf(ExeFileName, (void **)&Buffer, &FileSize))
- {
- goto End;
- }
-
- g_64bit_system = IsPe64(Buffer);
-
- if (!IsPathExist(TRUE, "ventoy"))
- {
- if (!CreateDirectoryA("ventoy", NULL))
- {
- Log("Failed to create ventoy directory err:%u", GetLastError());
- goto End;
- }
- }
-
- for (PeStart = 0; PeStart < FileSize; PeStart += 16)
- {
- if (CheckOsParam((ventoy_os_param *)(Buffer + PeStart)) &&
- CheckPeHead(Buffer + PeStart + sizeof(ventoy_os_param) + sizeof(ventoy_windows_data)))
- {
- Log("Find os pararm at %u", PeStart);
-
- memcpy(&g_os_param, Buffer + PeStart, sizeof(ventoy_os_param));
- memcpy(&g_windows_data, Buffer + PeStart + sizeof(ventoy_os_param), sizeof(ventoy_windows_data));
- memcpy(g_os_param_reserved, g_os_param.vtoy_reserved, sizeof(g_os_param_reserved));
-
- if (g_os_param_reserved[0] == 1)
- {
- Log("break here for debug .....");
- goto End;
- }
-
- // convert / to \\
- for (Pos = 0; Pos < sizeof(g_os_param.vtoy_img_path) && g_os_param.vtoy_img_path[Pos]; Pos++)
- {
- if (g_os_param.vtoy_img_path[Pos] == '/')
- {
- g_os_param.vtoy_img_path[Pos] = '\\';
- }
- }
-
- PeStart += sizeof(ventoy_os_param) + sizeof(ventoy_windows_data);
- sprintf_s(LunchFile, MAX_PATH, "ventoy\\%s", GetFileNameInPath(ExeFileName));
- SaveBuffer2File(LunchFile, Buffer + PeStart, FileSize - PeStart);
- break;
- }
- }
-
- if (PeStart >= FileSize)
- {
- Log("OS param not found");
- goto End;
- }
-
- if (g_os_param_reserved[0] == 2)
- {
- Log("skip hook for debug .....");
- rc = 0;
- goto End;
- }
-
- rc = VentoyHook(&g_os_param);
-
-End:
-
- if (Buffer)
- {
- free(Buffer);
- }
-
- return rc;
-}
-
-int main(int argc, char **argv)
-{
- int i = 0;
- int rc = 0;
- CHAR *Pos = NULL;
- CHAR CurDir[MAX_PATH];
- CHAR LunchFile[MAX_PATH];
- STARTUPINFOA Si;
- PROCESS_INFORMATION Pi;
-
- if (argv[0] && argv[0][0] && argv[0][1] == ':')
- {
- GetCurrentDirectoryA(sizeof(CurDir), CurDir);
-
- strcpy_s(LunchFile, sizeof(LunchFile), argv[0]);
- Pos = (char *)GetFileNameInPath(LunchFile);
-
- strcat_s(CurDir, sizeof(CurDir), "\\");
- strcat_s(CurDir, sizeof(CurDir), Pos);
-
- if (_stricmp(argv[0], CurDir) != 0)
- {
- *Pos = 0;
- SetCurrentDirectoryA(LunchFile);
- }
- }
-
- Log("######## VentoyJump ##########");
- Log("argc = %d argv[0] = <%s>", argc, argv[0]);
-
- if (Pos && *Pos == 0)
- {
- Log("Old current directory = <%s>", CurDir);
- Log("New current directory = <%s>", LunchFile);
- }
- else
- {
- GetCurrentDirectoryA(sizeof(CurDir), CurDir);
- Log("Current directory = <%s>", CurDir);
- }
-
- GetStartupInfoA(&Si);
-
- memset(LunchFile, 0, sizeof(LunchFile));
- rc = VentoyJump(argc, argv, LunchFile);
-
- if (g_os_param_reserved[0] == 3)
- {
- Log("Open log for debug ...");
- sprintf_s(LunchFile, sizeof(LunchFile), "%s", "notepad.exe ventoy.log");
- }
- else
- {
- Si.dwFlags |= STARTF_USESHOWWINDOW;
- Si.wShowWindow = SW_HIDE;
- Log("Ventoy jump %s ...", rc == 0 ? "success" : "failed");
- }
-
- CreateProcessA(NULL, LunchFile, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
-
- while (rc)
- {
- Log("Ventoy hook failed, now wait and retry ...");
- Sleep(1000);
-
- rc = VentoyHook(&g_os_param);
- }
-
- WaitForSingleObject(Pi.hProcess, INFINITE);
-
- return 0;
-}
+/******************************************************************************\r
+* vtoyjump.c\r
+*\r
+* Copyright (c) 2021, longpanda <admin@ventoy.net>\r
+*\r
+* This program is free software; you can redistribute it and/or\r
+* modify it under the terms of the GNU General Public License as\r
+* published by the Free Software Foundation; either version 3 of the\r
+* License, or (at your option) any later version.\r
+*\r
+* This program is distributed in the hope that it will be useful, but\r
+* WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+* General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with this program; if not, see <http://www.gnu.org/licenses/>.\r
+*\r
+*/\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <Windows.h>\r
+#include <virtdisk.h>\r
+#include <winioctl.h>\r
+#include <VersionHelpers.h>\r
+#include "vtoyjump.h"\r
+#include "fat_filelib.h"\r
+\r
+static ventoy_os_param g_os_param;\r
+static ventoy_windows_data g_windows_data;\r
+static UINT8 g_os_param_reserved[32];\r
+static INT g_system_bit = VTOY_BIT;\r
+static ventoy_guid g_ventoy_guid = VENTOY_GUID;\r
+static HANDLE g_vtoylog_mutex = NULL;\r
+static HANDLE g_vtoyins_mutex = NULL;\r
+\r
+static BOOL g_wimboot_mode = FALSE;\r
+\r
+static DWORD g_vtoy_disk_drive;\r
+\r
+static CHAR g_prog_full_path[MAX_PATH];\r
+static CHAR g_prog_dir[MAX_PATH];\r
+static CHAR g_prog_name[MAX_PATH];\r
+\r
+#define VTOY_PECMD_PATH "X:\\Windows\\system32\\ventoy\\PECMD.EXE"\r
+#define ORG_PECMD_PATH "X:\\Windows\\system32\\PECMD.EXE"\r
+#define ORG_PECMD_BK_PATH "X:\\Windows\\system32\\VTOYJUMP.EXE"\r
+\r
+#define WIMBOOT_FILE "X:\\Windows\\system32\\vtoy_wimboot"\r
+#define WIMBOOT_DONE "X:\\Windows\\system32\\vtoy_wimboot_done"\r
+\r
+#define AUTO_RUN_BAT "X:\\VentoyAutoRun.bat"\r
+#define AUTO_RUN_LOG "X:\\VentoyAutoRun.log"\r
+\r
+#define VTOY_AUTO_FILE "X:\\_vtoy_auto_install"\r
+\r
+#define LOG_FILE "X:\\Windows\\system32\\ventoy.log"\r
+#define MUTEX_LOCK(hmutex) if (hmutex != NULL) LockStatus = WaitForSingleObject(hmutex, INFINITE)\r
+#define MUTEX_UNLOCK(hmutex) if (hmutex != NULL && WAIT_OBJECT_0 == LockStatus) ReleaseMutex(hmutex)\r
+\r
+static const char * GetFileNameInPath(const char *fullpath)\r
+{\r
+ int i;\r
+\r
+ if (strstr(fullpath, ":"))\r
+ {\r
+ for (i = (int)strlen(fullpath); i > 0; i--)\r
+ {\r
+ if (fullpath[i - 1] == '/' || fullpath[i - 1] == '\\')\r
+ {\r
+ return fullpath + i;\r
+ }\r
+ }\r
+ }\r
+\r
+ return fullpath;\r
+}\r
+\r
+static int split_path_name(char *fullpath, char *dir, char *name)\r
+{\r
+ CHAR ch;\r
+ CHAR *Pos = NULL;\r
+\r
+ Pos = (CHAR *)GetFileNameInPath(fullpath);\r
+\r
+ strcpy_s(name, MAX_PATH, Pos);\r
+\r
+ ch = *(Pos - 1);\r
+ *(Pos - 1) = 0;\r
+ strcpy_s(dir, MAX_PATH, fullpath);\r
+ *(Pos - 1) = ch;\r
+\r
+ return 0;\r
+}\r
+\r
+static void TrimString(CHAR *String, BOOL TrimLeft)\r
+{\r
+ CHAR *Pos1 = String;\r
+ CHAR *Pos2 = String;\r
+ size_t Len = strlen(String);\r
+\r
+ while (Len > 0)\r
+ {\r
+ if (String[Len - 1] != ' ' && String[Len - 1] != '\t')\r
+ {\r
+ break;\r
+ }\r
+ String[Len - 1] = 0;\r
+ Len--;\r
+ }\r
+\r
+ if (TrimLeft)\r
+ { \r
+ while (*Pos1 == ' ' || *Pos1 == '\t')\r
+ {\r
+ Pos1++;\r
+ }\r
+\r
+ while (*Pos1)\r
+ {\r
+ *Pos2++ = *Pos1++;\r
+ }\r
+ *Pos2++ = 0;\r
+ }\r
+\r
+ return;\r
+}\r
+\r
+static int VentoyProcessRunCmd(const char *Fmt, ...)\r
+{\r
+ int Len = 0;\r
+ va_list Arg;\r
+ STARTUPINFOA Si;\r
+ PROCESS_INFORMATION Pi;\r
+ char szBuf[1024] = { 0 };\r
+\r
+ va_start(Arg, Fmt);\r
+ Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len, sizeof(szBuf)-Len, Fmt, Arg);\r
+ va_end(Arg);\r
+\r
+ GetStartupInfoA(&Si);\r
+ Si.dwFlags |= STARTF_USESHOWWINDOW;\r
+ Si.wShowWindow = SW_HIDE;\r
+\r
+ Log("Process Run: <%s>", szBuf);\r
+ CreateProcessA(NULL, szBuf, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);\r
+ WaitForSingleObject(Pi.hProcess, INFINITE);\r
+\r
+ return 0;\r
+}\r
+\r
+static CHAR VentoyGetFirstFreeDriveLetter(BOOL Reverse)\r
+{\r
+ int i;\r
+ CHAR Letter = 'T';\r
+ DWORD Drives;\r
+\r
+ Drives = GetLogicalDrives();\r
+\r
+ if (Reverse)\r
+ {\r
+ for (i = 25; i >= 2; i--)\r
+ {\r
+ if (0 == (Drives & (1 << i)))\r
+ {\r
+ Letter = 'A' + i;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ for (i = 2; i < 26; i++)\r
+ {\r
+ if (0 == (Drives & (1 << i)))\r
+ {\r
+ Letter = 'A' + i;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ Log("FirstFreeDriveLetter %u %C:", Reverse, Letter);\r
+ return Letter;\r
+}\r
+\r
+void Log(const char *Fmt, ...)\r
+{\r
+ va_list Arg;\r
+ int Len = 0;\r
+ FILE *File = NULL;\r
+ SYSTEMTIME Sys;\r
+ char szBuf[1024];\r
+ DWORD LockStatus = 0;\r
+ DWORD PID = GetCurrentProcessId();\r
+\r
+ GetLocalTime(&Sys);\r
+ Len += sprintf_s(szBuf, sizeof(szBuf),\r
+ "[%4d/%02d/%02d %02d:%02d:%02d.%03d] [%u] ",\r
+ Sys.wYear, Sys.wMonth, Sys.wDay,\r
+ Sys.wHour, Sys.wMinute, Sys.wSecond,\r
+ Sys.wMilliseconds, PID);\r
+\r
+ va_start(Arg, Fmt);\r
+ Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len, sizeof(szBuf)-Len, Fmt, Arg);\r
+ va_end(Arg);\r
+\r
+ MUTEX_LOCK(g_vtoylog_mutex);\r
+\r
+ fopen_s(&File, LOG_FILE, "a+");\r
+ if (File)\r
+ {\r
+ fwrite(szBuf, 1, Len, File);\r
+ fwrite("\n", 1, 1, File);\r
+ fclose(File);\r
+ }\r
+\r
+ MUTEX_UNLOCK(g_vtoylog_mutex);\r
+}\r
+\r
+\r
+static int LoadNtDriver(const char *DrvBinPath)\r
+{\r
+ int i;\r
+ int rc = 0;\r
+ BOOL Ret;\r
+ DWORD Status;\r
+ SC_HANDLE hServiceMgr;\r
+ SC_HANDLE hService;\r
+ char name[256] = { 0 };\r
+\r
+ for (i = (int)strlen(DrvBinPath) - 1; i >= 0; i--)\r
+ {\r
+ if (DrvBinPath[i] == '\\' || DrvBinPath[i] == '/')\r
+ {\r
+ sprintf_s(name, sizeof(name), "%s", DrvBinPath + i + 1);\r
+ break;\r
+ }\r
+ }\r
+\r
+ Log("Load NT driver: %s %s", DrvBinPath, name);\r
+\r
+ hServiceMgr = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);\r
+ if (hServiceMgr == NULL)\r
+ {\r
+ Log("OpenSCManager failed Error:%u", GetLastError());\r
+ return 1;\r
+ }\r
+\r
+ Log("OpenSCManager OK");\r
+\r
+ hService = CreateServiceA(hServiceMgr,\r
+ name,\r
+ name,\r
+ SERVICE_ALL_ACCESS,\r
+ SERVICE_KERNEL_DRIVER,\r
+ SERVICE_DEMAND_START,\r
+ SERVICE_ERROR_NORMAL,\r
+ DrvBinPath,\r
+ NULL, NULL, NULL, NULL, NULL);\r
+ if (hService == NULL)\r
+ {\r
+ Status = GetLastError();\r
+ if (Status != ERROR_IO_PENDING && Status != ERROR_SERVICE_EXISTS)\r
+ {\r
+ Log("CreateService failed v %u", Status);\r
+ CloseServiceHandle(hServiceMgr);\r
+ return 1;\r
+ }\r
+\r
+ hService = OpenServiceA(hServiceMgr, name, SERVICE_ALL_ACCESS);\r
+ if (hService == NULL)\r
+ {\r
+ Log("OpenService failed %u", Status);\r
+ CloseServiceHandle(hServiceMgr);\r
+ return 1;\r
+ }\r
+ }\r
+\r
+ Log("CreateService imdisk OK");\r
+\r
+ Ret = StartServiceA(hService, 0, NULL);\r
+ if (Ret)\r
+ {\r
+ Log("StartService OK");\r
+ }\r
+ else\r
+ {\r
+ Status = GetLastError();\r
+ if (Status == ERROR_SERVICE_ALREADY_RUNNING)\r
+ {\r
+ rc = 0;\r
+ }\r
+ else\r
+ {\r
+ Log("StartService error %u", Status);\r
+ rc = 1;\r
+ }\r
+ }\r
+\r
+ CloseServiceHandle(hService);\r
+ CloseServiceHandle(hServiceMgr);\r
+\r
+ Log("Load NT driver %s", rc ? "failed" : "success");\r
+\r
+ return rc;\r
+}\r
+\r
+static int ReadWholeFile2Buf(const char *Fullpath, void **Data, DWORD *Size)\r
+{\r
+ int rc = 1;\r
+ DWORD FileSize;\r
+ DWORD dwSize;\r
+ HANDLE Handle;\r
+ BYTE *Buffer = NULL;\r
+\r
+ Log("ReadWholeFile2Buf <%s>", Fullpath);\r
+\r
+ Handle = CreateFileA(Fullpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);\r
+ if (Handle == INVALID_HANDLE_VALUE)\r
+ {\r
+ Log("Could not open the file<%s>, error:%u", Fullpath, GetLastError());\r
+ goto End;\r
+ }\r
+\r
+ FileSize = SetFilePointer(Handle, 0, NULL, FILE_END);\r
+\r
+ Buffer = malloc(FileSize);\r
+ if (!Buffer)\r
+ {\r
+ Log("Failed to alloc memory size:%u", FileSize);\r
+ goto End;\r
+ }\r
+\r
+ SetFilePointer(Handle, 0, NULL, FILE_BEGIN);\r
+ if (!ReadFile(Handle, Buffer, FileSize, &dwSize, NULL))\r
+ {\r
+ Log("ReadFile failed, dwSize:%u error:%u", dwSize, GetLastError());\r
+ goto End;\r
+ }\r
+\r
+ *Data = Buffer;\r
+ *Size = FileSize;\r
+\r
+ Log("Success read file size:%u", FileSize);\r
+\r
+ rc = 0;\r
+\r
+End:\r
+ SAFE_CLOSE_HANDLE(Handle);\r
+\r
+ return rc;\r
+}\r
+\r
+static BOOL CheckPeHead(BYTE *Buffer, DWORD Size, DWORD Offset)\r
+{\r
+ UINT32 PeOffset;\r
+ BYTE *Head = NULL;\r
+ DWORD End;\r
+ ventoy_windows_data *pdata = NULL;\r
+\r
+ Head = Buffer + Offset;\r
+ pdata = (ventoy_windows_data *)Head;\r
+ Head += sizeof(ventoy_windows_data);\r
+\r
+ if (pdata->auto_install_script[0] && pdata->auto_install_len > 0)\r
+ {\r
+ End = Offset + sizeof(ventoy_windows_data) + pdata->auto_install_len + 60;\r
+ if (End < Size)\r
+ {\r
+ Head += pdata->auto_install_len;\r
+ }\r
+ }\r
+\r
+ if (Head[0] != 'M' || Head[1] != 'Z')\r
+ {\r
+ return FALSE;\r
+ }\r
+\r
+ PeOffset = *(UINT32 *)(Head + 60);\r
+ if (*(UINT32 *)(Head + PeOffset) != 0x00004550)\r
+ {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+\r
+static BOOL CheckOsParam(ventoy_os_param *param)\r
+{\r
+ UINT32 i;\r
+ BYTE Sum = 0;\r
+\r
+ if (memcmp(¶m->guid, &g_ventoy_guid, sizeof(ventoy_guid)))\r
+ {\r
+ return FALSE;\r
+ }\r
+\r
+ for (i = 0; i < sizeof(ventoy_os_param); i++)\r
+ {\r
+ Sum += *((BYTE *)param + i);\r
+ }\r
+ \r
+ if (Sum)\r
+ {\r
+ return FALSE;\r
+ }\r
+\r
+ if (param->vtoy_img_location_addr % 4096)\r
+ {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+static int SaveBuffer2File(const char *Fullpath, void *Buffer, DWORD Length)\r
+{\r
+ int rc = 1;\r
+ DWORD dwSize;\r
+ HANDLE Handle;\r
+\r
+ Log("SaveBuffer2File <%s> len:%u", Fullpath, Length);\r
+\r
+ Handle = CreateFileA(Fullpath, GENERIC_READ | GENERIC_WRITE,\r
+ FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, 0, 0);\r
+ if (Handle == INVALID_HANDLE_VALUE)\r
+ {\r
+ Log("Could not create new file, error:%u", GetLastError());\r
+ goto End;\r
+ }\r
+\r
+ WriteFile(Handle, Buffer, Length, &dwSize, NULL);\r
+\r
+ rc = 0;\r
+\r
+End:\r
+ SAFE_CLOSE_HANDLE(Handle);\r
+\r
+ return rc;\r
+}\r
+\r
+static int IsUTF8Encode(const char *src)\r
+{\r
+ int i;\r
+ const UCHAR *Byte = (const UCHAR *)src;\r
+\r
+ for (i = 0; i < MAX_PATH && Byte[i]; i++)\r
+ {\r
+ if (Byte[i] > 127)\r
+ {\r
+ return 1;\r
+ }\r
+ }\r
+ \r
+ return 0;\r
+}\r
+\r
+static int Utf8ToUtf16(const char* src, WCHAR * dst)\r
+{\r
+ int size = MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, 0);\r
+ return MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size + 1);\r
+}\r
+\r
+static BOOL IsDirExist(const char *Fmt, ...)\r
+{\r
+ va_list Arg; \r
+ DWORD Attr;\r
+ int UTF8 = 0;\r
+ CHAR FilePathA[MAX_PATH];\r
+ WCHAR FilePathW[MAX_PATH];\r
+\r
+ va_start(Arg, Fmt);\r
+ vsnprintf_s(FilePathA, sizeof(FilePathA), sizeof(FilePathA), Fmt, Arg);\r
+ va_end(Arg);\r
+\r
+ UTF8 = IsUTF8Encode(FilePathA);\r
+\r
+ if (UTF8)\r
+ {\r
+ Utf8ToUtf16(FilePathA, FilePathW);\r
+ Attr = GetFileAttributesW(FilePathW);\r
+ }\r
+ else\r
+ {\r
+ Attr = GetFileAttributesA(FilePathA);\r
+ }\r
+ \r
+ if (Attr != INVALID_FILE_ATTRIBUTES && (Attr & FILE_ATTRIBUTE_DIRECTORY))\r
+ {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+static BOOL IsFileExist(const char *Fmt, ...)\r
+{\r
+ va_list Arg;\r
+ HANDLE hFile;\r
+ DWORD Attr;\r
+ BOOL bRet = FALSE;\r
+ int UTF8 = 0;\r
+ CHAR FilePathA[MAX_PATH];\r
+ WCHAR FilePathW[MAX_PATH];\r
+\r
+ va_start(Arg, Fmt);\r
+ vsnprintf_s(FilePathA, sizeof(FilePathA), sizeof(FilePathA), Fmt, Arg);\r
+ va_end(Arg);\r
+\r
+ UTF8 = IsUTF8Encode(FilePathA);\r
+\r
+ if (UTF8)\r
+ {\r
+ Utf8ToUtf16(FilePathA, FilePathW);\r
+ hFile = CreateFileW(FilePathW, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);\r
+ }\r
+ else\r
+ {\r
+ hFile = CreateFileA(FilePathA, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);\r
+ }\r
+ if (INVALID_HANDLE_VALUE == hFile)\r
+ {\r
+ goto out;\r
+ }\r
+\r
+ CloseHandle(hFile);\r
+\r
+ if (UTF8)\r
+ {\r
+ Attr = GetFileAttributesW(FilePathW);\r
+ }\r
+ else\r
+ {\r
+ Attr = GetFileAttributesA(FilePathA);\r
+ }\r
+ \r
+ if (Attr & FILE_ATTRIBUTE_DIRECTORY)\r
+ {\r
+ goto out;\r
+ }\r
+\r
+ bRet = TRUE;\r
+\r
+out:\r
+ Log("File <%s> %s", FilePathA, (bRet ? "exist" : "NOT exist"));\r
+ return bRet;\r
+}\r
+\r
+static int GetPhyDiskUUID(const char LogicalDrive, UINT8 *UUID, UINT32 *DiskSig, DISK_EXTENT *DiskExtent)\r
+{\r
+ BOOL Ret;\r
+ DWORD dwSize;\r
+ HANDLE Handle;\r
+ VOLUME_DISK_EXTENTS DiskExtents;\r
+ CHAR PhyPath[128];\r
+ UINT8 SectorBuf[512];\r
+\r
+ Log("GetPhyDiskUUID %C", LogicalDrive);\r
+\r
+ sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\%C:", LogicalDrive);\r
+ Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);\r
+ if (Handle == INVALID_HANDLE_VALUE)\r
+ {\r
+ Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());\r
+ return 1;\r
+ }\r
+\r
+ Ret = DeviceIoControl(Handle,\r
+ IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,\r
+ NULL,\r
+ 0,\r
+ &DiskExtents,\r
+ (DWORD)(sizeof(DiskExtents)),\r
+ (LPDWORD)&dwSize,\r
+ NULL);\r
+ if (!Ret || DiskExtents.NumberOfDiskExtents == 0)\r
+ {\r
+ Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed, error:%u", GetLastError());\r
+ CloseHandle(Handle);\r
+ return 1;\r
+ }\r
+ CloseHandle(Handle);\r
+\r
+ memcpy(DiskExtent, DiskExtents.Extents, sizeof(DISK_EXTENT));\r
+ Log("%C: is in PhysicalDrive%d Offset:%llu", LogicalDrive, DiskExtents.Extents[0].DiskNumber, \r
+ (ULONGLONG)(DiskExtents.Extents[0].StartingOffset.QuadPart));\r
+\r
+ sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", DiskExtents.Extents[0].DiskNumber);\r
+ Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);\r
+ if (Handle == INVALID_HANDLE_VALUE)\r
+ {\r
+ Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());\r
+ return 1;\r
+ }\r
+\r
+ if (!ReadFile(Handle, SectorBuf, sizeof(SectorBuf), &dwSize, NULL))\r
+ {\r
+ Log("ReadFile failed, dwSize:%u error:%u", dwSize, GetLastError());\r
+ CloseHandle(Handle);\r
+ return 1;\r
+ }\r
+ \r
+ memcpy(UUID, SectorBuf + 0x180, 16);\r
+ if (DiskSig)\r
+ {\r
+ memcpy(DiskSig, SectorBuf + 0x1B8, 4);\r
+ }\r
+\r
+ CloseHandle(Handle);\r
+ return 0;\r
+}\r
+\r
+static int VentoyMountAnywhere(HANDLE Handle)\r
+{\r
+ DWORD Status;\r
+ ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters;\r
+\r
+ Log("VentoyMountAnywhere");\r
+\r
+ memset(&AttachParameters, 0, sizeof(AttachParameters));\r
+ AttachParameters.Version = ATTACH_VIRTUAL_DISK_VERSION_1;\r
+\r
+ Status = AttachVirtualDisk(Handle, NULL, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY | ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME, 0, &AttachParameters, NULL);\r
+ if (Status != ERROR_SUCCESS)\r
+ {\r
+ Log("Failed to attach virtual disk ErrorCode:%u", Status);\r
+ return 1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+int VentoyMountY(HANDLE Handle)\r
+{\r
+ int i;\r
+ BOOL bRet = FALSE;\r
+ DWORD Status;\r
+ DWORD physicalDriveNameSize;\r
+ CHAR *Pos = NULL;\r
+ WCHAR physicalDriveName[MAX_PATH];\r
+ CHAR physicalDriveNameA[MAX_PATH];\r
+ CHAR cdromDriveName[MAX_PATH];\r
+ ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters;\r
+\r
+ Log("VentoyMountY");\r
+\r
+ memset(&AttachParameters, 0, sizeof(AttachParameters));\r
+ AttachParameters.Version = ATTACH_VIRTUAL_DISK_VERSION_1;\r
+\r
+ 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);\r
+ if (Status != ERROR_SUCCESS)\r
+ {\r
+ Log("Failed to attach virtual disk ErrorCode:%u", Status);\r
+ return 1;\r
+ }\r
+\r
+ memset(physicalDriveName, 0, sizeof(physicalDriveName));\r
+ memset(physicalDriveNameA, 0, sizeof(physicalDriveNameA));\r
+\r
+ physicalDriveNameSize = MAX_PATH;\r
+ Status = GetVirtualDiskPhysicalPath(Handle, &physicalDriveNameSize, physicalDriveName);\r
+ if (Status != ERROR_SUCCESS)\r
+ {\r
+ Log("Failed GetVirtualDiskPhysicalPath ErrorCode:%u", Status);\r
+ return 1;\r
+ }\r
+\r
+ for (i = 0; physicalDriveName[i]; i++)\r
+ {\r
+ physicalDriveNameA[i] = (CHAR)toupper((CHAR)(physicalDriveName[i]));\r
+ }\r
+\r
+ Log("physicalDriveNameA=<%s>", physicalDriveNameA);\r
+\r
+ Pos = strstr(physicalDriveNameA, "CDROM");\r
+ if (!Pos)\r
+ {\r
+ Log("Not cdrom phy drive");\r
+ return 1;\r
+ }\r
+\r
+ sprintf_s(cdromDriveName, sizeof(cdromDriveName), "\\Device\\%s", Pos);\r
+ Log("cdromDriveName=<%s>", cdromDriveName);\r
+\r
+ for (i = 0; i < 3 && (bRet == FALSE); i++)\r
+ {\r
+ Sleep(1000);\r
+ bRet = DefineDosDeviceA(DDD_RAW_TARGET_PATH, "Y:", cdromDriveName);\r
+ Log("DefineDosDeviceA %s", bRet ? "success" : "failed");\r
+ }\r
+\r
+ return bRet ? 0 : 1;\r
+}\r
+\r
+static BOOL VentoyAPINeedMountY(const char *IsoPath)\r
+{\r
+ (void)IsoPath;\r
+\r
+ /* TBD */\r
+ return FALSE;\r
+}\r
+\r
+static int VentoyAttachVirtualDisk(HANDLE Handle, const char *IsoPath)\r
+{\r
+ int DriveYFree;\r
+ DWORD Drives;\r
+ \r
+ Drives = GetLogicalDrives();\r
+ if ((1 << 24) & Drives)\r
+ {\r
+ Log("Y: is occupied");\r
+ DriveYFree = 0;\r
+ }\r
+ else\r
+ {\r
+ Log("Y: is free now");\r
+ DriveYFree = 1;\r
+ }\r
+\r
+ if (DriveYFree && VentoyAPINeedMountY(IsoPath))\r
+ {\r
+ return VentoyMountY(Handle);\r
+ }\r
+ else\r
+ {\r
+ return VentoyMountAnywhere(Handle);\r
+ }\r
+}\r
+\r
+int VentoyMountISOByAPI(const char *IsoPath)\r
+{\r
+ int i;\r
+ HANDLE Handle;\r
+ DWORD Status;\r
+ WCHAR wFilePath[512] = { 0 };\r
+ VIRTUAL_STORAGE_TYPE StorageType;\r
+ OPEN_VIRTUAL_DISK_PARAMETERS OpenParameters;\r
+\r
+ Log("VentoyMountISOByAPI <%s>", IsoPath);\r
+\r
+ if (IsUTF8Encode(IsoPath))\r
+ {\r
+ Log("This is UTF8 encoding");\r
+ MultiByteToWideChar(CP_UTF8, 0, IsoPath, (int)strlen(IsoPath), wFilePath, (int)(sizeof(wFilePath) / sizeof(WCHAR)));\r
+ }\r
+ else\r
+ {\r
+ Log("This is ANSI encoding");\r
+ MultiByteToWideChar(CP_ACP, 0, IsoPath, (int)strlen(IsoPath), wFilePath, (int)(sizeof(wFilePath) / sizeof(WCHAR)));\r
+ }\r
+\r
+ memset(&StorageType, 0, sizeof(StorageType));\r
+ memset(&OpenParameters, 0, sizeof(OpenParameters));\r
+ \r
+ OpenParameters.Version = OPEN_VIRTUAL_DISK_VERSION_1;\r
+\r
+ for (i = 0; i < 10; i++)\r
+ {\r
+ Status = OpenVirtualDisk(&StorageType, wFilePath, VIRTUAL_DISK_ACCESS_READ, 0, &OpenParameters, &Handle);\r
+ if (ERROR_FILE_NOT_FOUND == Status || ERROR_PATH_NOT_FOUND == Status)\r
+ {\r
+ Log("OpenVirtualDisk ErrorCode:%u, now wait and retry...", Status);\r
+ Sleep(1000);\r
+ }\r
+ else\r
+ {\r
+ if (ERROR_SUCCESS == Status)\r
+ {\r
+ Log("OpenVirtualDisk success");\r
+ }\r
+ else if (ERROR_VIRTDISK_PROVIDER_NOT_FOUND == Status)\r
+ {\r
+ Log("VirtualDisk for ISO file is not supported in current system");\r
+ }\r
+ else\r
+ {\r
+ Log("Failed to open virtual disk ErrorCode:%u", Status);\r
+ }\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Status != ERROR_SUCCESS)\r
+ {\r
+ return 1;\r
+ }\r
+\r
+ Log("OpenVirtualDisk success");\r
+\r
+ Status = VentoyAttachVirtualDisk(Handle, IsoPath);\r
+ if (Status != ERROR_SUCCESS)\r
+ {\r
+ Log("Failed to attach virtual disk ErrorCode:%u", Status);\r
+ CloseHandle(Handle);\r
+ return 1;\r
+ }\r
+\r
+ Log("VentoyAttachVirtualDisk success");\r
+\r
+ CloseHandle(Handle);\r
+ return 0;\r
+}\r
+\r
+\r
+static HANDLE g_FatPhyDrive;\r
+static UINT64 g_Part2StartSec;\r
+\r
+static int CopyFileFromFatDisk(const CHAR* SrcFile, const CHAR *DstFile)\r
+{\r
+ int rc = 1;\r
+ int size = 0;\r
+ char *buf = NULL;\r
+ void *flfile = NULL;\r
+\r
+ Log("CopyFileFromFatDisk (%s)==>(%s)", SrcFile, DstFile);\r
+\r
+ flfile = fl_fopen(SrcFile, "rb");\r
+ if (flfile)\r
+ {\r
+ fl_fseek(flfile, 0, SEEK_END);\r
+ size = (int)fl_ftell(flfile);\r
+ fl_fseek(flfile, 0, SEEK_SET);\r
+\r
+ buf = (char *)malloc(size);\r
+ if (buf)\r
+ {\r
+ fl_fread(buf, 1, size, flfile);\r
+\r
+ rc = 0;\r
+ SaveBuffer2File(DstFile, buf, size);\r
+ free(buf);\r
+ }\r
+\r
+ fl_fclose(flfile);\r
+ }\r
+\r
+ return rc;\r
+}\r
+\r
+static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)\r
+{\r
+ DWORD dwSize;\r
+ BOOL bRet;\r
+ DWORD ReadSize;\r
+ LARGE_INTEGER liCurrentPosition;\r
+\r
+ liCurrentPosition.QuadPart = Sector + g_Part2StartSec;\r
+ liCurrentPosition.QuadPart *= 512;\r
+ SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);\r
+\r
+ ReadSize = (DWORD)(SectorCount * 512);\r
+\r
+ bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL);\r
+ if (bRet == FALSE || dwSize != ReadSize)\r
+ {\r
+ Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u", bRet, ReadSize, dwSize, GetLastError());\r
+ }\r
+\r
+ return 1;\r
+}\r
+\r
+static BOOL Is2K10PE(void)\r
+{\r
+ BOOL bRet = FALSE;\r
+ FILE *fp = NULL;\r
+ CHAR szLine[1024];\r
+\r
+ fopen_s(&fp, "X:\\Windows\\System32\\PECMD.INI", "r");\r
+ if (!fp)\r
+ {\r
+ return FALSE;\r
+ }\r
+\r
+ memset(szLine, 0, sizeof(szLine));\r
+ while (fgets(szLine, sizeof(szLine) - 1, fp))\r
+ {\r
+ if (strstr(szLine, "2k10\\"))\r
+ {\r
+ bRet = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ fclose(fp);\r
+ return bRet;\r
+}\r
+\r
+static CHAR GetIMDiskMountLogicalDrive(void)\r
+{\r
+ CHAR Letter = 'Y';\r
+ DWORD Drives;\r
+ DWORD Mask = 0x1000000;\r
+\r
+ // fixed use M as mountpoint for 2K10 PE\r
+ if (Is2K10PE())\r
+ {\r
+ Log("Use M: for 2K10 PE");\r
+ return 'M';\r
+ }\r
+\r
+ Drives = GetLogicalDrives();\r
+ Log("Drives=0x%x", Drives);\r
+ \r
+ while (Mask)\r
+ {\r
+ if ((Drives & Mask) == 0)\r
+ {\r
+ break;\r
+ }\r
+\r
+ Letter--;\r
+ Mask >>= 1;\r
+ }\r
+\r
+ return Letter;\r
+}\r
+\r
+UINT64 GetVentoyEfiPartStartSector(HANDLE hDrive)\r
+{\r
+ BOOL bRet;\r
+ DWORD dwSize; \r
+ MBR_HEAD MBR; \r
+ VTOY_GPT_INFO *pGpt = NULL;\r
+ UINT64 StartSector = 0;\r
+\r
+ SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);\r
+\r
+ bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);\r
+ Log("Read MBR Ret:%u Size:%u code:%u", bRet, dwSize, LASTERR);\r
+\r
+ if ((!bRet) || (dwSize != sizeof(MBR)))\r
+ {\r
+ 0;\r
+ }\r
+\r
+ if (MBR.PartTbl[0].FsFlag == 0xEE)\r
+ {\r
+ Log("GPT partition style");\r
+\r
+ pGpt = malloc(sizeof(VTOY_GPT_INFO));\r
+ if (!pGpt)\r
+ {\r
+ return 0;\r
+ }\r
+\r
+ SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);\r
+ bRet = ReadFile(hDrive, pGpt, sizeof(VTOY_GPT_INFO), &dwSize, NULL); \r
+ if ((!bRet) || (dwSize != sizeof(VTOY_GPT_INFO)))\r
+ {\r
+ Log("Failed to read gpt info %d %u %d", bRet, dwSize, LASTERR);\r
+ return 0;\r
+ }\r
+\r
+ StartSector = pGpt->PartTbl[1].StartLBA;\r
+ free(pGpt);\r
+ }\r
+ else\r
+ {\r
+ Log("MBR partition style");\r
+ StartSector = MBR.PartTbl[1].StartSectorId;\r
+ }\r
+\r
+ Log("GetVentoyEfiPart StartSector: %llu", StartSector);\r
+ return StartSector;\r
+}\r
+\r
+static int VentoyCopyImdisk(DWORD PhyDrive, CHAR *ImPath)\r
+{\r
+ int rc = 1;\r
+ BOOL bRet;\r
+ DWORD dwBytes;\r
+ HANDLE hDrive;\r
+ CHAR PhyPath[MAX_PATH];\r
+ GET_LENGTH_INFORMATION LengthInfo;\r
+\r
+ if (IsFileExist("X:\\Windows\\System32\\imdisk.exe"))\r
+ {\r
+ Log("imdisk.exe already exist, no need to copy...");\r
+ strcpy_s(ImPath, MAX_PATH, "imdisk.exe"); \r
+ return 0;\r
+ }\r
+\r
+ if (IsFileExist("X:\\Windows\\System32\\ventoy\\imdisk.exe"))\r
+ {\r
+ Log("imdisk.exe already copied, no need to copy...");\r
+ strcpy_s(ImPath, MAX_PATH, "ventoy\\imdisk.exe");\r
+ return 0;\r
+ }\r
+\r
+ sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", PhyDrive);\r
+ hDrive = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);\r
+ if (hDrive == INVALID_HANDLE_VALUE)\r
+ {\r
+ Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());\r
+ goto End;\r
+ }\r
+\r
+ bRet = DeviceIoControl(hDrive, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &LengthInfo, sizeof(LengthInfo), &dwBytes, NULL);\r
+ if (!bRet)\r
+ {\r
+ Log("Could not get phy disk %s size, error:%u", PhyPath, GetLastError());\r
+ goto End;\r
+ }\r
+\r
+ g_FatPhyDrive = hDrive;\r
+ g_Part2StartSec = GetVentoyEfiPartStartSector(hDrive);\r
+\r
+ Log("Parse FAT fs...");\r
+\r
+ fl_init();\r
+\r
+ if (0 == fl_attach_media(VentoyFatDiskRead, NULL))\r
+ {\r
+ if (g_system_bit == 64)\r
+ {\r
+ CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.sys", "ventoy\\imdisk.sys");\r
+ CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.exe", "ventoy\\imdisk.exe");\r
+ CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.cpl", "ventoy\\imdisk.cpl");\r
+ }\r
+ else\r
+ {\r
+ CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.sys", "ventoy\\imdisk.sys");\r
+ CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.exe", "ventoy\\imdisk.exe");\r
+ CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.cpl", "ventoy\\imdisk.cpl");\r
+ }\r
+\r
+ GetCurrentDirectoryA(sizeof(PhyPath), PhyPath);\r
+ strcat_s(PhyPath, sizeof(PhyPath), "\\ventoy\\imdisk.sys");\r
+\r
+ if (LoadNtDriver(PhyPath) == 0)\r
+ { \r
+ strcpy_s(ImPath, MAX_PATH, "ventoy\\imdisk.exe");\r
+ rc = 0;\r
+ }\r
+ }\r
+ fl_shutdown();\r
+\r
+End:\r
+\r
+ SAFE_CLOSE_HANDLE(hDrive);\r
+\r
+ return rc;\r
+}\r
+\r
+static int VentoyRunImdisk(const char *IsoPath, const char *imdiskexe)\r
+{\r
+ CHAR Letter;\r
+ CHAR Cmdline[512];\r
+ WCHAR CmdlineW[512];\r
+ PROCESS_INFORMATION Pi;\r
+\r
+ Log("VentoyRunImdisk <%s> <%s>", IsoPath, imdiskexe);\r
+\r
+ Letter = GetIMDiskMountLogicalDrive();\r
+ sprintf_s(Cmdline, sizeof(Cmdline), "%s -a -o ro -f \"%s\" -m %C:", imdiskexe, IsoPath, Letter);\r
+ Log("mount iso to %C: use imdisk cmd <%s>", Letter, Cmdline);\r
+\r
+ if (IsUTF8Encode(IsoPath))\r
+ {\r
+ STARTUPINFOW Si;\r
+ GetStartupInfoW(&Si);\r
+ Si.dwFlags |= STARTF_USESHOWWINDOW;\r
+ Si.wShowWindow = SW_HIDE;\r
+\r
+ Utf8ToUtf16(Cmdline, CmdlineW);\r
+ CreateProcessW(NULL, CmdlineW, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);\r
+\r
+ Log("This is UTF8 encoding");\r
+ }\r
+ else\r
+ {\r
+ STARTUPINFOA Si;\r
+ GetStartupInfoA(&Si);\r
+ Si.dwFlags |= STARTF_USESHOWWINDOW;\r
+ Si.wShowWindow = SW_HIDE;\r
+\r
+ CreateProcessA(NULL, Cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);\r
+\r
+ Log("This is ANSI encoding");\r
+ }\r
+\r
+ Log("Wait for imdisk process ...");\r
+ WaitForSingleObject(Pi.hProcess, INFINITE);\r
+ Log("imdisk process finished");\r
+\r
+ return 0;\r
+}\r
+\r
+int VentoyMountISOByImdisk(const char *IsoPath, DWORD PhyDrive)\r
+{\r
+ int rc = 1;\r
+ CHAR ImPath[MAX_PATH];\r
+\r
+ Log("VentoyMountISOByImdisk %s", IsoPath);\r
+\r
+ if (0 == VentoyCopyImdisk(PhyDrive, ImPath))\r
+ {\r
+ VentoyRunImdisk(IsoPath, ImPath);\r
+ rc = 0;\r
+ }\r
+\r
+ return rc;\r
+}\r
+\r
+static int GetIsoId(CONST CHAR *IsoPath, IsoId *ids)\r
+{\r
+ int i;\r
+ int n = 0;\r
+ HANDLE hFile;\r
+ DWORD dwSize = 0;\r
+ BOOL bRet[8];\r
+\r
+ hFile = CreateFileA(IsoPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);\r
+ if (hFile == INVALID_HANDLE_VALUE)\r
+ {\r
+ return 1;\r
+ }\r
+\r
+ SetFilePointer(hFile, 2048 * 16 + 8, NULL, FILE_BEGIN);\r
+ bRet[n++] = ReadFile(hFile, ids->SystemId, 32, &dwSize, NULL);\r
+ \r
+ SetFilePointer(hFile, 2048 * 16 + 40, NULL, FILE_BEGIN);\r
+ bRet[n++] = ReadFile(hFile, ids->VolumeId, 32, &dwSize, NULL);\r
+\r
+ SetFilePointer(hFile, 2048 * 16 + 318, NULL, FILE_BEGIN);\r
+ bRet[n++] = ReadFile(hFile, ids->PulisherId, 128, &dwSize, NULL);\r
+\r
+ SetFilePointer(hFile, 2048 * 16 + 446, NULL, FILE_BEGIN);\r
+ bRet[n++] = ReadFile(hFile, ids->PreparerId, 128, &dwSize, NULL);\r
+\r
+ CloseHandle(hFile);\r
+\r
+\r
+ for (i = 0; i < n; i++)\r
+ {\r
+ if (bRet[i] == FALSE)\r
+ {\r
+ return 1;\r
+ }\r
+ }\r
+\r
+\r
+ TrimString(ids->SystemId, FALSE);\r
+ TrimString(ids->VolumeId, FALSE);\r
+ TrimString(ids->PulisherId, FALSE);\r
+ TrimString(ids->PreparerId, FALSE);\r
+\r
+ Log("ISO ID: System<%s> Volume<%s> Pulisher<%s> Preparer<%s>", \r
+ ids->SystemId, ids->VolumeId, ids->PulisherId, ids->PreparerId);\r
+\r
+ return 0;\r
+}\r
+\r
+static int CheckSkipMountIso(CONST CHAR *IsoPath)\r
+{\r
+ BOOL InRoot = FALSE;\r
+ int slashcnt = 0;\r
+ CONST CHAR *p = NULL;\r
+ IsoId ID;\r
+\r
+ // C:\\xxx\r
+ for (p = IsoPath; *p; p++)\r
+ {\r
+ if (*p == '\\' || *p == '/')\r
+ {\r
+ slashcnt++;\r
+ }\r
+ }\r
+\r
+ if (slashcnt == 2)\r
+ {\r
+ InRoot = TRUE;\r
+ }\r
+\r
+ memset(&ID, 0, sizeof(ID));\r
+ if (GetIsoId(IsoPath, &ID))\r
+ {\r
+ return 0;\r
+ }\r
+\r
+ //Bob.Ombs.Modified.Win10PEx64.iso will auto find ISO file in root, so we can skip the mount\r
+ if (InRoot && strcmp(ID.VolumeId, "Modified-Win10PEx64") == 0)\r
+ {\r
+ return 1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+static int MountIsoFile(CONST CHAR *IsoPath, DWORD PhyDrive)\r
+{\r
+ if (CheckSkipMountIso(IsoPath))\r
+ {\r
+ Log("Skip mount ISO file for <%s>", IsoPath);\r
+ return 0;\r
+ }\r
+\r
+ if (IsWindows8OrGreater())\r
+ {\r
+ Log("This is Windows 8 or latter...");\r
+ if (VentoyMountISOByAPI(IsoPath) == 0)\r
+ {\r
+ Log("Mount iso by API success");\r
+ return 0;\r
+ }\r
+ else\r
+ {\r
+ Log("Mount iso by API failed, maybe not supported, try imdisk");\r
+ return VentoyMountISOByImdisk(IsoPath, PhyDrive);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ Log("This is before Windows 8 ...");\r
+ if (VentoyMountISOByImdisk(IsoPath, PhyDrive) == 0)\r
+ {\r
+ Log("Mount iso by imdisk success");\r
+ return 0;\r
+ }\r
+ else\r
+ {\r
+ return VentoyMountISOByAPI(IsoPath);\r
+ }\r
+ }\r
+}\r
+\r
+static int GetPhyDriveByLogicalDrive(int DriveLetter)\r
+{\r
+ BOOL Ret;\r
+ DWORD dwSize;\r
+ HANDLE Handle;\r
+ VOLUME_DISK_EXTENTS DiskExtents;\r
+ CHAR PhyPath[128];\r
+\r
+ sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\%C:", (CHAR)DriveLetter);\r
+\r
+ Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);\r
+ if (Handle == INVALID_HANDLE_VALUE)\r
+ {\r
+ Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());\r
+ return -1;\r
+ }\r
+\r
+ Ret = DeviceIoControl(Handle,\r
+ IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,\r
+ NULL,\r
+ 0,\r
+ &DiskExtents,\r
+ (DWORD)(sizeof(DiskExtents)),\r
+ (LPDWORD)&dwSize,\r
+ NULL);\r
+\r
+ if (!Ret || DiskExtents.NumberOfDiskExtents == 0)\r
+ {\r
+ Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath, GetLastError());\r
+ SAFE_CLOSE_HANDLE(Handle);\r
+ return -1;\r
+ }\r
+ SAFE_CLOSE_HANDLE(Handle);\r
+\r
+ Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",\r
+ PhyPath,\r
+ DiskExtents.Extents[0].DiskNumber,\r
+ DiskExtents.Extents[0].StartingOffset.QuadPart,\r
+ DiskExtents.Extents[0].ExtentLength.QuadPart\r
+ );\r
+\r
+ return (int)DiskExtents.Extents[0].DiskNumber;\r
+}\r
+\r
+\r
+static int DeleteVentoyPart2MountPoint(DWORD PhyDrive)\r
+{\r
+ CHAR Letter = 'A';\r
+ DWORD Drives;\r
+ DWORD PhyDisk;\r
+ CHAR DriveName[] = "?:\\";\r
+\r
+ Log("DeleteVentoyPart2MountPoint Phy%u ...", PhyDrive);\r
+\r
+ Drives = GetLogicalDrives();\r
+ while (Drives)\r
+ {\r
+ if ((Drives & 0x01) && IsFileExist("%C:\\ventoy\\ventoy.cpio", Letter))\r
+ {\r
+ Log("File %C:\\ventoy\\ventoy.cpio exist", Letter);\r
+\r
+ PhyDisk = GetPhyDriveByLogicalDrive(Letter);\r
+ Log("PhyDisk=%u for %C", PhyDisk, Letter);\r
+\r
+ if (PhyDisk == PhyDrive)\r
+ {\r
+ DriveName[0] = Letter;\r
+ DeleteVolumeMountPointA(DriveName);\r
+ return 0;\r
+ }\r
+ }\r
+\r
+ Letter++;\r
+ Drives >>= 1;\r
+ }\r
+\r
+ return 1;\r
+}\r
+\r
+static BOOL check_tar_archive(const char *archive, CHAR *tarName)\r
+{\r
+ int len;\r
+ int nameLen;\r
+ const char *pos = archive;\r
+ const char *slash = archive;\r
+\r
+ while (*pos)\r
+ {\r
+ if (*pos == '\\' || *pos == '/')\r
+ {\r
+ slash = pos;\r
+ }\r
+ pos++;\r
+ }\r
+\r
+ len = (int)strlen(slash);\r
+\r
+ if (len > 7 && (strncmp(slash + len - 7, ".tar.gz", 7) == 0 || strncmp(slash + len - 7, ".tar.xz", 7) == 0))\r
+ {\r
+ nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);\r
+ tarName[nameLen - 3] = 0;\r
+ return TRUE;\r
+ }\r
+ else if (len > 8 && strncmp(slash + len - 8, ".tar.bz2", 8) == 0)\r
+ {\r
+ nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);\r
+ tarName[nameLen - 4] = 0;\r
+ return TRUE;\r
+ }\r
+ else if (len > 9 && strncmp(slash + len - 9, ".tar.lzma", 9) == 0)\r
+ {\r
+ nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);\r
+ tarName[nameLen - 5] = 0;\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+static UCHAR *g_unxz_buffer = NULL;\r
+static int g_unxz_len = 0;\r
+\r
+static void unxz_error(char *x)\r
+{\r
+ Log("%s", x);\r
+}\r
+\r
+static int unxz_flush(void *src, unsigned int size)\r
+{\r
+ memcpy(g_unxz_buffer + g_unxz_len, src, size);\r
+ g_unxz_len += (int)size;\r
+\r
+ return (int)size;\r
+}\r
+\r
+static int DecompressInjectionArchive(const char *archive, DWORD PhyDrive)\r
+{\r
+ int rc = 1;\r
+ int writelen = 0;\r
+ UCHAR *Buffer = NULL;\r
+ UCHAR *RawBuffer = NULL;\r
+ BOOL bRet;\r
+ DWORD dwBytes;\r
+ DWORD dwSize;\r
+ HANDLE hDrive;\r
+ HANDLE hOut;\r
+ DWORD flags = CREATE_NO_WINDOW;\r
+ CHAR StrBuf[MAX_PATH];\r
+ CHAR tarName[MAX_PATH];\r
+ STARTUPINFOA Si;\r
+ PROCESS_INFORMATION Pi;\r
+ PROCESS_INFORMATION NewPi;\r
+ GET_LENGTH_INFORMATION LengthInfo;\r
+ SECURITY_ATTRIBUTES Sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };\r
+\r
+ Log("DecompressInjectionArchive %s", archive);\r
+\r
+ sprintf_s(StrBuf, sizeof(StrBuf), "\\\\.\\PhysicalDrive%d", PhyDrive);\r
+ hDrive = CreateFileA(StrBuf, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);\r
+ if (hDrive == INVALID_HANDLE_VALUE)\r
+ {\r
+ Log("Could not open the disk<%s>, error:%u", StrBuf, GetLastError());\r
+ goto End;\r
+ }\r
+\r
+ bRet = DeviceIoControl(hDrive, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &LengthInfo, sizeof(LengthInfo), &dwBytes, NULL);\r
+ if (!bRet)\r
+ {\r
+ Log("Could not get phy disk %s size, error:%u", StrBuf, GetLastError());\r
+ goto End;\r
+ }\r
+\r
+ g_FatPhyDrive = hDrive;\r
+ g_Part2StartSec = GetVentoyEfiPartStartSector(hDrive);\r
+\r
+ Log("Parse FAT fs...");\r
+\r
+ fl_init();\r
+\r
+ if (0 == fl_attach_media(VentoyFatDiskRead, NULL))\r
+ {\r
+ if (g_system_bit == 64)\r
+ {\r
+ CopyFileFromFatDisk("/ventoy/7z/64/7za.xz", "ventoy\\7za.xz");\r
+ }\r
+ else\r
+ {\r
+ CopyFileFromFatDisk("/ventoy/7z/32/7za.xz", "ventoy\\7za.xz");\r
+ }\r
+\r
+ ReadWholeFile2Buf("ventoy\\7za.xz", &Buffer, &dwSize);\r
+ Log("7za.xz file size:%u", dwSize);\r
+\r
+ RawBuffer = malloc(SIZE_1MB * 4);\r
+ if (RawBuffer)\r
+ {\r
+ g_unxz_buffer = RawBuffer;\r
+ g_unxz_len = 0;\r
+ unxz(Buffer, (int)dwSize, NULL, unxz_flush, NULL, &writelen, unxz_error);\r
+ if (writelen == (int)dwSize)\r
+ {\r
+ Log("Decompress success 7za.xz(%u) ---> 7za.exe(%d)", dwSize, g_unxz_len);\r
+ }\r
+ else\r
+ {\r
+ Log("Decompress failed 7za.xz(%u) ---> 7za.exe(%u)", dwSize, dwSize);\r
+ }\r
+\r
+ SaveBuffer2File("ventoy\\7za.exe", RawBuffer, (DWORD)g_unxz_len);\r
+\r
+ g_unxz_buffer = NULL;\r
+ g_unxz_len = 0;\r
+ free(RawBuffer);\r
+ }\r
+ else\r
+ {\r
+ Log("Failed to alloc 4MB memory");\r
+ }\r
+\r
+ sprintf_s(StrBuf, sizeof(StrBuf), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", archive);\r
+\r
+ Log("extract inject to X:");\r
+ Log("cmdline:<%s>", StrBuf);\r
+\r
+ GetStartupInfoA(&Si);\r
+\r
+ hOut = CreateFileA("ventoy\\7z.log",\r
+ FILE_APPEND_DATA,\r
+ FILE_SHARE_WRITE | FILE_SHARE_READ,\r
+ &Sa,\r
+ OPEN_ALWAYS,\r
+ FILE_ATTRIBUTE_NORMAL,\r
+ NULL);\r
+\r
+ Si.dwFlags |= STARTF_USESTDHANDLES;\r
+\r
+ if (hOut != INVALID_HANDLE_VALUE)\r
+ {\r
+ Si.hStdError = hOut;\r
+ Si.hStdOutput = hOut;\r
+ }\r
+\r
+ CreateProcessA(NULL, StrBuf, NULL, NULL, TRUE, flags, NULL, NULL, &Si, &Pi);\r
+ WaitForSingleObject(Pi.hProcess, INFINITE);\r
+\r
+ //\r
+ // decompress tar archive, for tar.gz/tar.xz/tar.bz2\r
+ //\r
+ if (check_tar_archive(archive, tarName))\r
+ {\r
+ Log("Decompress tar archive...<%s>", tarName);\r
+\r
+ sprintf_s(StrBuf, sizeof(StrBuf), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", tarName);\r
+\r
+ CreateProcessA(NULL, StrBuf, NULL, NULL, TRUE, flags, NULL, NULL, &Si, &NewPi);\r
+ WaitForSingleObject(NewPi.hProcess, INFINITE);\r
+\r
+ Log("Now delete %s", tarName);\r
+ DeleteFileA(tarName);\r
+ }\r
+\r
+ SAFE_CLOSE_HANDLE(hOut);\r
+ }\r
+ fl_shutdown();\r
+\r
+End:\r
+\r
+ SAFE_CLOSE_HANDLE(hDrive);\r
+\r
+ return rc;\r
+}\r
+\r
+static int UnattendNeedVarExpand(const char *script)\r
+{\r
+ FILE *fp = NULL;\r
+ char szLine[4096];\r
+\r
+ fopen_s(&fp, script, "r");\r
+ if (!fp)\r
+ {\r
+ return 0;\r
+ }\r
+\r
+ szLine[0] = szLine[4095] = 0;\r
+ \r
+ while (fgets(szLine, sizeof(szLine) - 1, fp))\r
+ {\r
+ if (strstr(szLine, "$$VT_"))\r
+ {\r
+ fclose(fp);\r
+ return 1;\r
+ }\r
+ \r
+ szLine[0] = szLine[4095] = 0;\r
+ }\r
+ \r
+ fclose(fp);\r
+ return 0;\r
+}\r
+\r
+static int ExpandSingleVar(VarDiskInfo *pDiskInfo, int DiskNum, const char *var, char *value, int len)\r
+{\r
+ int i;\r
+ int index = -1;\r
+ UINT64 uiDst = 0;\r
+ UINT64 uiDelta = 0;\r
+ UINT64 uiMaxSize = 0;\r
+ UINT64 uiMaxDelta = ULLONG_MAX;\r
+\r
+ value[0] = 0;\r
+ \r
+ if (strcmp(var, "VT_WINDOWS_DISK_1ST_NONVTOY") == 0)\r
+ {\r
+ for (i = 0; i < DiskNum; i++)\r
+ {\r
+ if (pDiskInfo[i].Capacity > 0 && i != g_vtoy_disk_drive)\r
+ {\r
+ Log("%s=<PhyDrive%d>", var, i);\r
+ sprintf_s(value, len, "%d", i);\r
+ return 0;\r
+ }\r
+ }\r
+ }\r
+ else if (strcmp(var, "VT_WINDOWS_DISK_1ST_NONUSB") == 0)\r
+ {\r
+ for (i = 0; i < DiskNum; i++)\r
+ {\r
+ if (pDiskInfo[i].Capacity > 0 && pDiskInfo[i].BusType != BusTypeUsb)\r
+ {\r
+ Log("%s=<PhyDrive%d>", var, i);\r
+ sprintf_s(value, len, "%d", i);\r
+ return 0;\r
+ }\r
+ }\r
+ }\r
+ else if (strcmp(var, "VT_WINDOWS_DISK_MAX_SIZE") == 0)\r
+ {\r
+ for (i = 0; i < DiskNum; i++)\r
+ {\r
+ if (pDiskInfo[i].Capacity > 0 && pDiskInfo[i].Capacity > uiMaxSize)\r
+ {\r
+ index = i;\r
+ uiMaxSize = pDiskInfo[i].Capacity;\r
+ }\r
+ }\r
+\r
+ Log("%s=<PhyDrive%d>", var, index);\r
+ sprintf_s(value, len, "%d", index);\r
+ }\r
+ else if (strncmp(var, "VT_WINDOWS_DISK_CLOSEST_", 24) == 0)\r
+ {\r
+ uiDst = strtoul(var + 24, NULL, 10);\r
+ uiDst = uiDst * (1024ULL * 1024ULL * 1024ULL);\r
+ \r
+ for (i = 0; i < DiskNum; i++)\r
+ {\r
+ if (pDiskInfo[i].Capacity == 0)\r
+ {\r
+ continue;\r
+ }\r
+ \r
+ if (pDiskInfo[i].Capacity > uiDst)\r
+ {\r
+ uiDelta = pDiskInfo[i].Capacity - uiDst;\r
+ }\r
+ else\r
+ {\r
+ uiDelta = uiDst - pDiskInfo[i].Capacity;\r
+ }\r
+ \r
+ if (uiDelta < uiMaxDelta)\r
+ {\r
+ uiMaxDelta = uiDelta;\r
+ index = i;\r
+ }\r
+ }\r
+\r
+ Log("%s=<PhyDrive%d>", var, index);\r
+ sprintf_s(value, len, "%d", index);\r
+ }\r
+ else\r
+ {\r
+ Log("Invalid var name <%s>", var);\r
+ sprintf_s(value, len, "$$%s$$", var);\r
+ }\r
+ \r
+ if (value[0] == 0)\r
+ {\r
+ sprintf_s(value, len, "$$%s$$", var);\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+static int GetRegDwordValue(HKEY Key, LPCSTR SubKey, LPCSTR ValueName, DWORD *pValue)\r
+{\r
+ HKEY hKey;\r
+ DWORD Type;\r
+ DWORD Size;\r
+ LSTATUS lRet;\r
+ DWORD Value;\r
+\r
+ lRet = RegOpenKeyExA(Key, SubKey, 0, KEY_QUERY_VALUE, &hKey);\r
+ Log("RegOpenKeyExA <%s> Ret:%ld", SubKey, lRet);\r
+\r
+ if (ERROR_SUCCESS == lRet)\r
+ {\r
+ Size = sizeof(Value);\r
+ lRet = RegQueryValueExA(hKey, ValueName, NULL, &Type, (LPBYTE)&Value, &Size);\r
+ Log("RegQueryValueExA <%s> ret:%u Size:%u Value:%u", ValueName, lRet, Size, Value);\r
+\r
+ *pValue = Value;\r
+ RegCloseKey(hKey);\r
+\r
+ return 0;\r
+ }\r
+ else\r
+ {\r
+ return 1;\r
+ }\r
+}\r
+\r
+static const CHAR * GetBusTypeString(int Type)\r
+{\r
+ switch (Type)\r
+ {\r
+ case BusTypeUnknown: return "unknown";\r
+ case BusTypeScsi: return "SCSI";\r
+ case BusTypeAtapi: return "Atapi";\r
+ case BusTypeAta: return "ATA";\r
+ case BusType1394: return "1394";\r
+ case BusTypeSsa: return "SSA";\r
+ case BusTypeFibre: return "Fibre";\r
+ case BusTypeUsb: return "USB";\r
+ case BusTypeRAID: return "RAID";\r
+ case BusTypeiScsi: return "iSCSI";\r
+ case BusTypeSas: return "SAS";\r
+ case BusTypeSata: return "SATA";\r
+ case BusTypeSd: return "SD";\r
+ case BusTypeMmc: return "MMC";\r
+ case BusTypeVirtual: return "Virtual";\r
+ case BusTypeFileBackedVirtual: return "FileBackedVirtual";\r
+ case BusTypeSpaces: return "Spaces";\r
+ case BusTypeNvme: return "Nvme";\r
+ }\r
+ return "unknown";\r
+}\r
+\r
+static int GetHumanReadableGBSize(UINT64 SizeBytes)\r
+{\r
+ int i;\r
+ int Pow2 = 1;\r
+ double Delta;\r
+ double GB = SizeBytes * 1.0 / 1000 / 1000 / 1000;\r
+\r
+ if ((SizeBytes % 1073741824) == 0)\r
+ {\r
+ return (int)(SizeBytes / 1073741824);\r
+ }\r
+\r
+ for (i = 0; i < 12; i++)\r
+ {\r
+ if (Pow2 > GB)\r
+ {\r
+ Delta = (Pow2 - GB) / Pow2;\r
+ }\r
+ else\r
+ {\r
+ Delta = (GB - Pow2) / Pow2;\r
+ }\r
+\r
+ if (Delta < 0.05)\r
+ {\r
+ return Pow2;\r
+ }\r
+\r
+ Pow2 <<= 1;\r
+ }\r
+\r
+ return (int)GB;\r
+}\r
+\r
+static int EnumerateAllDisk(VarDiskInfo **ppDiskInfo, int *pDiskNum)\r
+{\r
+ int i;\r
+ DWORD Value;\r
+ int DiskNum = 0;\r
+ BOOL bRet;\r
+ DWORD dwBytes;\r
+ VarDiskInfo *pDiskInfo = NULL;\r
+ HANDLE Handle = INVALID_HANDLE_VALUE;\r
+ CHAR PhyDrive[128]; \r
+ GET_LENGTH_INFORMATION LengthInfo;\r
+ STORAGE_PROPERTY_QUERY Query;\r
+ STORAGE_DESCRIPTOR_HEADER DevDescHeader;\r
+ STORAGE_DEVICE_DESCRIPTOR *pDevDesc;\r
+ \r
+ if (GetRegDwordValue(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\disk\\Enum", "Count", &Value) == 0)\r
+ {\r
+ DiskNum = (int)Value;\r
+ }\r
+ else\r
+ {\r
+ Log("Failed to read disk count");\r
+ return 1;\r
+ }\r
+\r
+ Log("Current phy disk count:%d", DiskNum);\r
+ if (DiskNum <= 0)\r
+ {\r
+ return 1;\r
+ }\r
+\r
+ pDiskInfo = malloc(DiskNum * sizeof(VarDiskInfo));\r
+ if (!pDiskInfo)\r
+ {\r
+ Log("Failed to alloc");\r
+ return 1;\r
+ }\r
+ memset(pDiskInfo, 0, DiskNum * sizeof(VarDiskInfo));\r
+\r
+ for (i = 0; i < DiskNum; i++)\r
+ {\r
+ SAFE_CLOSE_HANDLE(Handle);\r
+\r
+ safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", i);\r
+ Handle = CreateFileA(PhyDrive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); \r
+ Log("Create file Handle:%p %s status:%u", Handle, PhyDrive, LASTERR);\r
+\r
+ if (Handle == INVALID_HANDLE_VALUE)\r
+ {\r
+ continue;\r
+ }\r
+\r
+ bRet = DeviceIoControl(Handle,\r
+ IOCTL_DISK_GET_LENGTH_INFO, NULL,\r
+ 0,\r
+ &LengthInfo,\r
+ sizeof(LengthInfo),\r
+ &dwBytes,\r
+ NULL);\r
+ if (!bRet)\r
+ {\r
+ Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR);\r
+ continue;\r
+ }\r
+\r
+ Log("PHYSICALDRIVE%d size %llu bytes", i, (ULONGLONG)LengthInfo.Length.QuadPart);\r
+\r
+ Query.PropertyId = StorageDeviceProperty;\r
+ Query.QueryType = PropertyStandardQuery;\r
+\r
+ bRet = DeviceIoControl(Handle,\r
+ IOCTL_STORAGE_QUERY_PROPERTY,\r
+ &Query,\r
+ sizeof(Query),\r
+ &DevDescHeader,\r
+ sizeof(STORAGE_DESCRIPTOR_HEADER),\r
+ &dwBytes,\r
+ NULL);\r
+ if (!bRet)\r
+ {\r
+ Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR, dwBytes);\r
+ continue;\r
+ }\r
+\r
+ if (DevDescHeader.Size < sizeof(STORAGE_DEVICE_DESCRIPTOR))\r
+ {\r
+ Log("Invalid DevDescHeader.Size:%u", DevDescHeader.Size);\r
+ continue;\r
+ }\r
+\r
+ pDevDesc = (STORAGE_DEVICE_DESCRIPTOR *)malloc(DevDescHeader.Size);\r
+ if (!pDevDesc)\r
+ {\r
+ Log("failed to malloc error:%u len:%u", LASTERR, DevDescHeader.Size);\r
+ continue;\r
+ }\r
+\r
+ bRet = DeviceIoControl(Handle,\r
+ IOCTL_STORAGE_QUERY_PROPERTY,\r
+ &Query,\r
+ sizeof(Query),\r
+ pDevDesc,\r
+ DevDescHeader.Size,\r
+ &dwBytes,\r
+ NULL);\r
+ if (!bRet)\r
+ {\r
+ Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR, dwBytes);\r
+ free(pDevDesc);\r
+ continue;\r
+ }\r
+\r
+ pDiskInfo[i].RemovableMedia = pDevDesc->RemovableMedia;\r
+ pDiskInfo[i].BusType = pDevDesc->BusType;\r
+ pDiskInfo[i].DeviceType = pDevDesc->DeviceType;\r
+ pDiskInfo[i].Capacity = LengthInfo.Length.QuadPart;\r
+\r
+ if (pDevDesc->VendorIdOffset)\r
+ {\r
+ safe_strcpy(pDiskInfo[i].VendorId, (char *)pDevDesc + pDevDesc->VendorIdOffset);\r
+ TrimString(pDiskInfo[i].VendorId, TRUE);\r
+ }\r
+\r
+ if (pDevDesc->ProductIdOffset)\r
+ {\r
+ safe_strcpy(pDiskInfo[i].ProductId, (char *)pDevDesc + pDevDesc->ProductIdOffset);\r
+ TrimString(pDiskInfo[i].ProductId, TRUE);\r
+ }\r
+\r
+ if (pDevDesc->ProductRevisionOffset)\r
+ {\r
+ safe_strcpy(pDiskInfo[i].ProductRev, (char *)pDevDesc + pDevDesc->ProductRevisionOffset);\r
+ TrimString(pDiskInfo[i].ProductRev, TRUE);\r
+ }\r
+\r
+ if (pDevDesc->SerialNumberOffset)\r
+ {\r
+ safe_strcpy(pDiskInfo[i].SerialNumber, (char *)pDevDesc + pDevDesc->SerialNumberOffset);\r
+ TrimString(pDiskInfo[i].SerialNumber, TRUE);\r
+ }\r
+\r
+ free(pDevDesc);\r
+ SAFE_CLOSE_HANDLE(Handle);\r
+ }\r
+\r
+ Log("########## DUMP DISK BEGIN ##########");\r
+ for (i = 0; i < DiskNum; i++)\r
+ {\r
+ Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s",\r
+ i, GetBusTypeString(pDiskInfo[i].BusType), pDiskInfo[i].RemovableMedia,\r
+ GetHumanReadableGBSize(pDiskInfo[i].Capacity), pDiskInfo[i].Capacity,\r
+ pDiskInfo[i].VendorId, pDiskInfo[i].ProductId);\r
+ }\r
+ Log("Ventoy disk is PhyDvr%d", g_vtoy_disk_drive);\r
+ Log("########## DUMP DISK END ##########");\r
+\r
+ *ppDiskInfo = pDiskInfo;\r
+ *pDiskNum = DiskNum;\r
+ return 0;\r
+}\r
+\r
+static int UnattendVarExpand(const char *script, const char *tmpfile)\r
+{\r
+ FILE *fp = NULL;\r
+ FILE *fout = NULL;\r
+ char *start = NULL;\r
+ char *end = NULL;\r
+ char szLine[4096];\r
+ char szValue[256];\r
+ int DiskNum = 0;\r
+ VarDiskInfo *pDiskInfo = NULL;\r
+\r
+ Log("UnattendVarExpand ...");\r
+\r
+ if (EnumerateAllDisk(&pDiskInfo, &DiskNum))\r
+ {\r
+ Log("Failed to EnumerateAllDisk");\r
+ return 1;\r
+ }\r
+ \r
+ fopen_s(&fp, script, "r");\r
+ if (!fp)\r
+ {\r
+ free(pDiskInfo);\r
+ return 0;\r
+ }\r
+\r
+ fopen_s(&fout, tmpfile, "w+");\r
+ if (!fout)\r
+ {\r
+ fclose(fp);\r
+ free(pDiskInfo);\r
+ return 0;\r
+ }\r
+\r
+ szLine[0] = szLine[4095] = 0;\r
+ \r
+ while (fgets(szLine, sizeof(szLine) - 1, fp))\r
+ {\r
+ start = strstr(szLine, "$$VT_");\r
+ if (start)\r
+ {\r
+ end = strstr(start + 5, "$$");\r
+ }\r
+\r
+ if (start && end)\r
+ {\r
+ *start = 0;\r
+ fprintf(fout, "%s", szLine);\r
+\r
+ *end = 0;\r
+ ExpandSingleVar(pDiskInfo, DiskNum, start + 2, szValue, sizeof(szValue) - 1);\r
+ fprintf(fout, "%s", szValue);\r
+ \r
+ fprintf(fout, "%s", end + 2);\r
+ }\r
+ else\r
+ {\r
+ fprintf(fout, "%s", szLine);\r
+ }\r
+ \r
+ szLine[0] = szLine[4095] = 0;\r
+ }\r
+\r
+ fclose(fp);\r
+ fclose(fout);\r
+ free(pDiskInfo);\r
+ return 0;\r
+}\r
+\r
+//#define VAR_DEBUG 1\r
+\r
+static int CreateUnattendRegKey(const char *file)\r
+{\r
+ DWORD dw;\r
+ HKEY hKey;\r
+ LSTATUS Ret;\r
+\r
+#ifndef VAR_DEBUG\r
+ Ret = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "System\\Setup", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dw);\r
+ if (ERROR_SUCCESS == Ret)\r
+ {\r
+ Ret = RegSetValueEx(hKey, "UnattendFile", 0, REG_SZ, file, (DWORD)(strlen(file) + 1));\r
+ }\r
+#endif\r
+\r
+ return 0;\r
+}\r
+\r
+static int ProcessUnattendedInstallation(const char *script, DWORD PhyDrive)\r
+{\r
+ CHAR Letter;\r
+ CHAR DrvLetter;\r
+ CHAR TmpFile[MAX_PATH];\r
+ CHAR CurDir[MAX_PATH];\r
+ CHAR ImPath[MAX_PATH];\r
+\r
+ Log("Copy unattended XML ...");\r
+ \r
+ GetCurrentDirectory(sizeof(CurDir), CurDir);\r
+ Letter = CurDir[0];\r
+ if ((Letter >= 'A' && Letter <= 'Z') || (Letter >= 'a' && Letter <= 'z'))\r
+ {\r
+ Log("Current Drive Letter: %C", Letter);\r
+ }\r
+ else\r
+ {\r
+ Letter = 'X';\r
+ }\r
+\r
+#ifdef VAR_DEBUG\r
+ sprintf_s(CurDir, sizeof(CurDir), "%C:\\AutounattendXXX.xml", Letter);\r
+#else\r
+ sprintf_s(CurDir, sizeof(CurDir), "%C:\\Unattend.xml", Letter);\r
+#endif\r
+\r
+ if (UnattendNeedVarExpand(script))\r
+ {\r
+ sprintf_s(TmpFile, sizeof(TmpFile), "%C:\\__Autounattend", Letter);\r
+ UnattendVarExpand(script, TmpFile);\r
+ \r
+ Log("Expand Copy file <%s> --> <%s>", script, CurDir);\r
+ CopyFileA(TmpFile, CurDir, FALSE);\r
+ }\r
+ else\r
+ {\r
+ Log("No var expand copy file <%s> --> <%s>", script, CurDir);\r
+ CopyFileA(script, CurDir, FALSE);\r
+ }\r
+\r
+ VentoyCopyImdisk(PhyDrive, ImPath);\r
+ DrvLetter = VentoyGetFirstFreeDriveLetter(FALSE);\r
+ VentoyProcessRunCmd("%s -a -s 64M -m %C: -p \"/fs:FAT32 /q /y\"", ImPath, DrvLetter);\r
+\r
+ Sleep(300);\r
+\r
+ sprintf_s(TmpFile, sizeof(TmpFile), "%C:\\Unattend.xml", DrvLetter);\r
+ if (CopyFileA(CurDir, TmpFile, FALSE))\r
+ {\r
+ DeleteFileA(CurDir);\r
+ Log("Move file <%s> ==> <%s>, use the later as unattend XML", CurDir, TmpFile);\r
+ CreateUnattendRegKey(TmpFile);\r
+ }\r
+ else\r
+ {\r
+ Log("Failed to copy file <%s> ==> <%s>, use OLD", CurDir, TmpFile);\r
+ CreateUnattendRegKey(CurDir);\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+static int Windows11Bypass(const char *isofile, const char MntLetter, UINT8 Check, UINT8 NRO)\r
+{\r
+ int Ret = 1;\r
+ DWORD dwHandle;\r
+ DWORD dwSize;\r
+ DWORD dwValue = 1;\r
+ UINT VerLen = 0;\r
+ CHAR *Buffer = NULL;\r
+ VS_FIXEDFILEINFO* VerInfo = NULL;\r
+ CHAR CheckFile[MAX_PATH];\r
+ UINT16 Major, Minor, Build, Revision;\r
+\r
+ Log("Windows11Bypass for <%s> %C: Check:%u NRO:%u", isofile, MntLetter, Check, NRO);\r
+\r
+ if (FALSE == IsFileExist("%C:\\sources\\boot.wim", MntLetter) ||\r
+ FALSE == IsFileExist("%C:\\sources\\compatresources.dll", MntLetter))\r
+ {\r
+ Log("boot.wim/compatresources.dll not exist, this is not a windows install media.");\r
+ goto End;\r
+ }\r
+\r
+ if (FALSE == IsFileExist("%C:\\sources\\install.wim", MntLetter) && \r
+ FALSE == IsFileExist("%C:\\sources\\install.esd", MntLetter))\r
+ {\r
+ Log("install.wim/install.esd not exist, this is not a windows install media.");\r
+ goto End;\r
+ }\r
+\r
+ sprintf_s(CheckFile, sizeof(CheckFile), "%C:\\sources\\compatresources.dll", MntLetter);\r
+ dwSize = GetFileVersionInfoSizeA(CheckFile, &dwHandle);\r
+ if (0 == dwSize)\r
+ {\r
+ Log("Failed to get file version info size: %u", LASTERR);\r
+ goto End;\r
+ }\r
+\r
+ Buffer = malloc(dwSize);\r
+ if (!Buffer)\r
+ {\r
+ goto End;\r
+ }\r
+\r
+ if (FALSE == GetFileVersionInfoA(CheckFile, dwHandle, dwSize, Buffer))\r
+ {\r
+ Log("Failed to get file version info : %u", LASTERR);\r
+ goto End;\r
+ }\r
+\r
+ if (VerQueryValueA(Buffer, "\\", (LPVOID)&VerInfo, &VerLen) && VerLen != 0)\r
+ {\r
+ if (VerInfo->dwSignature == VS_FFI_SIGNATURE)\r
+ {\r
+ Major = HIWORD(VerInfo->dwFileVersionMS);\r
+ Minor = LOWORD(VerInfo->dwFileVersionMS);\r
+ Build = HIWORD(VerInfo->dwFileVersionLS);\r
+ Revision = LOWORD(VerInfo->dwFileVersionLS);\r
+\r
+ Log("FileVersionze: <%u %u %u %u>", Major, Minor, Build, Revision);\r
+\r
+ if (Major == 10 && Build > 20000)\r
+ {\r
+ Major = 11;\r
+ }\r
+\r
+ if (Major != 11)\r
+ {\r
+ Log("This is not Windows 11, not need to bypass.", Major);\r
+ goto End;\r
+ }\r
+ }\r
+ }\r
+\r
+ //Now we really need to bypass windows 11 check. create registry\r
+ HKEY hKey = NULL;\r
+ HKEY hSubKey = NULL;\r
+ LSTATUS Status;\r
+\r
+ if (Check)\r
+ {\r
+ Status = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "System\\Setup", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwSize);\r
+ if (ERROR_SUCCESS != Status)\r
+ {\r
+ Log("Failed to create reg key System\\Setup %u %u", LASTERR, Status);\r
+ goto End;\r
+ }\r
+\r
+ Status = RegCreateKeyExA(hKey, "LabConfig", 0, NULL, 0, KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_CREATE_SUB_KEY, NULL, &hSubKey, &dwSize);\r
+ if (ERROR_SUCCESS != Status)\r
+ {\r
+ Log("Failed to create LabConfig reg %u %u", LASTERR, Status);\r
+ goto End;\r
+ }\r
+\r
+ //set reg value\r
+ Status += RegSetValueExA(hSubKey, "BypassRAMCheck", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));\r
+ Status += RegSetValueExA(hSubKey, "BypassTPMCheck", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));\r
+ Status += RegSetValueExA(hSubKey, "BypassSecureBootCheck", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));\r
+ Status += RegSetValueExA(hSubKey, "BypassCPUCheck", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));\r
+\r
+ Log("Create bypass check registry %s %u", (Status == ERROR_SUCCESS) ? "SUCCESS" : "FAILED", Status);\r
+ }\r
+\r
+\r
+ if (NRO)\r
+ {\r
+ Status = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwSize);\r
+ if (ERROR_SUCCESS != Status)\r
+ {\r
+ Log("Failed to create reg key SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\OOBE %u %u", LASTERR, Status);\r
+ goto End;\r
+ }\r
+\r
+ Status = RegCreateKeyExA(hKey, "OOBE", 0, NULL, 0, KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_CREATE_SUB_KEY, NULL, &hSubKey, &dwSize);\r
+ if (ERROR_SUCCESS != Status)\r
+ {\r
+ Log("Failed to create OOBE reg %u %u", LASTERR, Status);\r
+ goto End;\r
+ }\r
+\r
+ Status += RegSetValueExA(hSubKey, "BypassNRO", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));\r
+ Log("Create BypassNRO registry %s %u", (Status == ERROR_SUCCESS) ? "SUCCESS" : "FAILED", Status);\r
+ }\r
+ \r
+\r
+ Ret = 0;\r
+\r
+End:\r
+ if (Buffer)\r
+ {\r
+ free(Buffer);\r
+ }\r
+ \r
+ return Ret; \r
+}\r
+\r
+static BOOL CheckVentoyDisk(DWORD DiskNum)\r
+{\r
+ DWORD dwSize = 0;\r
+ CHAR PhyPath[128];\r
+ UINT8 SectorBuf[512];\r
+ HANDLE Handle;\r
+ UINT8 check[8] = { 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44 };\r
+\r
+ sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", DiskNum);\r
+ Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);\r
+ if (Handle == INVALID_HANDLE_VALUE)\r
+ {\r
+ Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());\r
+ return FALSE;\r
+ }\r
+\r
+ if (!ReadFile(Handle, SectorBuf, sizeof(SectorBuf), &dwSize, NULL))\r
+ {\r
+ Log("ReadFile failed, dwSize:%u error:%u", dwSize, GetLastError());\r
+ CloseHandle(Handle);\r
+ return FALSE;\r
+ }\r
+\r
+ CloseHandle(Handle);\r
+\r
+ if (memcmp(SectorBuf + 0x190, check, 8) == 0)\r
+ {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+\r
+static int VentoyHook(ventoy_os_param *param)\r
+{\r
+ int i;\r
+ int rc;\r
+ BOOL find = FALSE;\r
+ BOOL vtoyfind = FALSE;\r
+ CHAR Letter;\r
+ CHAR MntLetter;\r
+ CHAR VtoyLetter;\r
+ DWORD Drives;\r
+ DWORD NewDrives;\r
+ DWORD VtoyDiskNum;\r
+ UINT32 DiskSig;\r
+ UINT32 VtoySig;\r
+ DISK_EXTENT DiskExtent;\r
+ DISK_EXTENT VtoyDiskExtent;\r
+ UINT8 UUID[16];\r
+ CHAR IsoPath[MAX_PATH];\r
+\r
+ Log("VentoyHook Path:<%s>", param->vtoy_img_path);\r
+\r
+ if (IsUTF8Encode(param->vtoy_img_path))\r
+ {\r
+ Log("This file is UTF8 encoding");\r
+ }\r
+\r
+ for (i = 0; i < 5; i++)\r
+ {\r
+ Letter = 'A';\r
+ Drives = GetLogicalDrives();\r
+ Log("Logic Drives: 0x%x", Drives);\r
+\r
+ while (Drives)\r
+ {\r
+ if (Drives & 0x01)\r
+ {\r
+ sprintf_s(IsoPath, sizeof(IsoPath), "%C:\\%s", Letter, param->vtoy_img_path);\r
+ if (IsFileExist("%s", IsoPath))\r
+ {\r
+ Log("File exist under %C:", Letter);\r
+ memset(UUID, 0, sizeof(UUID));\r
+ memset(&DiskExtent, 0, sizeof(DiskExtent));\r
+ if (GetPhyDiskUUID(Letter, UUID, NULL, &DiskExtent) == 0)\r
+ {\r
+ if (memcmp(UUID, param->vtoy_disk_guid, 16) == 0)\r
+ {\r
+ Log("Disk UUID match");\r
+ find = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ Log("File NOT exist under %C:", Letter);\r
+ }\r
+ }\r
+\r
+ Drives >>= 1;\r
+ Letter++;\r
+ }\r
+\r
+ if (find)\r
+ {\r
+ break;\r
+ }\r
+ else\r
+ {\r
+ Log("Now wait and retry ...");\r
+ Sleep(1000);\r
+ }\r
+ }\r
+\r
+ if (find == FALSE)\r
+ {\r
+ Log("Failed to find ISO file");\r
+ return 1;\r
+ }\r
+\r
+ Log("Find ISO file <%s>", IsoPath);\r
+ \r
+ //Find VtoyLetter in Vlnk Mode\r
+ if (g_os_param_reserved[6] == 1)\r
+ {\r
+ memcpy(&VtoySig, g_os_param_reserved + 7, 4);\r
+ for (i = 0; i < 5; i++)\r
+ {\r
+ VtoyLetter = 'A';\r
+ Drives = GetLogicalDrives();\r
+ Log("Logic Drives: 0x%x VentoySig:%08X", Drives, VtoySig);\r
+\r
+ while (Drives)\r
+ {\r
+ if (Drives & 0x01)\r
+ {\r
+ memset(UUID, 0, sizeof(UUID));\r
+ memset(&VtoyDiskExtent, 0, sizeof(VtoyDiskExtent));\r
+ DiskSig = 0;\r
+ if (GetPhyDiskUUID(VtoyLetter, UUID, &DiskSig, &VtoyDiskExtent) == 0)\r
+ {\r
+ Log("DiskSig=%08X PartStart=%lld", DiskSig, VtoyDiskExtent.StartingOffset.QuadPart);\r
+ if (DiskSig == VtoySig && VtoyDiskExtent.StartingOffset.QuadPart == SIZE_1MB)\r
+ {\r
+ Log("Ventoy Disk Sig match");\r
+ vtoyfind = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ Drives >>= 1;\r
+ VtoyLetter++;\r
+ }\r
+\r
+ if (vtoyfind)\r
+ {\r
+ Log("Find Ventoy Letter: %C", VtoyLetter);\r
+ break;\r
+ }\r
+ else\r
+ {\r
+ Log("Now wait and retry ...");\r
+ Sleep(1000);\r
+ }\r
+ }\r
+\r
+ if (vtoyfind == FALSE)\r
+ {\r
+ Log("Failed to find ventoy disk");\r
+ return 1;\r
+ }\r
+\r
+ VtoyDiskNum = VtoyDiskExtent.DiskNumber;\r
+ }\r
+ else\r
+ {\r
+ VtoyLetter = Letter;\r
+ Log("No vlnk mode %C", Letter);\r
+\r
+ VtoyDiskNum = DiskExtent.DiskNumber;\r
+ }\r
+\r
+ if (CheckVentoyDisk(VtoyDiskNum))\r
+ {\r
+ Log("Disk check OK %C: %u", VtoyLetter, VtoyDiskNum);\r
+ }\r
+ else\r
+ {\r
+ Log("Failed to check ventoy disk %u", VtoyDiskNum);\r
+ return 1;\r
+ }\r
+\r
+ g_vtoy_disk_drive = VtoyDiskNum;\r
+\r
+ Drives = GetLogicalDrives();\r
+ Log("Drives before mount: 0x%x", Drives);\r
+\r
+ rc = MountIsoFile(IsoPath, VtoyDiskNum);\r
+\r
+ NewDrives = GetLogicalDrives();\r
+ Log("Drives after mount: 0x%x (0x%x)", NewDrives, (NewDrives ^ Drives));\r
+\r
+ MntLetter = 'A';\r
+ NewDrives = (NewDrives ^ Drives);\r
+ while (NewDrives)\r
+ {\r
+ if (NewDrives & 0x01)\r
+ {\r
+ if ((NewDrives >> 1) == 0)\r
+ {\r
+ Log("The ISO file is mounted at %C:", MntLetter);\r
+ }\r
+ else\r
+ {\r
+ Log("Maybe the ISO file is mounted at %C:", MntLetter);\r
+ }\r
+ break;\r
+ }\r
+\r
+ NewDrives >>= 1;\r
+ MntLetter++;\r
+ }\r
+\r
+ Log("Mount ISO FILE: %s", rc == 0 ? "SUCCESS" : "FAILED");\r
+\r
+ //Windows 11 bypass check\r
+ if (g_windows_data.windows11_bypass_check == 1 || g_windows_data.windows11_bypass_nro == 1)\r
+ {\r
+ Windows11Bypass(IsoPath, MntLetter, g_windows_data.windows11_bypass_check, g_windows_data.windows11_bypass_nro);\r
+ }\r
+\r
+ // for protect\r
+ rc = DeleteVentoyPart2MountPoint(VtoyDiskNum);\r
+ Log("Delete ventoy mountpoint: %s", rc == 0 ? "SUCCESS" : "NO NEED");\r
+ \r
+ if (g_windows_data.auto_install_script[0])\r
+ {\r
+ if (IsFileExist("%s", VTOY_AUTO_FILE))\r
+ {\r
+ Log("use auto install script %s...", VTOY_AUTO_FILE);\r
+ ProcessUnattendedInstallation(VTOY_AUTO_FILE, VtoyDiskNum);\r
+ }\r
+ else\r
+ {\r
+ Log("auto install script %s not exist", IsoPath);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ Log("auto install no need");\r
+ }\r
+\r
+ if (g_windows_data.injection_archive[0])\r
+ {\r
+ sprintf_s(IsoPath, sizeof(IsoPath), "%C:%s", VtoyLetter, g_windows_data.injection_archive);\r
+ if (IsFileExist("%s", IsoPath))\r
+ {\r
+ Log("decompress injection archive %s...", IsoPath);\r
+ DecompressInjectionArchive(IsoPath, VtoyDiskNum);\r
+\r
+ if (IsFileExist("%s", AUTO_RUN_BAT))\r
+ {\r
+ HANDLE hOut;\r
+ DWORD flags = CREATE_NO_WINDOW;\r
+ CHAR StrBuf[1024];\r
+ STARTUPINFOA Si;\r
+ PROCESS_INFORMATION Pi;\r
+ SECURITY_ATTRIBUTES Sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };\r
+\r
+ Log("%s exist, now run it...", AUTO_RUN_BAT);\r
+\r
+ GetStartupInfoA(&Si);\r
+\r
+ hOut = CreateFileA(AUTO_RUN_LOG,\r
+ FILE_APPEND_DATA,\r
+ FILE_SHARE_WRITE | FILE_SHARE_READ,\r
+ &Sa,\r
+ OPEN_ALWAYS,\r
+ FILE_ATTRIBUTE_NORMAL,\r
+ NULL);\r
+\r
+ Si.dwFlags |= STARTF_USESTDHANDLES;\r
+ if (hOut != INVALID_HANDLE_VALUE)\r
+ {\r
+ Si.hStdError = hOut;\r
+ Si.hStdOutput = hOut;\r
+ }\r
+\r
+ sprintf_s(IsoPath, sizeof(IsoPath), "%C:\\%s", Letter, param->vtoy_img_path);\r
+ sprintf_s(StrBuf, sizeof(StrBuf), "cmd.exe /c %s \"%s\" %C", AUTO_RUN_BAT, IsoPath, MntLetter);\r
+ CreateProcessA(NULL, StrBuf, NULL, NULL, TRUE, flags, NULL, NULL, &Si, &Pi);\r
+ WaitForSingleObject(Pi.hProcess, INFINITE);\r
+\r
+ SAFE_CLOSE_HANDLE(hOut);\r
+ }\r
+ else\r
+ {\r
+ Log("%s not exist...", AUTO_RUN_BAT);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ Log("injection archive %s not exist", IsoPath);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ Log("no injection archive found");\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+static int ExtractWindowsDataFile(char *databuf)\r
+{\r
+ int len = 0;\r
+ char *filedata = NULL;\r
+ ventoy_windows_data *pdata = (ventoy_windows_data *)databuf;\r
+\r
+ Log("ExtractWindowsDataFile: auto install <%s:%d>", pdata->auto_install_script, pdata->auto_install_len);\r
+\r
+ filedata = databuf + sizeof(ventoy_windows_data);\r
+\r
+ if (pdata->auto_install_script[0] && pdata->auto_install_len > 0)\r
+ {\r
+ SaveBuffer2File(VTOY_AUTO_FILE, filedata, pdata->auto_install_len);\r
+ filedata += pdata->auto_install_len;\r
+ len = pdata->auto_install_len;\r
+ }\r
+ \r
+ return len;\r
+}\r
+\r
+static int ventoy_check_create_directory(void)\r
+{\r
+ if (IsDirExist("ventoy"))\r
+ {\r
+ Log("ventoy directory already exist");\r
+ }\r
+ else\r
+ {\r
+ Log("ventoy directory not exist, now create it.");\r
+ if (!CreateDirectoryA("ventoy", NULL))\r
+ {\r
+ Log("Failed to create ventoy directory err:%u", GetLastError());\r
+ return 1;\r
+ }\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+int VentoyJump(INT argc, CHAR **argv, CHAR *LunchFile)\r
+{\r
+ int rc = 1;\r
+ int stat = 0;\r
+ int exlen = 0;\r
+ DWORD Pos;\r
+ DWORD PeStart;\r
+ DWORD FileSize;\r
+ DWORD LockStatus = 0;\r
+ BYTE *Buffer = NULL; \r
+ CHAR ExeFileName[MAX_PATH];\r
+\r
+ sprintf_s(ExeFileName, sizeof(ExeFileName), "%s", argv[0]);\r
+ if (!IsFileExist("%s", ExeFileName))\r
+ {\r
+ Log("File %s NOT exist, now try %s.exe", ExeFileName, ExeFileName);\r
+ sprintf_s(ExeFileName, sizeof(ExeFileName), "%s.exe", argv[0]);\r
+\r
+ Log("File %s exist ? %s", ExeFileName, IsFileExist("%s", ExeFileName) ? "YES" : "NO");\r
+ }\r
+\r
+ if (ReadWholeFile2Buf(ExeFileName, (void **)&Buffer, &FileSize))\r
+ {\r
+ goto End;\r
+ }\r
+ \r
+ Log("VentoyJump %dbit", g_system_bit);\r
+\r
+ MUTEX_LOCK(g_vtoyins_mutex);\r
+ stat = ventoy_check_create_directory();\r
+ MUTEX_UNLOCK(g_vtoyins_mutex);\r
+\r
+ if (stat != 0)\r
+ {\r
+ goto End;\r
+ }\r
+\r
+ for (PeStart = 0; PeStart < FileSize; PeStart += 16)\r
+ {\r
+ if (CheckOsParam((ventoy_os_param *)(Buffer + PeStart)) && \r
+ CheckPeHead(Buffer, FileSize, PeStart + sizeof(ventoy_os_param)))\r
+ {\r
+ Log("Find os pararm at %u", PeStart);\r
+\r
+ memcpy(&g_os_param, Buffer + PeStart, sizeof(ventoy_os_param));\r
+ memcpy(&g_windows_data, Buffer + PeStart + sizeof(ventoy_os_param), sizeof(ventoy_windows_data)); \r
+ exlen = ExtractWindowsDataFile(Buffer + PeStart + sizeof(ventoy_os_param));\r
+ memcpy(g_os_param_reserved, g_os_param.vtoy_reserved, sizeof(g_os_param_reserved));\r
+\r
+ if (g_os_param_reserved[0] == 1)\r
+ {\r
+ Log("break here for debug .....");\r
+ goto End;\r
+ }\r
+\r
+ // convert / to \\ \r
+ for (Pos = 0; Pos < sizeof(g_os_param.vtoy_img_path) && g_os_param.vtoy_img_path[Pos]; Pos++)\r
+ {\r
+ if (g_os_param.vtoy_img_path[Pos] == '/')\r
+ {\r
+ g_os_param.vtoy_img_path[Pos] = '\\';\r
+ }\r
+ }\r
+\r
+ PeStart += sizeof(ventoy_os_param) + sizeof(ventoy_windows_data) + exlen;\r
+ sprintf_s(LunchFile, MAX_PATH, "ventoy\\%s", GetFileNameInPath(ExeFileName));\r
+\r
+ MUTEX_LOCK(g_vtoyins_mutex);\r
+ if (IsFileExist("%s", LunchFile))\r
+ {\r
+ Log("vtoyjump multiple call ...");\r
+ rc = 0;\r
+ MUTEX_UNLOCK(g_vtoyins_mutex);\r
+ goto End;\r
+ }\r
+\r
+ SaveBuffer2File(LunchFile, Buffer + PeStart, FileSize - PeStart);\r
+ MUTEX_UNLOCK(g_vtoyins_mutex);\r
+\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (PeStart >= FileSize)\r
+ {\r
+ Log("OS param not found");\r
+ goto End;\r
+ }\r
+\r
+ if (g_os_param_reserved[0] == 2)\r
+ {\r
+ Log("skip hook for debug .....");\r
+ rc = 0;\r
+ goto End;\r
+ }\r
+\r
+ rc = VentoyHook(&g_os_param);\r
+\r
+End:\r
+\r
+ if (Buffer)\r
+ {\r
+ free(Buffer);\r
+ }\r
+\r
+ return rc;\r
+}\r
+\r
+\r
+int real_main(int argc, char **argv)\r
+{\r
+ int i = 0;\r
+ int rc = 0;\r
+ CHAR NewFile[MAX_PATH];\r
+ CHAR LunchFile[MAX_PATH];\r
+ CHAR CallParam[1024] = { 0 };\r
+ STARTUPINFOA Si;\r
+ PROCESS_INFORMATION Pi;\r
+\r
+ Log("#### real_main #### argc = %d", argc);\r
+ Log("program full path: <%s>", g_prog_full_path);\r
+ Log("program dir: <%s>", g_prog_dir);\r
+ Log("program name: <%s>", g_prog_name);\r
+\r
+ Log("argc = %d", argc);\r
+ for (i = 0; i < argc; i++)\r
+ {\r
+ Log("argv[%d]=<%s>", i, argv[i]);\r
+ if (i > 0)\r
+ {\r
+ strcat_s(CallParam, sizeof(CallParam), " ");\r
+ strcat_s(CallParam, sizeof(CallParam), argv[i]);\r
+ }\r
+ }\r
+\r
+ GetStartupInfoA(&Si);\r
+ memset(LunchFile, 0, sizeof(LunchFile));\r
+\r
+ rc = VentoyJump(argc, argv, LunchFile);\r
+\r
+ Log("LunchFile=<%s> CallParam=<%s>", LunchFile, CallParam);\r
+\r
+ if (_stricmp(g_prog_name, "winpeshl.exe") != 0 && IsFileExist("ventoy\\%s", g_prog_name))\r
+ {\r
+ sprintf_s(NewFile, sizeof(NewFile), "%s\\VTOYJUMP.EXE", g_prog_dir);\r
+ MoveFileA(g_prog_full_path, NewFile);\r
+ Log("Move <%s> to <%s>", g_prog_full_path, NewFile);\r
+\r
+ sprintf_s(NewFile, sizeof(NewFile), "ventoy\\%s", g_prog_name);\r
+ CopyFileA(NewFile, g_prog_full_path, TRUE);\r
+ Log("Copy <%s> to <%s>", NewFile, g_prog_full_path);\r
+\r
+ sprintf_s(LunchFile, sizeof(LunchFile), "%s", g_prog_full_path);\r
+ Log("Final lunchFile is <%s>", LunchFile);\r
+ }\r
+ else\r
+ {\r
+ Log("We don't need to recover original <%s>", g_prog_name);\r
+ }\r
+\r
+ if (g_os_param_reserved[0] == 3)\r
+ {\r
+ Log("Open log for debug ...");\r
+ sprintf_s(LunchFile, sizeof(LunchFile), "%s", "notepad.exe ventoy.log");\r
+ }\r
+ else\r
+ {\r
+ if (CallParam[0])\r
+ {\r
+ strcat_s(LunchFile, sizeof(LunchFile), CallParam);\r
+ }\r
+ else if (NULL == strstr(LunchFile, "setup.exe"))\r
+ {\r
+ Log("Not setup.exe, hide windows.");\r
+ Si.dwFlags |= STARTF_USESHOWWINDOW;\r
+ Si.wShowWindow = SW_HIDE;\r
+ }\r
+\r
+ Log("Ventoy jump %s ...", rc == 0 ? "success" : "failed");\r
+ }\r
+\r
+ Log("Now launch <%s> ...", LunchFile);\r
+\r
+ if (g_os_param_reserved[0] == 4)\r
+ {\r
+ Log("Open cmd for debug ...");\r
+ Si.dwFlags |= STARTF_USESHOWWINDOW;\r
+ Si.wShowWindow = SW_NORMAL;\r
+ sprintf_s(LunchFile, sizeof(LunchFile), "%s", "cmd.exe");\r
+ }\r
+\r
+ Log("Backup log at this point");\r
+ CopyFileA(LOG_FILE, "X:\\Windows\\ventoy.backup", TRUE);\r
+\r
+ CreateProcessA(NULL, LunchFile, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);\r
+\r
+ for (i = 0; rc && i < 1800; i++)\r
+ {\r
+ Log("Ventoy hook failed, now wait and retry ...");\r
+ Sleep(1000);\r
+ rc = VentoyHook(&g_os_param);\r
+ }\r
+\r
+ Log("Wait process...");\r
+ WaitForSingleObject(Pi.hProcess, INFINITE);\r
+\r
+ Log("vtoyjump finished");\r
+ return 0;\r
+}\r
+\r
+static void VentoyToUpper(CHAR *str)\r
+{\r
+ int i;\r
+ for (i = 0; str[i]; i++)\r
+ {\r
+ str[i] = (CHAR)toupper(str[i]);\r
+ }\r
+}\r
+\r
+static int vtoy_remove_duplicate_file(char *File)\r
+{\r
+ CHAR szCmd[MAX_PATH];\r
+ CHAR NewFile[MAX_PATH];\r
+ STARTUPINFOA Si;\r
+ PROCESS_INFORMATION Pi;\r
+\r
+ Log("<1> Copy New file", File);\r
+ sprintf_s(NewFile, sizeof(NewFile), "%s_NEW", File);\r
+ CopyFileA(File, NewFile, FALSE);\r
+\r
+ Log("<2> Remove file <%s>", File);\r
+ GetStartupInfoA(&Si);\r
+ Si.dwFlags |= STARTF_USESHOWWINDOW;\r
+ Si.wShowWindow = SW_HIDE;\r
+ sprintf_s(szCmd, sizeof(szCmd), "cmd.exe /c del /F /Q %s", File);\r
+ CreateProcessA(NULL, szCmd, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);\r
+ WaitForSingleObject(Pi.hProcess, INFINITE);\r
+\r
+ Log("<3> Copy back file <%s>", File);\r
+ MoveFileA(NewFile, File);\r
+\r
+ return 0;\r
+}\r
+\r
+int main(int argc, char **argv)\r
+{\r
+ int i;\r
+ STARTUPINFOA Si;\r
+ PROCESS_INFORMATION Pi;\r
+ CHAR CurDir[MAX_PATH];\r
+ CHAR NewArgv0[MAX_PATH];\r
+ CHAR CallParam[1024] = { 0 };\r
+\r
+ g_vtoylog_mutex = CreateMutexA(NULL, FALSE, "VTOYLOG_LOCK");\r
+ g_vtoyins_mutex = CreateMutexA(NULL, FALSE, "VTOYINS_LOCK");\r
+\r
+ Log("######## VentoyJump %dbit ##########", g_system_bit);\r
+\r
+ GetCurrentDirectoryA(sizeof(CurDir), CurDir);\r
+ Log("Current directory is <%s>", CurDir);\r
+ \r
+ GetModuleFileNameA(NULL, g_prog_full_path, MAX_PATH);\r
+ split_path_name(g_prog_full_path, g_prog_dir, g_prog_name);\r
+\r
+ Log("EXE path: <%s> dir:<%s> name:<%s>", g_prog_full_path, g_prog_dir, g_prog_name);\r
+\r
+ if (IsFileExist(WIMBOOT_FILE))\r
+ {\r
+ Log("This is wimboot mode ...");\r
+ g_wimboot_mode = TRUE;\r
+\r
+ if (!IsFileExist(WIMBOOT_DONE))\r
+ {\r
+ vtoy_remove_duplicate_file(g_prog_full_path);\r
+ SaveBuffer2File(WIMBOOT_DONE, g_prog_full_path, 1);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ Log("This is normal mode ...");\r
+ }\r
+\r
+ if (_stricmp(g_prog_name, "WinLogon.exe") == 0)\r
+ {\r
+ Log("This time is rejump back ...");\r
+ \r
+ strcpy_s(g_prog_full_path, sizeof(g_prog_full_path), argv[1]);\r
+ split_path_name(g_prog_full_path, g_prog_dir, g_prog_name);\r
+\r
+ return real_main(argc - 1, argv + 1);\r
+ }\r
+ else if (_stricmp(g_prog_name, "PECMD.exe") == 0)\r
+ {\r
+ strcpy_s(NewArgv0, sizeof(NewArgv0), g_prog_dir);\r
+ VentoyToUpper(NewArgv0);\r
+ \r
+ if (NULL == strstr(NewArgv0, "SYSTEM32") && IsFileExist(ORG_PECMD_BK_PATH))\r
+ {\r
+ Log("Just call original pecmd.exe");\r
+ strcpy_s(CallParam, sizeof(CallParam), ORG_PECMD_PATH);\r
+ }\r
+ else\r
+ {\r
+ Log("We need to rejump for pecmd ...");\r
+\r
+ ventoy_check_create_directory();\r
+ CopyFileA(g_prog_full_path, "ventoy\\WinLogon.exe", TRUE);\r
+\r
+ sprintf_s(CallParam, sizeof(CallParam), "ventoy\\WinLogon.exe %s", g_prog_full_path);\r
+ }\r
+ \r
+ for (i = 1; i < argc; i++)\r
+ {\r
+ strcat_s(CallParam, sizeof(CallParam), " ");\r
+ strcat_s(CallParam, sizeof(CallParam), argv[i]);\r
+ }\r
+\r
+ Log("Now rejump to <%s> ...", CallParam);\r
+ GetStartupInfoA(&Si);\r
+ CreateProcessA(NULL, CallParam, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);\r
+\r
+ Log("Wait rejump process...");\r
+ WaitForSingleObject(Pi.hProcess, INFINITE);\r
+ Log("rejump finished");\r
+ return 0;\r
+ }\r
+ else\r
+ {\r
+ Log("We don't need to rejump ...");\r
+\r
+ ventoy_check_create_directory();\r
+ strcpy_s(NewArgv0, sizeof(NewArgv0), g_prog_full_path);\r
+ argv[0] = NewArgv0;\r
+\r
+ return real_main(argc, argv);\r
+ }\r
+}\r