/****************************************************************************** * vtoyjump.c * * Copyright (c) 2021, longpanda * * 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 . * */ #include #include #include #include #include #include #include #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 INT g_system_bit = VTOY_BIT; static ventoy_guid g_ventoy_guid = VENTOY_GUID; static HANDLE g_vtoylog_mutex = NULL; static HANDLE g_vtoyins_mutex = NULL; static BOOL g_wimboot_mode = FALSE; static DWORD g_vtoy_disk_drive; static CHAR g_prog_full_path[MAX_PATH]; static CHAR g_prog_dir[MAX_PATH]; static CHAR g_prog_name[MAX_PATH]; #define VTOY_PECMD_PATH "X:\\Windows\\system32\\ventoy\\PECMD.EXE" #define ORG_PECMD_PATH "X:\\Windows\\system32\\PECMD.EXE" #define ORG_PECMD_BK_PATH "X:\\Windows\\system32\\VTOYJUMP.EXE" #define WIMBOOT_FILE "X:\\Windows\\system32\\vtoy_wimboot" #define WIMBOOT_DONE "X:\\Windows\\system32\\vtoy_wimboot_done" #define AUTO_RUN_BAT "X:\\VentoyAutoRun.bat" #define AUTO_RUN_LOG "X:\\VentoyAutoRun.log" #define VTOY_AUTO_FILE "X:\\_vtoy_auto_install" #define LOG_FILE "X:\\Windows\\system32\\ventoy.log" #define MUTEX_LOCK(hmutex) if (hmutex != NULL) LockStatus = WaitForSingleObject(hmutex, INFINITE) #define MUTEX_UNLOCK(hmutex) if (hmutex != NULL && WAIT_OBJECT_0 == LockStatus) ReleaseMutex(hmutex) #define BREAK() BreakAndLaunchCmd(__LINE__) static void BreakAndLaunchCmd(int line) { STARTUPINFOA Si; PROCESS_INFORMATION Pi; Log("Break at line:%d", line); GetStartupInfoA(&Si); Si.dwFlags |= STARTF_USESHOWWINDOW; Si.wShowWindow = SW_NORMAL; CreateProcessA(NULL, "cmd.exe", NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi); WaitForSingleObject(Pi.hProcess, INFINITE); } static const char * GetFileNameInPath(const char *fullpath) { int i; if (strstr(fullpath, ":")) { for (i = (int)strlen(fullpath); i > 0; i--) { if (fullpath[i - 1] == '/' || fullpath[i - 1] == '\\') { return fullpath + i; } } } return fullpath; } static int split_path_name(char *fullpath, char *dir, char *name) { CHAR ch; CHAR *Pos = NULL; Pos = (CHAR *)GetFileNameInPath(fullpath); strcpy_s(name, MAX_PATH, Pos); ch = *(Pos - 1); *(Pos - 1) = 0; strcpy_s(dir, MAX_PATH, fullpath); *(Pos - 1) = ch; return 0; } static void TrimString(CHAR *String, BOOL TrimLeft) { CHAR *Pos1 = String; CHAR *Pos2 = String; size_t Len = strlen(String); while (Len > 0) { if (String[Len - 1] != ' ' && String[Len - 1] != '\t') { break; } String[Len - 1] = 0; Len--; } if (TrimLeft) { while (*Pos1 == ' ' || *Pos1 == '\t') { Pos1++; } while (*Pos1) { *Pos2++ = *Pos1++; } *Pos2++ = 0; } return; } static int VentoyProcessRunCmd(const char *Fmt, ...) { int Len = 0; va_list Arg; STARTUPINFOA Si; PROCESS_INFORMATION Pi; char szBuf[1024] = { 0 }; va_start(Arg, Fmt); Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len, sizeof(szBuf)-Len, Fmt, Arg); va_end(Arg); GetStartupInfoA(&Si); Si.dwFlags |= STARTF_USESHOWWINDOW; Si.wShowWindow = SW_HIDE; Log("Process Run: <%s>", szBuf); CreateProcessA(NULL, szBuf, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi); WaitForSingleObject(Pi.hProcess, INFINITE); return 0; } static CHAR VentoyGetFirstFreeDriveLetter(BOOL Reverse) { int i; CHAR Letter = 'T'; DWORD Drives; Drives = GetLogicalDrives(); if (Reverse) { for (i = 25; i >= 2; i--) { if (0 == (Drives & (1 << i))) { Letter = 'A' + i; break; } } } else { for (i = 2; i < 26; i++) { if (0 == (Drives & (1 << i))) { Letter = 'A' + i; break; } } } Log("FirstFreeDriveLetter %u %C:", Reverse, Letter); return Letter; } void Log(const char *Fmt, ...) { va_list Arg; int Len = 0; FILE *File = NULL; SYSTEMTIME Sys; char szBuf[1024]; DWORD LockStatus = 0; DWORD PID = GetCurrentProcessId(); GetLocalTime(&Sys); Len += sprintf_s(szBuf, sizeof(szBuf), "[%4d/%02d/%02d %02d:%02d:%02d.%03d] [%u] ", Sys.wYear, Sys.wMonth, Sys.wDay, Sys.wHour, Sys.wMinute, Sys.wSecond, Sys.wMilliseconds, PID); va_start(Arg, Fmt); Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len, sizeof(szBuf)-Len, Fmt, Arg); va_end(Arg); MUTEX_LOCK(g_vtoylog_mutex); fopen_s(&File, LOG_FILE, "a+"); if (File) { fwrite(szBuf, 1, Len, File); fwrite("\n", 1, 1, File); fclose(File); } MUTEX_UNLOCK(g_vtoylog_mutex); } 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 *Buffer, DWORD Size, DWORD Offset) { UINT32 PeOffset; BYTE *Head = NULL; DWORD End; ventoy_windows_data *pdata = NULL; Head = Buffer + Offset; pdata = (ventoy_windows_data *)Head; Head += sizeof(ventoy_windows_data); if (pdata->auto_install_script[0] && pdata->auto_install_len > 0) { End = Offset + sizeof(ventoy_windows_data) + pdata->auto_install_len + 60; if (End < Size) { Head += pdata->auto_install_len; } } if (Head[0] != 'M' || Head[1] != 'Z') { return FALSE; } PeOffset = *(UINT32 *)(Head + 60); if (*(UINT32 *)(Head + PeOffset) != 0x00004550) { return FALSE; } return TRUE; } 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 int IsUTF8Encode(const char *src) { int i; const UCHAR *Byte = (const UCHAR *)src; for (i = 0; i < MAX_PATH && Byte[i]; i++) { if (Byte[i] > 127) { return 1; } } return 0; } static int Utf16ToUtf8(const WCHAR *src, char *dst) { int len; int size; len = (int)wcslen(src) + 1; size = WideCharToMultiByte(CP_UTF8, 0, src, len, NULL, 0, NULL, NULL); return WideCharToMultiByte(CP_UTF8, 0, src, len, dst, size, NULL, NULL); } static int Utf8ToUtf16(const char* src, WCHAR * dst) { int size = MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, 0); return MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size + 1); } BOOL IsDirExist(const char *Fmt, ...) { va_list Arg; DWORD Attr; int UTF8 = 0; CHAR FilePathA[MAX_PATH]; WCHAR FilePathW[MAX_PATH]; va_start(Arg, Fmt); vsnprintf_s(FilePathA, sizeof(FilePathA), sizeof(FilePathA), Fmt, Arg); va_end(Arg); UTF8 = IsUTF8Encode(FilePathA); if (UTF8) { Utf8ToUtf16(FilePathA, FilePathW); Attr = GetFileAttributesW(FilePathW); } else { Attr = GetFileAttributesA(FilePathA); } if (Attr != INVALID_FILE_ATTRIBUTES && (Attr & FILE_ATTRIBUTE_DIRECTORY)) { return TRUE; } return FALSE; } BOOL IsFileExist(const char *Fmt, ...) { va_list Arg; HANDLE hFile; DWORD Attr; BOOL bRet = FALSE; int UTF8 = 0; CHAR FilePathA[MAX_PATH]; WCHAR FilePathW[MAX_PATH]; va_start(Arg, Fmt); vsnprintf_s(FilePathA, sizeof(FilePathA), sizeof(FilePathA), Fmt, Arg); va_end(Arg); UTF8 = IsUTF8Encode(FilePathA); if (UTF8) { Utf8ToUtf16(FilePathA, FilePathW); hFile = CreateFileW(FilePathW, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); } else { hFile = CreateFileA(FilePathA, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); } if (INVALID_HANDLE_VALUE == hFile) { goto out; } CloseHandle(hFile); if (UTF8) { Attr = GetFileAttributesW(FilePathW); } else { Attr = GetFileAttributesA(FilePathA); } if (Attr & FILE_ATTRIBUTE_DIRECTORY) { goto out; } bRet = TRUE; out: Log("File <%s> %s", FilePathA, (bRet ? "exist" : "NOT exist")); return bRet; } static int GetPhyDiskUUID(const char LogicalDrive, UINT8 *UUID, UINT32 *DiskSig, 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(DISK_EXTENT)); Log("%C: is in PhysicalDrive%d Offset:%llu", LogicalDrive, DiskExtents.Extents[0].DiskNumber, (ULONGLONG)(DiskExtents.Extents[0].StartingOffset.QuadPart)); 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); if (DiskSig) { memcpy(DiskSig, SectorBuf + 0x1B8, 4); } CloseHandle(Handle); return 0; } static int VentoyMountAnywhere(HANDLE Handle) { DWORD Status; ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters; Log("VentoyMountAnywhere"); memset(&AttachParameters, 0, sizeof(AttachParameters)); AttachParameters.Version = ATTACH_VIRTUAL_DISK_VERSION_1; 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); return 1; } return 0; } int VentoyMountY(HANDLE Handle) { int i; BOOL bRet = FALSE; DWORD Status; DWORD physicalDriveNameSize; CHAR *Pos = NULL; WCHAR physicalDriveName[MAX_PATH]; CHAR physicalDriveNameA[MAX_PATH]; CHAR cdromDriveName[MAX_PATH]; ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters; Log("VentoyMountY"); memset(&AttachParameters, 0, sizeof(AttachParameters)); AttachParameters.Version = ATTACH_VIRTUAL_DISK_VERSION_1; 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); if (Status != ERROR_SUCCESS) { Log("Failed to attach virtual disk ErrorCode:%u", Status); return 1; } memset(physicalDriveName, 0, sizeof(physicalDriveName)); memset(physicalDriveNameA, 0, sizeof(physicalDriveNameA)); physicalDriveNameSize = MAX_PATH; Status = GetVirtualDiskPhysicalPath(Handle, &physicalDriveNameSize, physicalDriveName); if (Status != ERROR_SUCCESS) { Log("Failed GetVirtualDiskPhysicalPath ErrorCode:%u", Status); return 1; } for (i = 0; physicalDriveName[i]; i++) { physicalDriveNameA[i] = (CHAR)toupper((CHAR)(physicalDriveName[i])); } Log("physicalDriveNameA=<%s>", physicalDriveNameA); Pos = strstr(physicalDriveNameA, "CDROM"); if (!Pos) { Log("Not cdrom phy drive"); return 1; } sprintf_s(cdromDriveName, sizeof(cdromDriveName), "\\Device\\%s", Pos); Log("cdromDriveName=<%s>", cdromDriveName); for (i = 0; i < 3 && (bRet == FALSE); i++) { Sleep(1000); bRet = DefineDosDeviceA(DDD_RAW_TARGET_PATH, "Y:", cdromDriveName); Log("DefineDosDeviceA %s", bRet ? "success" : "failed"); } return bRet ? 0 : 1; } static BOOL VentoyAPINeedMountY(const char *IsoPath) { (void)IsoPath; /* TBD */ return FALSE; } static int VentoyAttachVirtualDisk(HANDLE Handle, const char *IsoPath) { int DriveYFree; DWORD Drives; Drives = GetLogicalDrives(); if ((1 << 24) & Drives) { Log("Y: is occupied"); DriveYFree = 0; } else { Log("Y: is free now"); DriveYFree = 1; } if (DriveYFree && VentoyAPINeedMountY(IsoPath)) { return VentoyMountY(Handle); } else { return VentoyMountAnywhere(Handle); } } int VentoyMountISOByAPI(const char *IsoPath) { int i; HANDLE Handle; DWORD Status; WCHAR wFilePath[512] = { 0 }; VIRTUAL_STORAGE_TYPE StorageType; OPEN_VIRTUAL_DISK_PARAMETERS OpenParameters; Log("VentoyMountISOByAPI <%s>", IsoPath); if (IsUTF8Encode(IsoPath)) { Log("This is UTF8 encoding"); MultiByteToWideChar(CP_UTF8, 0, IsoPath, (int)strlen(IsoPath), wFilePath, (int)(sizeof(wFilePath) / sizeof(WCHAR))); } else { Log("This is ANSI encoding"); MultiByteToWideChar(CP_ACP, 0, IsoPath, (int)strlen(IsoPath), wFilePath, (int)(sizeof(wFilePath) / sizeof(WCHAR))); } memset(&StorageType, 0, sizeof(StorageType)); memset(&OpenParameters, 0, sizeof(OpenParameters)); OpenParameters.Version = OPEN_VIRTUAL_DISK_VERSION_1; for (i = 0; i < 10; i++) { Status = OpenVirtualDisk(&StorageType, wFilePath, VIRTUAL_DISK_ACCESS_READ, 0, &OpenParameters, &Handle); if (ERROR_FILE_NOT_FOUND == Status || ERROR_PATH_NOT_FOUND == Status) { Log("OpenVirtualDisk ErrorCode:%u, now wait and retry...", Status); Sleep(1000); } else { if (ERROR_SUCCESS == Status) { Log("OpenVirtualDisk success"); } else 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); } break; } } if (Status != ERROR_SUCCESS) { return 1; } Log("OpenVirtualDisk success"); Status = VentoyAttachVirtualDisk(Handle, IsoPath); if (Status != ERROR_SUCCESS) { Log("Failed to attach virtual disk ErrorCode:%u", Status); CloseHandle(Handle); return 1; } Log("VentoyAttachVirtualDisk success"); 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", bRet, ReadSize, dwSize, GetLastError()); } return 1; } static BOOL Is2K10PE(void) { BOOL bRet = FALSE; FILE *fp = NULL; CHAR szLine[1024]; fopen_s(&fp, "X:\\Windows\\System32\\PECMD.INI", "r"); if (!fp) { return FALSE; } memset(szLine, 0, sizeof(szLine)); while (fgets(szLine, sizeof(szLine) - 1, fp)) { if (strstr(szLine, "2k10\\")) { bRet = TRUE; break; } } fclose(fp); return bRet; } static CHAR GetIMDiskMountLogicalDrive(const char *suffix) { CHAR Letter = 'Y'; DWORD Drives; DWORD Mask = 0x1000000; // fixed use M as mountpoint for 2K10 PE if (Is2K10PE()) { Log("Use M: for 2K10 PE"); return 'M'; } //fixed use Z as mountpoint for Lenovo Product Recovery if (strcmp(suffix, "VTLRI") == 0) { return 'Z'; } 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; } static int VentoyCopyImdisk(DWORD PhyDrive, CHAR *ImPath) { int rc = 1; BOOL bRet; DWORD dwBytes; HANDLE hDrive; CHAR PhyPath[MAX_PATH]; GET_LENGTH_INFORMATION LengthInfo; if (IsFileExist("X:\\Windows\\System32\\imdisk.exe")) { Log("imdisk.exe already exist, no need to copy..."); strcpy_s(ImPath, MAX_PATH, "imdisk.exe"); return 0; } if (IsFileExist("X:\\Windows\\System32\\ventoy\\imdisk.exe")) { Log("imdisk.exe already copied, no need to copy..."); strcpy_s(ImPath, MAX_PATH, "ventoy\\imdisk.exe"); return 0; } 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_system_bit == 64) { 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) { strcpy_s(ImPath, MAX_PATH, "ventoy\\imdisk.exe"); rc = 0; } } fl_shutdown(); End: SAFE_CLOSE_HANDLE(hDrive); return rc; } static int VentoyRunImdisk(const char *suffix, const char *IsoPath, const char *imdiskexe, const char *opt) { CHAR Letter; CHAR Cmdline[512]; WCHAR CmdlineW[512]; PROCESS_INFORMATION Pi; Log("VentoyRunImdisk <%s> <%s> <%s> <%s>", suffix, IsoPath, imdiskexe, opt); Letter = GetIMDiskMountLogicalDrive(suffix); sprintf_s(Cmdline, sizeof(Cmdline), "%s -a -o %s -f \"%s\" -m %C:", imdiskexe, opt, IsoPath, Letter); Log("mount iso to %C: use imdisk cmd <%s>", Letter, Cmdline); if (IsUTF8Encode(IsoPath)) { STARTUPINFOW Si; GetStartupInfoW(&Si); Si.dwFlags |= STARTF_USESHOWWINDOW; Si.wShowWindow = SW_HIDE; Utf8ToUtf16(Cmdline, CmdlineW); CreateProcessW(NULL, CmdlineW, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi); Log("This is UTF8 encoding"); } else { STARTUPINFOA Si; GetStartupInfoA(&Si); Si.dwFlags |= STARTF_USESHOWWINDOW; Si.wShowWindow = SW_HIDE; CreateProcessA(NULL, Cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi); Log("This is ANSI encoding"); } Log("Wait for imdisk process ..."); WaitForSingleObject(Pi.hProcess, INFINITE); Log("imdisk process finished"); return 0; } int VentoyMountISOByImdisk(const char *IsoPath, DWORD PhyDrive) { int rc = 1; CHAR ImPath[MAX_PATH]; Log("VentoyMountISOByImdisk %s", IsoPath); if (0 == VentoyCopyImdisk(PhyDrive, ImPath)) { VentoyRunImdisk("iso", IsoPath, ImPath, "ro"); rc = 0; } return rc; } static int GetIsoId(CONST CHAR *IsoPath, IsoId *ids) { int i; int n = 0; HANDLE hFile; DWORD dwSize = 0; BOOL bRet[8]; hFile = CreateFileA(IsoPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) { return 1; } SetFilePointer(hFile, 2048 * 16 + 8, NULL, FILE_BEGIN); bRet[n++] = ReadFile(hFile, ids->SystemId, 32, &dwSize, NULL); SetFilePointer(hFile, 2048 * 16 + 40, NULL, FILE_BEGIN); bRet[n++] = ReadFile(hFile, ids->VolumeId, 32, &dwSize, NULL); SetFilePointer(hFile, 2048 * 16 + 318, NULL, FILE_BEGIN); bRet[n++] = ReadFile(hFile, ids->PulisherId, 128, &dwSize, NULL); SetFilePointer(hFile, 2048 * 16 + 446, NULL, FILE_BEGIN); bRet[n++] = ReadFile(hFile, ids->PreparerId, 128, &dwSize, NULL); CloseHandle(hFile); for (i = 0; i < n; i++) { if (bRet[i] == FALSE) { return 1; } } TrimString(ids->SystemId, FALSE); TrimString(ids->VolumeId, FALSE); TrimString(ids->PulisherId, FALSE); TrimString(ids->PreparerId, FALSE); Log("ISO ID: System<%s> Volume<%s> Pulisher<%s> Preparer<%s>", ids->SystemId, ids->VolumeId, ids->PulisherId, ids->PreparerId); return 0; } static int CheckSkipMountIso(CONST CHAR *IsoPath) { BOOL InRoot = FALSE; int slashcnt = 0; CONST CHAR *p = NULL; IsoId ID; // C:\\xxx for (p = IsoPath; *p; p++) { if (*p == '\\' || *p == '/') { slashcnt++; } } if (slashcnt == 2) { InRoot = TRUE; } memset(&ID, 0, sizeof(ID)); if (GetIsoId(IsoPath, &ID)) { return 0; } //Bob.Ombs.Modified.Win10PEx64.iso will auto find ISO file in root, so we can skip the mount if (InRoot && strcmp(ID.VolumeId, "Modified-Win10PEx64") == 0) { return 1; } return 0; } static int MountIsoFile(CONST CHAR *IsoPath, DWORD PhyDrive) { if (CheckSkipMountIso(IsoPath)) { Log("Skip mount ISO file for <%s>", IsoPath); return 0; } 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) && IsFileExist("%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 UCHAR *g_unxz_buffer = NULL; static int g_unxz_len = 0; static void unxz_error(char *x) { Log("%s", x); } static int unxz_flush(void *src, unsigned int size) { memcpy(g_unxz_buffer + g_unxz_len, src, size); g_unxz_len += (int)size; return (int)size; } static int DecompressInjectionArchive(const char *archive, DWORD PhyDrive) { int rc = 1; int writelen = 0; UCHAR *Buffer = NULL; UCHAR *RawBuffer = NULL; BOOL bRet; DWORD dwBytes; DWORD dwSize; 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_system_bit == 64) { CopyFileFromFatDisk("/ventoy/7z/64/7za.xz", "ventoy\\7za.xz"); } else { CopyFileFromFatDisk("/ventoy/7z/32/7za.xz", "ventoy\\7za.xz"); } ReadWholeFile2Buf("ventoy\\7za.xz", &Buffer, &dwSize); Log("7za.xz file size:%u", dwSize); RawBuffer = malloc(SIZE_1MB * 4); if (RawBuffer) { g_unxz_buffer = RawBuffer; g_unxz_len = 0; unxz(Buffer, (int)dwSize, NULL, unxz_flush, NULL, &writelen, unxz_error); if (writelen == (int)dwSize) { Log("Decompress success 7za.xz(%u) ---> 7za.exe(%d)", dwSize, g_unxz_len); } else { Log("Decompress failed 7za.xz(%u) ---> 7za.exe(%u)", dwSize, dwSize); } SaveBuffer2File("ventoy\\7za.exe", RawBuffer, (DWORD)g_unxz_len); g_unxz_buffer = NULL; g_unxz_len = 0; free(RawBuffer); } else { Log("Failed to alloc 4MB memory"); } 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 UnattendNeedVarExpand(const char *script) { FILE *fp = NULL; char szLine[4096]; fopen_s(&fp, script, "r"); if (!fp) { return 0; } szLine[0] = szLine[4095] = 0; while (fgets(szLine, sizeof(szLine) - 1, fp)) { if (strstr(szLine, "$$VT_")) { fclose(fp); return 1; } szLine[0] = szLine[4095] = 0; } fclose(fp); return 0; } static int ExpandSingleVar(VarDiskInfo *pDiskInfo, int DiskNum, const char *var, char *value, int len) { int i; int index = -1; UINT64 uiDst = 0; UINT64 uiDelta = 0; UINT64 uiMaxSize = 0; UINT64 uiMaxDelta = ULLONG_MAX; value[0] = 0; if (strcmp(var, "VT_WINDOWS_DISK_1ST_NONVTOY") == 0) { for (i = 0; i < DiskNum; i++) { if (pDiskInfo[i].Capacity > 0 && i != g_vtoy_disk_drive) { Log("%s=", var, i); sprintf_s(value, len, "%d", i); return 0; } } } else if (strcmp(var, "VT_WINDOWS_DISK_1ST_NONUSB") == 0) { for (i = 0; i < DiskNum; i++) { if (pDiskInfo[i].Capacity > 0 && pDiskInfo[i].BusType != BusTypeUsb) { Log("%s=", var, i); sprintf_s(value, len, "%d", i); return 0; } } } else if (strcmp(var, "VT_WINDOWS_DISK_MAX_SIZE") == 0) { for (i = 0; i < DiskNum; i++) { if (pDiskInfo[i].Capacity > 0 && pDiskInfo[i].Capacity > uiMaxSize) { index = i; uiMaxSize = pDiskInfo[i].Capacity; } } Log("%s=", var, index); sprintf_s(value, len, "%d", index); } else if (strncmp(var, "VT_WINDOWS_DISK_CLOSEST_", 24) == 0) { uiDst = strtoul(var + 24, NULL, 10); uiDst = uiDst * (1024ULL * 1024ULL * 1024ULL); for (i = 0; i < DiskNum; i++) { if (pDiskInfo[i].Capacity == 0) { continue; } if (pDiskInfo[i].Capacity > uiDst) { uiDelta = pDiskInfo[i].Capacity - uiDst; } else { uiDelta = uiDst - pDiskInfo[i].Capacity; } if (uiDelta < uiMaxDelta) { uiMaxDelta = uiDelta; index = i; } } Log("%s=", var, index); sprintf_s(value, len, "%d", index); } else { Log("Invalid var name <%s>", var); sprintf_s(value, len, "$$%s$$", var); } if (value[0] == 0) { sprintf_s(value, len, "$$%s$$", var); } return 0; } static int GetRegDwordValue(HKEY Key, LPCSTR SubKey, LPCSTR ValueName, DWORD *pValue) { HKEY hKey; DWORD Type; DWORD Size; LSTATUS lRet; DWORD Value; lRet = RegOpenKeyExA(Key, SubKey, 0, KEY_QUERY_VALUE, &hKey); Log("RegOpenKeyExA <%s> Ret:%ld", SubKey, lRet); if (ERROR_SUCCESS == lRet) { Size = sizeof(Value); lRet = RegQueryValueExA(hKey, ValueName, NULL, &Type, (LPBYTE)&Value, &Size); Log("RegQueryValueExA <%s> ret:%u Size:%u Value:%u", ValueName, lRet, Size, Value); *pValue = Value; RegCloseKey(hKey); return 0; } else { return 1; } } static const CHAR * GetBusTypeString(int Type) { switch (Type) { case BusTypeUnknown: return "unknown"; case BusTypeScsi: return "SCSI"; case BusTypeAtapi: return "Atapi"; case BusTypeAta: return "ATA"; case BusType1394: return "1394"; case BusTypeSsa: return "SSA"; case BusTypeFibre: return "Fibre"; case BusTypeUsb: return "USB"; case BusTypeRAID: return "RAID"; case BusTypeiScsi: return "iSCSI"; case BusTypeSas: return "SAS"; case BusTypeSata: return "SATA"; case BusTypeSd: return "SD"; case BusTypeMmc: return "MMC"; case BusTypeVirtual: return "Virtual"; case BusTypeFileBackedVirtual: return "FileBackedVirtual"; case BusTypeSpaces: return "Spaces"; case BusTypeNvme: return "Nvme"; } return "unknown"; } static int GetHumanReadableGBSize(UINT64 SizeBytes) { int i; int Pow2 = 1; double Delta; double GB = SizeBytes * 1.0 / 1000 / 1000 / 1000; if ((SizeBytes % 1073741824) == 0) { return (int)(SizeBytes / 1073741824); } for (i = 0; i < 12; i++) { if (Pow2 > GB) { Delta = (Pow2 - GB) / Pow2; } else { Delta = (GB - Pow2) / Pow2; } if (Delta < 0.05) { return Pow2; } Pow2 <<= 1; } return (int)GB; } static int EnumerateAllDisk(VarDiskInfo **ppDiskInfo, int *pDiskNum) { int i; DWORD Value; int DiskNum = 0; BOOL bRet; DWORD dwBytes; VarDiskInfo *pDiskInfo = NULL; HANDLE Handle = INVALID_HANDLE_VALUE; CHAR PhyDrive[128]; GET_LENGTH_INFORMATION LengthInfo; STORAGE_PROPERTY_QUERY Query; STORAGE_DESCRIPTOR_HEADER DevDescHeader; STORAGE_DEVICE_DESCRIPTOR *pDevDesc; if (GetRegDwordValue(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\disk\\Enum", "Count", &Value) == 0) { DiskNum = (int)Value; } else { Log("Failed to read disk count"); return 1; } Log("Current phy disk count:%d", DiskNum); if (DiskNum <= 0) { return 1; } pDiskInfo = malloc(DiskNum * sizeof(VarDiskInfo)); if (!pDiskInfo) { Log("Failed to alloc"); return 1; } memset(pDiskInfo, 0, DiskNum * sizeof(VarDiskInfo)); for (i = 0; i < DiskNum; i++) { SAFE_CLOSE_HANDLE(Handle); safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", i); Handle = CreateFileA(PhyDrive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); Log("Create file Handle:%p %s status:%u", Handle, PhyDrive, LASTERR); if (Handle == INVALID_HANDLE_VALUE) { continue; } bRet = DeviceIoControl(Handle, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &LengthInfo, sizeof(LengthInfo), &dwBytes, NULL); if (!bRet) { Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR); continue; } Log("PHYSICALDRIVE%d size %llu bytes", i, (ULONGLONG)LengthInfo.Length.QuadPart); Query.PropertyId = StorageDeviceProperty; Query.QueryType = PropertyStandardQuery; bRet = DeviceIoControl(Handle, IOCTL_STORAGE_QUERY_PROPERTY, &Query, sizeof(Query), &DevDescHeader, sizeof(STORAGE_DESCRIPTOR_HEADER), &dwBytes, NULL); if (!bRet) { Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR, dwBytes); continue; } if (DevDescHeader.Size < sizeof(STORAGE_DEVICE_DESCRIPTOR)) { Log("Invalid DevDescHeader.Size:%u", DevDescHeader.Size); continue; } pDevDesc = (STORAGE_DEVICE_DESCRIPTOR *)malloc(DevDescHeader.Size); if (!pDevDesc) { Log("failed to malloc error:%u len:%u", LASTERR, DevDescHeader.Size); continue; } bRet = DeviceIoControl(Handle, IOCTL_STORAGE_QUERY_PROPERTY, &Query, sizeof(Query), pDevDesc, DevDescHeader.Size, &dwBytes, NULL); if (!bRet) { Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR, dwBytes); free(pDevDesc); continue; } pDiskInfo[i].RemovableMedia = pDevDesc->RemovableMedia; pDiskInfo[i].BusType = pDevDesc->BusType; pDiskInfo[i].DeviceType = pDevDesc->DeviceType; pDiskInfo[i].Capacity = LengthInfo.Length.QuadPart; if (pDevDesc->VendorIdOffset) { safe_strcpy(pDiskInfo[i].VendorId, (char *)pDevDesc + pDevDesc->VendorIdOffset); TrimString(pDiskInfo[i].VendorId, TRUE); } if (pDevDesc->ProductIdOffset) { safe_strcpy(pDiskInfo[i].ProductId, (char *)pDevDesc + pDevDesc->ProductIdOffset); TrimString(pDiskInfo[i].ProductId, TRUE); } if (pDevDesc->ProductRevisionOffset) { safe_strcpy(pDiskInfo[i].ProductRev, (char *)pDevDesc + pDevDesc->ProductRevisionOffset); TrimString(pDiskInfo[i].ProductRev, TRUE); } if (pDevDesc->SerialNumberOffset) { safe_strcpy(pDiskInfo[i].SerialNumber, (char *)pDevDesc + pDevDesc->SerialNumberOffset); TrimString(pDiskInfo[i].SerialNumber, TRUE); } free(pDevDesc); SAFE_CLOSE_HANDLE(Handle); } Log("########## DUMP DISK BEGIN ##########"); for (i = 0; i < DiskNum; i++) { Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s", i, GetBusTypeString(pDiskInfo[i].BusType), pDiskInfo[i].RemovableMedia, GetHumanReadableGBSize(pDiskInfo[i].Capacity), pDiskInfo[i].Capacity, pDiskInfo[i].VendorId, pDiskInfo[i].ProductId); } Log("Ventoy disk is PhyDvr%d", g_vtoy_disk_drive); Log("########## DUMP DISK END ##########"); *ppDiskInfo = pDiskInfo; *pDiskNum = DiskNum; return 0; } static int UnattendVarExpand(const char *script, const char *tmpfile) { FILE *fp = NULL; FILE *fout = NULL; char *start = NULL; char *end = NULL; char szLine[4096]; char szValue[256]; int DiskNum = 0; VarDiskInfo *pDiskInfo = NULL; Log("UnattendVarExpand ..."); if (EnumerateAllDisk(&pDiskInfo, &DiskNum)) { Log("Failed to EnumerateAllDisk"); return 1; } fopen_s(&fp, script, "r"); if (!fp) { free(pDiskInfo); return 0; } fopen_s(&fout, tmpfile, "w+"); if (!fout) { fclose(fp); free(pDiskInfo); return 0; } szLine[0] = szLine[4095] = 0; while (fgets(szLine, sizeof(szLine) - 1, fp)) { start = strstr(szLine, "$$VT_"); if (start) { end = strstr(start + 5, "$$"); } if (start && end) { *start = 0; fprintf(fout, "%s", szLine); *end = 0; ExpandSingleVar(pDiskInfo, DiskNum, start + 2, szValue, sizeof(szValue) - 1); fprintf(fout, "%s", szValue); fprintf(fout, "%s", end + 2); } else { fprintf(fout, "%s", szLine); } szLine[0] = szLine[4095] = 0; } fclose(fp); fclose(fout); free(pDiskInfo); return 0; } //#define VAR_DEBUG 1 static int CreateUnattendRegKey(const char *file) { DWORD dw; HKEY hKey; LSTATUS Ret; #ifndef VAR_DEBUG 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, file, (DWORD)(strlen(file) + 1)); } #endif return 0; } static int ProcessUnattendedInstallation(const char *script, DWORD PhyDrive) { CHAR Letter; CHAR DrvLetter; CHAR TmpFile[MAX_PATH]; CHAR CurDir[MAX_PATH]; CHAR ImPath[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'; } #ifdef VAR_DEBUG sprintf_s(CurDir, sizeof(CurDir), "%C:\\AutounattendXXX.xml", Letter); #else sprintf_s(CurDir, sizeof(CurDir), "%C:\\Unattend.xml", Letter); #endif if (UnattendNeedVarExpand(script)) { sprintf_s(TmpFile, sizeof(TmpFile), "%C:\\__Autounattend", Letter); UnattendVarExpand(script, TmpFile); Log("Expand Copy file <%s> --> <%s>", script, CurDir); CopyFileA(TmpFile, CurDir, FALSE); } else { Log("No var expand copy file <%s> --> <%s>", script, CurDir); CopyFileA(script, CurDir, FALSE); } VentoyCopyImdisk(PhyDrive, ImPath); DrvLetter = VentoyGetFirstFreeDriveLetter(FALSE); VentoyProcessRunCmd("%s -a -s 64M -m %C: -p \"/fs:FAT32 /q /y\"", ImPath, DrvLetter); Sleep(300); sprintf_s(TmpFile, sizeof(TmpFile), "%C:\\Unattend.xml", DrvLetter); if (CopyFileA(CurDir, TmpFile, FALSE)) { DeleteFileA(CurDir); Log("Move file <%s> ==> <%s>, use the later as unattend XML", CurDir, TmpFile); CreateUnattendRegKey(TmpFile); } else { Log("Failed to copy file <%s> ==> <%s>, use OLD", CurDir, TmpFile); CreateUnattendRegKey(CurDir); } return 0; } static int VentoyGetFileVersion(const CHAR *FilePath, UINT16 *pMajor, UINT16 *pMinor, UINT16 *pBuild, UINT16 *pRevision) { int ret = 1; DWORD dwHandle; DWORD dwSize; UINT VerLen = 0; CHAR *Buffer = NULL; VS_FIXEDFILEINFO* VerInfo = NULL; UINT16 Major, Minor, Build, Revision; Log("Get file version for <%s>", FilePath); dwSize = GetFileVersionInfoSizeA(FilePath, &dwHandle); if (0 == dwSize) { Log("Failed to get file version info size: %u", LASTERR); goto End; } Buffer = malloc(dwSize); if (!Buffer) { Log("malloc failed %u", dwSize); goto End; } if (FALSE == GetFileVersionInfoA(FilePath, dwHandle, dwSize, Buffer)) { Log("Failed to get file version info : %u", LASTERR); goto End; } if (VerQueryValueA(Buffer, "\\", (LPVOID)&VerInfo, &VerLen) && VerLen != 0) { if (VerInfo->dwSignature == VS_FFI_SIGNATURE) { Major = HIWORD(VerInfo->dwFileVersionMS); Minor = LOWORD(VerInfo->dwFileVersionMS); Build = HIWORD(VerInfo->dwFileVersionLS); Revision = LOWORD(VerInfo->dwFileVersionLS); Log("FileVersionze: <%u %u %u %u>", Major, Minor, Build, Revision); if (Major == 10 && Build > 20000) { Major = 11; } if (pMajor) { *pMajor = Major; } if (pMinor) { *pMinor = Minor; } if (pBuild) { *pBuild = Build; } if (pRevision) { *pRevision = Revision; } ret = 0; } else { Log("Invalid verinfo signature 0x%x", VerInfo->dwSignature); } } else { Log("VerQueryValueA failed %u", LASTERR); } End: if (Buffer) { free(Buffer); } return ret; } static BOOL VentoyIsNeedBypass(const char *isofile, const char MntLetter) { UINT16 Major; BOOL bRet = FALSE; CHAR CheckFile[MAX_PATH]; if (FALSE == IsFileExist("%C:\\sources\\install.wim", MntLetter) && FALSE == IsFileExist("%C:\\sources\\install.esd", MntLetter)) { Log("install.wim/install.esd not exist, this is not a windows install media."); goto End; } if (FALSE == IsFileExist("%C:\\sources\\boot.wim", MntLetter)) { Log("boot.wim not exist, this is not a windows install media."); goto End; } if (IsFileExist("%C:\\sources\\compatresources.dll", MntLetter)) { sprintf_s(CheckFile, sizeof(CheckFile), "%C:\\sources\\compatresources.dll", MntLetter); } else if (IsFileExist("%C:\\setup.exe", MntLetter)) { sprintf_s(CheckFile, sizeof(CheckFile), "%C:\\setup.exe", MntLetter); } else if (IsFileExist("X:\\setup.exe")) { sprintf_s(CheckFile, sizeof(CheckFile), "X:\\setup.exe"); } else { Log("No Check file found"); goto End; } if (VentoyGetFileVersion(CheckFile, &Major, NULL, NULL, NULL)) { goto End; } if (Major >= 11) { Log("Enable for Windows 11 %u", Major); bRet = TRUE; } else { Log("This is not Windows 11, not need to bypass %u.", Major); } End: return bRet; } static int Windows11Bypass(const char *isofile, const char MntLetter, UINT8 Check, UINT8 NRO) { int Ret = 1; HKEY hKey = NULL; HKEY hSubKey = NULL; LSTATUS Status; DWORD dwValue = 1; DWORD dwSize; Log("Windows11Bypass for <%s> %C: Check:%u NRO:%u", isofile, MntLetter, Check, NRO); if (!VentoyIsNeedBypass(isofile, MntLetter)) { goto End; } //Now we really need to bypass windows 11 check. create registry if (Check) { Status = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "System\\Setup", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwSize); if (ERROR_SUCCESS != Status) { Log("Failed to create reg key System\\Setup %u %u", LASTERR, Status); goto End; } Status = RegCreateKeyExA(hKey, "LabConfig", 0, NULL, 0, KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_CREATE_SUB_KEY, NULL, &hSubKey, &dwSize); if (ERROR_SUCCESS != Status) { Log("Failed to create LabConfig reg %u %u", LASTERR, Status); goto End; } //set reg value Status += RegSetValueExA(hSubKey, "BypassRAMCheck", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD)); Status += RegSetValueExA(hSubKey, "BypassTPMCheck", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD)); Status += RegSetValueExA(hSubKey, "BypassSecureBootCheck", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD)); Status += RegSetValueExA(hSubKey, "BypassCPUCheck", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD)); Log("Create bypass check registry %s %u", (Status == ERROR_SUCCESS) ? "SUCCESS" : "FAILED", Status); } if (NRO) { Status = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwSize); if (ERROR_SUCCESS != Status) { Log("Failed to create reg key SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\OOBE %u %u", LASTERR, Status); goto End; } Status = RegCreateKeyExA(hKey, "OOBE", 0, NULL, 0, KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_CREATE_SUB_KEY, NULL, &hSubKey, &dwSize); if (ERROR_SUCCESS != Status) { Log("Failed to create OOBE reg %u %u", LASTERR, Status); goto End; } Status += RegSetValueExA(hSubKey, "BypassNRO", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD)); Log("Create BypassNRO registry %s %u", (Status == ERROR_SUCCESS) ? "SUCCESS" : "FAILED", Status); SetupMonNroStart(isofile); } Ret = 0; End: return Ret; } static BOOL CheckVentoyDisk(DWORD DiskNum) { DWORD dwSize = 0; CHAR PhyPath[128]; UINT8 SectorBuf[512]; HANDLE Handle; UINT8 check[8] = { 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44 }; sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", DiskNum); 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 FALSE; } if (!ReadFile(Handle, SectorBuf, sizeof(SectorBuf), &dwSize, NULL)) { Log("ReadFile failed, dwSize:%u error:%u", dwSize, GetLastError()); CloseHandle(Handle); return FALSE; } CloseHandle(Handle); if (memcmp(SectorBuf + 0x190, check, 8) == 0) { return TRUE; } return FALSE; } static BOOL VentoyIsLenovoRecovery(CHAR *IsoPath, CHAR *VTLRIPath) { int n; int UTF8 = 0; HANDLE hFile; DWORD Attr; WCHAR FilePathW[MAX_PATH]; UTF8 = IsUTF8Encode(IsoPath); if (UTF8) { Utf8ToUtf16(IsoPath, FilePathW); n = (int)wcslen(FilePathW); if (n > 4 && _wcsicmp(FilePathW + n - 4, L".iso") == 0) { FilePathW[n - 3] = L'V'; FilePathW[n - 2] = L'T'; FilePathW[n - 1] = L'L'; FilePathW[n - 0] = L'R'; FilePathW[n + 1] = L'I'; FilePathW[n + 2] = 0; hFile = CreateFileW(FilePathW, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); Attr = GetFileAttributesW(FilePathW); if ((Attr & FILE_ATTRIBUTE_DIRECTORY) == 0) { Utf16ToUtf8(FilePathW, VTLRIPath); return TRUE; } } } } else { n = (int)strlen(IsoPath); if (n > 4 && _stricmp(IsoPath + n - 4, ".iso") == 0) { IsoPath[n - 4] = 0; sprintf_s(VTLRIPath, MAX_PATH, "%s.VTLRI", IsoPath); IsoPath[n - 4] = '.'; if (IsFileExist(VTLRIPath)) { return TRUE; } } } return FALSE; } static int MountVTLRI(CHAR *ImgPath, DWORD PhyDrive) { STARTUPINFOA Si; PROCESS_INFORMATION Pi; CHAR Cmdline[256]; CHAR ImDiskPath[256]; Log("MountVTLRI <%s> %u", ImgPath, PhyDrive); VentoyCopyImdisk(PhyDrive, ImDiskPath); VentoyRunImdisk("VTLRI", ImgPath, ImDiskPath, "ro,rem"); CopyFileA(g_prog_full_path, "ventoy\\VTLRISRV.exe", FALSE); sprintf_s(Cmdline, sizeof(Cmdline), "ventoy\\VTLRISRV.exe VTLRI_SRV %C Z", ImgPath[0]); GetStartupInfoA(&Si); Si.dwFlags |= STARTF_USESHOWWINDOW; Si.wShowWindow = SW_HIDE; CreateProcessA(NULL, Cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi); Log("Process cmdline <%s>", Cmdline); return 0; } static int VentoyHook(ventoy_os_param *param) { int i; int rc; BOOL find = FALSE; BOOL vtoyfind = FALSE; CHAR Letter; CHAR MntLetter; CHAR VtoyLetter; DWORD Drives; DWORD NewDrives; DWORD VtoyDiskNum; UINT32 DiskSig; UINT32 VtoySig; DISK_EXTENT DiskExtent; DISK_EXTENT VtoyDiskExtent; UINT8 UUID[16]; CHAR IsoPath[MAX_PATH]; CHAR VTLRIPath[MAX_PATH]; Log("VentoyHook Path:<%s>", param->vtoy_img_path); if (IsUTF8Encode(param->vtoy_img_path)) { Log("This file is UTF8 encoding"); } for (i = 0; i < 5; i++) { Letter = 'A'; Drives = GetLogicalDrives(); Log("Logic Drives: 0x%x", Drives); while (Drives) { if (Drives & 0x01) { sprintf_s(IsoPath, sizeof(IsoPath), "%C:\\%s", Letter, param->vtoy_img_path); if (IsFileExist("%s", IsoPath)) { Log("File exist under %C:", Letter); memset(UUID, 0, sizeof(UUID)); memset(&DiskExtent, 0, sizeof(DiskExtent)); if (GetPhyDiskUUID(Letter, UUID, NULL, &DiskExtent) == 0) { if (memcmp(UUID, param->vtoy_disk_guid, 16) == 0) { Log("Disk UUID match"); find = TRUE; break; } } } else { Log("File NOT exist under %C:", Letter); } } Drives >>= 1; Letter++; } if (find) { break; } else { Log("Now wait and retry ..."); Sleep(1000); } } if (find == FALSE) { Log("Failed to find ISO file"); return 1; } Log("Find ISO file <%s>", IsoPath); //Find VtoyLetter in Vlnk Mode if (g_os_param_reserved[6] == 1) { memcpy(&VtoySig, g_os_param_reserved + 7, 4); for (i = 0; i < 5; i++) { VtoyLetter = 'A'; Drives = GetLogicalDrives(); Log("Logic Drives: 0x%x VentoySig:%08X", Drives, VtoySig); while (Drives) { if (Drives & 0x01) { memset(UUID, 0, sizeof(UUID)); memset(&VtoyDiskExtent, 0, sizeof(VtoyDiskExtent)); DiskSig = 0; if (GetPhyDiskUUID(VtoyLetter, UUID, &DiskSig, &VtoyDiskExtent) == 0) { Log("DiskSig=%08X PartStart=%lld", DiskSig, VtoyDiskExtent.StartingOffset.QuadPart); if (DiskSig == VtoySig && VtoyDiskExtent.StartingOffset.QuadPart == SIZE_1MB) { Log("Ventoy Disk Sig match"); vtoyfind = TRUE; break; } } } Drives >>= 1; VtoyLetter++; } if (vtoyfind) { Log("Find Ventoy Letter: %C", VtoyLetter); break; } else { Log("Now wait and retry ..."); Sleep(1000); } } if (vtoyfind == FALSE) { Log("Failed to find ventoy disk"); return 1; } VtoyDiskNum = VtoyDiskExtent.DiskNumber; } else { VtoyLetter = Letter; Log("No vlnk mode %C", Letter); VtoyDiskNum = DiskExtent.DiskNumber; } if (CheckVentoyDisk(VtoyDiskNum)) { Log("Disk check OK %C: %u", VtoyLetter, VtoyDiskNum); } else { Log("Failed to check ventoy disk %u", VtoyDiskNum); return 1; } g_vtoy_disk_drive = VtoyDiskNum; Drives = GetLogicalDrives(); Log("Drives before mount: 0x%x", Drives); if (VentoyIsLenovoRecovery(IsoPath, VTLRIPath)) { Log("This is lenovo recovery image, mount VTLRI file."); rc = MountVTLRI(VTLRIPath, VtoyDiskNum); } else { Log("This is normal image, mount ISO file."); rc = MountIsoFile(IsoPath, VtoyDiskNum); } NewDrives = GetLogicalDrives(); Log("Drives after mount: 0x%x (0x%x)", NewDrives, (NewDrives ^ Drives)); MntLetter = 'A'; NewDrives = (NewDrives ^ Drives); while (NewDrives) { if (NewDrives & 0x01) { if ((NewDrives >> 1) == 0) { Log("The ISO file is mounted at %C:", MntLetter); } else { Log("Maybe the ISO file is mounted at %C:", MntLetter); } break; } NewDrives >>= 1; MntLetter++; } Log("Mount ISO FILE: %s", rc == 0 ? "SUCCESS" : "FAILED"); //Windows 11 bypass check if (g_windows_data.windows11_bypass_check == 1 || g_windows_data.windows11_bypass_nro == 1) { Windows11Bypass(IsoPath, MntLetter, g_windows_data.windows11_bypass_check, g_windows_data.windows11_bypass_nro); } // for protect rc = DeleteVentoyPart2MountPoint(VtoyDiskNum); Log("Delete ventoy mountpoint: %s", rc == 0 ? "SUCCESS" : "NO NEED"); if (g_windows_data.auto_install_script[0]) { if (IsFileExist("%s", VTOY_AUTO_FILE)) { Log("use auto install script %s...", VTOY_AUTO_FILE); ProcessUnattendedInstallation(VTOY_AUTO_FILE, VtoyDiskNum); } 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", VtoyLetter, g_windows_data.injection_archive); if (IsFileExist("%s", IsoPath)) { Log("decompress injection archive %s...", IsoPath); DecompressInjectionArchive(IsoPath, VtoyDiskNum); if (IsFileExist("%s", AUTO_RUN_BAT)) { HANDLE hOut; DWORD flags = CREATE_NO_WINDOW; CHAR StrBuf[1024]; STARTUPINFOA Si; PROCESS_INFORMATION Pi; SECURITY_ATTRIBUTES Sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; Log("%s exist, now run it...", AUTO_RUN_BAT); GetStartupInfoA(&Si); hOut = CreateFileA(AUTO_RUN_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; } sprintf_s(IsoPath, sizeof(IsoPath), "%C:\\%s", Letter, param->vtoy_img_path); sprintf_s(StrBuf, sizeof(StrBuf), "cmd.exe /c %s \"%s\" %C", AUTO_RUN_BAT, IsoPath, MntLetter); CreateProcessA(NULL, StrBuf, NULL, NULL, TRUE, flags, NULL, NULL, &Si, &Pi); WaitForSingleObject(Pi.hProcess, INFINITE); SAFE_CLOSE_HANDLE(hOut); } else { Log("%s not exist...", AUTO_RUN_BAT); } } else { Log("injection archive %s not exist", IsoPath); } } else { Log("no injection archive found"); } return 0; } static int ExtractWindowsDataFile(char *databuf) { int len = 0; char *filedata = NULL; ventoy_windows_data *pdata = (ventoy_windows_data *)databuf; Log("ExtractWindowsDataFile: auto install <%s:%d>", pdata->auto_install_script, pdata->auto_install_len); filedata = databuf + sizeof(ventoy_windows_data); if (pdata->auto_install_script[0] && pdata->auto_install_len > 0) { SaveBuffer2File(VTOY_AUTO_FILE, filedata, pdata->auto_install_len); filedata += pdata->auto_install_len; len = pdata->auto_install_len; } return len; } static int ventoy_check_create_directory(void) { if (IsDirExist("ventoy")) { Log("ventoy directory already exist"); } else { Log("ventoy directory not exist, now create it."); if (!CreateDirectoryA("ventoy", NULL)) { Log("Failed to create ventoy directory err:%u", GetLastError()); return 1; } } return 0; } int VentoyJump(INT argc, CHAR **argv, CHAR *LunchFile) { int rc = 1; int stat = 0; int exlen = 0; DWORD Pos; DWORD PeStart; DWORD FileSize; DWORD LockStatus = 0; BYTE *Buffer = NULL; CHAR ExeFileName[MAX_PATH]; sprintf_s(ExeFileName, sizeof(ExeFileName), "%s", argv[0]); if (!IsFileExist("%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, IsFileExist("%s", ExeFileName) ? "YES" : "NO"); } if (ReadWholeFile2Buf(ExeFileName, (void **)&Buffer, &FileSize)) { goto End; } Log("VentoyJump %dbit", g_system_bit); MUTEX_LOCK(g_vtoyins_mutex); stat = ventoy_check_create_directory(); MUTEX_UNLOCK(g_vtoyins_mutex); if (stat != 0) { goto End; } for (PeStart = 0; PeStart < FileSize; PeStart += 16) { if (CheckOsParam((ventoy_os_param *)(Buffer + PeStart)) && CheckPeHead(Buffer, FileSize, PeStart + sizeof(ventoy_os_param))) { 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)); exlen = ExtractWindowsDataFile(Buffer + PeStart + sizeof(ventoy_os_param)); 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) + exlen; sprintf_s(LunchFile, MAX_PATH, "ventoy\\%s", GetFileNameInPath(ExeFileName)); MUTEX_LOCK(g_vtoyins_mutex); if (IsFileExist("%s", LunchFile)) { Log("vtoyjump multiple call ..."); rc = 0; MUTEX_UNLOCK(g_vtoyins_mutex); goto End; } SaveBuffer2File(LunchFile, Buffer + PeStart, FileSize - PeStart); MUTEX_UNLOCK(g_vtoyins_mutex); 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 real_main(int argc, char **argv) { int i = 0; int rc = 0; CHAR NewFile[MAX_PATH]; CHAR LunchFile[MAX_PATH]; CHAR CallParam[1024] = { 0 }; STARTUPINFOA Si; PROCESS_INFORMATION Pi; Log("#### real_main #### argc = %d", argc); Log("program full path: <%s>", g_prog_full_path); Log("program dir: <%s>", g_prog_dir); Log("program name: <%s>", g_prog_name); Log("argc = %d", argc); for (i = 0; i < argc; i++) { Log("argv[%d]=<%s>", i, argv[i]); if (i > 0) { strcat_s(CallParam, sizeof(CallParam), " "); strcat_s(CallParam, sizeof(CallParam), argv[i]); } } GetStartupInfoA(&Si); memset(LunchFile, 0, sizeof(LunchFile)); rc = VentoyJump(argc, argv, LunchFile); Log("LunchFile=<%s> CallParam=<%s>", LunchFile, CallParam); if (_stricmp(g_prog_name, "winpeshl.exe") != 0 && IsFileExist("ventoy\\%s", g_prog_name)) { sprintf_s(NewFile, sizeof(NewFile), "%s\\VTOYJUMP.EXE", g_prog_dir); MoveFileA(g_prog_full_path, NewFile); Log("Move <%s> to <%s>", g_prog_full_path, NewFile); sprintf_s(NewFile, sizeof(NewFile), "ventoy\\%s", g_prog_name); CopyFileA(NewFile, g_prog_full_path, TRUE); Log("Copy <%s> to <%s>", NewFile, g_prog_full_path); sprintf_s(LunchFile, sizeof(LunchFile), "%s", g_prog_full_path); Log("Final lunchFile is <%s>", LunchFile); } else { Log("We don't need to recover original <%s>", g_prog_name); } if (g_os_param_reserved[0] == 3) { Log("Open log for debug ..."); sprintf_s(LunchFile, sizeof(LunchFile), "%s", "notepad.exe ventoy.log"); } else { if (CallParam[0]) { strcat_s(LunchFile, sizeof(LunchFile), CallParam); } else if (NULL == strstr(LunchFile, "setup.exe")) { Log("Not setup.exe, hide windows."); Si.dwFlags |= STARTF_USESHOWWINDOW; Si.wShowWindow = SW_HIDE; } Log("Ventoy jump %s ...", rc == 0 ? "success" : "failed"); } Log("Now launch <%s> ...", LunchFile); if (g_os_param_reserved[0] == 4) { Log("Open cmd for debug ..."); Si.dwFlags |= STARTF_USESHOWWINDOW; Si.wShowWindow = SW_NORMAL; sprintf_s(LunchFile, sizeof(LunchFile), "%s", "cmd.exe"); } Log("Backup log at this point"); CopyFileA(LOG_FILE, "X:\\Windows\\ventoy.backup", TRUE); CreateProcessA(NULL, LunchFile, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi); for (i = 0; rc && i < 1800; i++) { Log("Ventoy hook failed, now wait and retry ..."); Sleep(1000); rc = VentoyHook(&g_os_param); } Log("Wait process..."); WaitForSingleObject(Pi.hProcess, INFINITE); Log("vtoyjump finished"); return 0; } static void VentoyToUpper(CHAR *str) { int i; for (i = 0; str[i]; i++) { str[i] = (CHAR)toupper(str[i]); } } static int vtoy_remove_duplicate_file(char *File) { CHAR szCmd[MAX_PATH]; CHAR NewFile[MAX_PATH]; STARTUPINFOA Si; PROCESS_INFORMATION Pi; Log("<1> Copy New file", File); sprintf_s(NewFile, sizeof(NewFile), "%s_NEW", File); CopyFileA(File, NewFile, FALSE); Log("<2> Remove file <%s>", File); GetStartupInfoA(&Si); Si.dwFlags |= STARTF_USESHOWWINDOW; Si.wShowWindow = SW_HIDE; sprintf_s(szCmd, sizeof(szCmd), "cmd.exe /c del /F /Q %s", File); CreateProcessA(NULL, szCmd, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi); WaitForSingleObject(Pi.hProcess, INFINITE); Log("<3> Copy back file <%s>", File); MoveFileA(NewFile, File); return 0; } static int VTLRI_ServiceMain(int argc, char **argv) { int n = 0; DWORD Err; BOOL bRet = TRUE; CHAR Drive[16]; CHAR FsType[64]; CHAR Cmdline[256]; PROCESS_INFORMATION Pi; STARTUPINFOA Si; //XXX.exe VTLRI_SRV D Z Log("VTLRI_ServiceMain start %s %s %s ...", argv[0], argv[1], argv[2]); sprintf_s(Drive, sizeof(Drive), "%C:\\", argv[2][0]); while (n < 3) { bRet = GetVolumeInformationA(Drive, NULL, 0, NULL, NULL, NULL, FsType, sizeof(FsType)); if (bRet) { Sleep(400); } else { Err = LASTERR; if (Err == ERROR_PATH_NOT_FOUND) { Log("%s not found", Drive); n++; } } } sprintf_s(Cmdline, sizeof(Cmdline), "ventoy\\imdisk.exe -d -m %C:", argv[3][0]); Log("Remove disk by <%s>", Cmdline); GetStartupInfoA(&Si); Si.dwFlags |= STARTF_USESHOWWINDOW; Si.wShowWindow = SW_HIDE; CreateProcessA(NULL, Cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi); WaitForSingleObject(Pi.hProcess, INFINITE); return 0; } int main(int argc, char **argv) { int i; STARTUPINFOA Si; PROCESS_INFORMATION Pi; CHAR CurDir[MAX_PATH]; CHAR NewArgv0[MAX_PATH]; CHAR CallParam[1024] = { 0 }; g_vtoylog_mutex = CreateMutexA(NULL, FALSE, "VTOYLOG_LOCK"); g_vtoyins_mutex = CreateMutexA(NULL, FALSE, "VTOYINS_LOCK"); Log("######## VentoyJump %dbit ##########", g_system_bit); if (argc > 1 && strcmp(argv[1], "VTLRI_SRV") == 0) { return VTLRI_ServiceMain(argc, argv); } GetCurrentDirectoryA(sizeof(CurDir), CurDir); Log("Current directory is <%s>", CurDir); GetModuleFileNameA(NULL, g_prog_full_path, MAX_PATH); split_path_name(g_prog_full_path, g_prog_dir, g_prog_name); Log("EXE path: <%s> dir:<%s> name:<%s>", g_prog_full_path, g_prog_dir, g_prog_name); if (IsFileExist(WIMBOOT_FILE)) { Log("This is wimboot mode ..."); g_wimboot_mode = TRUE; if (!IsFileExist(WIMBOOT_DONE)) { vtoy_remove_duplicate_file(g_prog_full_path); SaveBuffer2File(WIMBOOT_DONE, g_prog_full_path, 1); } } else { Log("This is normal mode ..."); } if (_stricmp(g_prog_name, "WinLogon.exe") == 0) { Log("This time is rejump back ..."); strcpy_s(g_prog_full_path, sizeof(g_prog_full_path), argv[1]); split_path_name(g_prog_full_path, g_prog_dir, g_prog_name); return real_main(argc - 1, argv + 1); } else if (_stricmp(g_prog_name, "PECMD.exe") == 0) { strcpy_s(NewArgv0, sizeof(NewArgv0), g_prog_dir); VentoyToUpper(NewArgv0); if (NULL == strstr(NewArgv0, "SYSTEM32") && IsFileExist(ORG_PECMD_BK_PATH)) { Log("Just call original pecmd.exe"); strcpy_s(CallParam, sizeof(CallParam), ORG_PECMD_PATH); } else { Log("We need to rejump for pecmd ..."); ventoy_check_create_directory(); CopyFileA(g_prog_full_path, "ventoy\\WinLogon.exe", TRUE); sprintf_s(CallParam, sizeof(CallParam), "ventoy\\WinLogon.exe %s", g_prog_full_path); } for (i = 1; i < argc; i++) { strcat_s(CallParam, sizeof(CallParam), " "); strcat_s(CallParam, sizeof(CallParam), argv[i]); } Log("Now rejump to <%s> ...", CallParam); GetStartupInfoA(&Si); CreateProcessA(NULL, CallParam, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi); Log("Wait rejump process..."); WaitForSingleObject(Pi.hProcess, INFINITE); Log("rejump finished"); return 0; } else { Log("We don't need to rejump ..."); ventoy_check_create_directory(); strcpy_s(NewArgv0, sizeof(NewArgv0), g_prog_full_path); argv[0] = NewArgv0; return real_main(argc, argv); } }