]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - vtoyjump/vtoyjump/vtoyjump.c
update vtoyjump
[Ventoy.git] / vtoyjump / vtoyjump / vtoyjump.c
1 /******************************************************************************
2 * vtoyjump.c
3 *
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 *
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <Windows.h>
25 #include <virtdisk.h>
26 #include <winioctl.h>
27 #include <VersionHelpers.h>
28 #include "vtoyjump.h"
29 #include "fat_filelib.h"
30
31 static ventoy_os_param g_os_param;
32 static ventoy_windows_data g_windows_data;
33 static UINT8 g_os_param_reserved[32];
34 static INT g_system_bit = VTOY_BIT;
35 static ventoy_guid g_ventoy_guid = VENTOY_GUID;
36 static HANDLE g_vtoylog_mutex = NULL;
37 static HANDLE g_vtoyins_mutex = NULL;
38
39 static BOOL g_wimboot_mode = FALSE;
40
41 static DWORD g_vtoy_disk_drive;
42
43 static CHAR g_prog_full_path[MAX_PATH];
44 static CHAR g_prog_dir[MAX_PATH];
45 static CHAR g_prog_name[MAX_PATH];
46
47 #define VTOY_PECMD_PATH "X:\\Windows\\system32\\ventoy\\PECMD.EXE"
48 #define ORG_PECMD_PATH "X:\\Windows\\system32\\PECMD.EXE"
49 #define ORG_PECMD_BK_PATH "X:\\Windows\\system32\\PECMD.EXE_BACK.EXE"
50
51 #define WIMBOOT_FILE "X:\\Windows\\system32\\vtoy_wimboot"
52 #define WIMBOOT_DONE "X:\\Windows\\system32\\vtoy_wimboot_done"
53
54 #define AUTO_RUN_BAT "X:\\VentoyAutoRun.bat"
55 #define AUTO_RUN_LOG "X:\\VentoyAutoRun.log"
56
57 #define VTOY_AUTO_FILE "X:\\_vtoy_auto_install"
58
59 #define LOG_FILE "X:\\Windows\\system32\\ventoy.log"
60 #define MUTEX_LOCK(hmutex) if (hmutex != NULL) LockStatus = WaitForSingleObject(hmutex, INFINITE)
61 #define MUTEX_UNLOCK(hmutex) if (hmutex != NULL && WAIT_OBJECT_0 == LockStatus) ReleaseMutex(hmutex)
62
63 static const char * GetFileNameInPath(const char *fullpath)
64 {
65 int i;
66
67 if (strstr(fullpath, ":"))
68 {
69 for (i = (int)strlen(fullpath); i > 0; i--)
70 {
71 if (fullpath[i - 1] == '/' || fullpath[i - 1] == '\\')
72 {
73 return fullpath + i;
74 }
75 }
76 }
77
78 return fullpath;
79 }
80
81 static int split_path_name(char *fullpath, char *dir, char *name)
82 {
83 CHAR ch;
84 CHAR *Pos = NULL;
85
86 Pos = (CHAR *)GetFileNameInPath(fullpath);
87
88 strcpy_s(name, MAX_PATH, Pos);
89
90 ch = *(Pos - 1);
91 *(Pos - 1) = 0;
92 strcpy_s(dir, MAX_PATH, fullpath);
93 *(Pos - 1) = ch;
94
95 return 0;
96 }
97
98 static void TrimString(CHAR *String, BOOL TrimLeft)
99 {
100 CHAR *Pos1 = String;
101 CHAR *Pos2 = String;
102 size_t Len = strlen(String);
103
104 while (Len > 0)
105 {
106 if (String[Len - 1] != ' ' && String[Len - 1] != '\t')
107 {
108 break;
109 }
110 String[Len - 1] = 0;
111 Len--;
112 }
113
114 if (TrimLeft)
115 {
116 while (*Pos1 == ' ' || *Pos1 == '\t')
117 {
118 Pos1++;
119 }
120
121 while (*Pos1)
122 {
123 *Pos2++ = *Pos1++;
124 }
125 *Pos2++ = 0;
126 }
127
128 return;
129 }
130
131 void Log(const char *Fmt, ...)
132 {
133 va_list Arg;
134 int Len = 0;
135 FILE *File = NULL;
136 SYSTEMTIME Sys;
137 char szBuf[1024];
138 DWORD LockStatus = 0;
139 DWORD PID = GetCurrentProcessId();
140
141 GetLocalTime(&Sys);
142 Len += sprintf_s(szBuf, sizeof(szBuf),
143 "[%4d/%02d/%02d %02d:%02d:%02d.%03d] [%u] ",
144 Sys.wYear, Sys.wMonth, Sys.wDay,
145 Sys.wHour, Sys.wMinute, Sys.wSecond,
146 Sys.wMilliseconds, PID);
147
148 va_start(Arg, Fmt);
149 Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len, sizeof(szBuf)-Len, Fmt, Arg);
150 va_end(Arg);
151
152 MUTEX_LOCK(g_vtoylog_mutex);
153
154 fopen_s(&File, LOG_FILE, "a+");
155 if (File)
156 {
157 fwrite(szBuf, 1, Len, File);
158 fwrite("\n", 1, 1, File);
159 fclose(File);
160 }
161
162 MUTEX_UNLOCK(g_vtoylog_mutex);
163 }
164
165
166 static int LoadNtDriver(const char *DrvBinPath)
167 {
168 int i;
169 int rc = 0;
170 BOOL Ret;
171 DWORD Status;
172 SC_HANDLE hServiceMgr;
173 SC_HANDLE hService;
174 char name[256] = { 0 };
175
176 for (i = (int)strlen(DrvBinPath) - 1; i >= 0; i--)
177 {
178 if (DrvBinPath[i] == '\\' || DrvBinPath[i] == '/')
179 {
180 sprintf_s(name, sizeof(name), "%s", DrvBinPath + i + 1);
181 break;
182 }
183 }
184
185 Log("Load NT driver: %s %s", DrvBinPath, name);
186
187 hServiceMgr = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
188 if (hServiceMgr == NULL)
189 {
190 Log("OpenSCManager failed Error:%u", GetLastError());
191 return 1;
192 }
193
194 Log("OpenSCManager OK");
195
196 hService = CreateServiceA(hServiceMgr,
197 name,
198 name,
199 SERVICE_ALL_ACCESS,
200 SERVICE_KERNEL_DRIVER,
201 SERVICE_DEMAND_START,
202 SERVICE_ERROR_NORMAL,
203 DrvBinPath,
204 NULL, NULL, NULL, NULL, NULL);
205 if (hService == NULL)
206 {
207 Status = GetLastError();
208 if (Status != ERROR_IO_PENDING && Status != ERROR_SERVICE_EXISTS)
209 {
210 Log("CreateService failed v %u", Status);
211 CloseServiceHandle(hServiceMgr);
212 return 1;
213 }
214
215 hService = OpenServiceA(hServiceMgr, name, SERVICE_ALL_ACCESS);
216 if (hService == NULL)
217 {
218 Log("OpenService failed %u", Status);
219 CloseServiceHandle(hServiceMgr);
220 return 1;
221 }
222 }
223
224 Log("CreateService imdisk OK");
225
226 Ret = StartServiceA(hService, 0, NULL);
227 if (Ret)
228 {
229 Log("StartService OK");
230 }
231 else
232 {
233 Status = GetLastError();
234 if (Status == ERROR_SERVICE_ALREADY_RUNNING)
235 {
236 rc = 0;
237 }
238 else
239 {
240 Log("StartService error %u", Status);
241 rc = 1;
242 }
243 }
244
245 CloseServiceHandle(hService);
246 CloseServiceHandle(hServiceMgr);
247
248 Log("Load NT driver %s", rc ? "failed" : "success");
249
250 return rc;
251 }
252
253 static int ReadWholeFile2Buf(const char *Fullpath, void **Data, DWORD *Size)
254 {
255 int rc = 1;
256 DWORD FileSize;
257 DWORD dwSize;
258 HANDLE Handle;
259 BYTE *Buffer = NULL;
260
261 Log("ReadWholeFile2Buf <%s>", Fullpath);
262
263 Handle = CreateFileA(Fullpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
264 if (Handle == INVALID_HANDLE_VALUE)
265 {
266 Log("Could not open the file<%s>, error:%u", Fullpath, GetLastError());
267 goto End;
268 }
269
270 FileSize = SetFilePointer(Handle, 0, NULL, FILE_END);
271
272 Buffer = malloc(FileSize);
273 if (!Buffer)
274 {
275 Log("Failed to alloc memory size:%u", FileSize);
276 goto End;
277 }
278
279 SetFilePointer(Handle, 0, NULL, FILE_BEGIN);
280 if (!ReadFile(Handle, Buffer, FileSize, &dwSize, NULL))
281 {
282 Log("ReadFile failed, dwSize:%u error:%u", dwSize, GetLastError());
283 goto End;
284 }
285
286 *Data = Buffer;
287 *Size = FileSize;
288
289 Log("Success read file size:%u", FileSize);
290
291 rc = 0;
292
293 End:
294 SAFE_CLOSE_HANDLE(Handle);
295
296 return rc;
297 }
298
299 static BOOL CheckPeHead(BYTE *Buffer, DWORD Size, DWORD Offset)
300 {
301 UINT32 PeOffset;
302 BYTE *Head = NULL;
303 DWORD End;
304 ventoy_windows_data *pdata = NULL;
305
306 Head = Buffer + Offset;
307 pdata = (ventoy_windows_data *)Head;
308 Head += sizeof(ventoy_windows_data);
309
310 if (pdata->auto_install_script[0] && pdata->auto_install_len > 0)
311 {
312 End = Offset + sizeof(ventoy_windows_data) + pdata->auto_install_len + 60;
313 if (End < Size)
314 {
315 Head += pdata->auto_install_len;
316 }
317 }
318
319 if (Head[0] != 'M' || Head[1] != 'Z')
320 {
321 return FALSE;
322 }
323
324 PeOffset = *(UINT32 *)(Head + 60);
325 if (*(UINT32 *)(Head + PeOffset) != 0x00004550)
326 {
327 return FALSE;
328 }
329
330 return TRUE;
331 }
332
333
334 static BOOL CheckOsParam(ventoy_os_param *param)
335 {
336 UINT32 i;
337 BYTE Sum = 0;
338
339 if (memcmp(&param->guid, &g_ventoy_guid, sizeof(ventoy_guid)))
340 {
341 return FALSE;
342 }
343
344 for (i = 0; i < sizeof(ventoy_os_param); i++)
345 {
346 Sum += *((BYTE *)param + i);
347 }
348
349 if (Sum)
350 {
351 return FALSE;
352 }
353
354 if (param->vtoy_img_location_addr % 4096)
355 {
356 return FALSE;
357 }
358
359 return TRUE;
360 }
361
362 static int SaveBuffer2File(const char *Fullpath, void *Buffer, DWORD Length)
363 {
364 int rc = 1;
365 DWORD dwSize;
366 HANDLE Handle;
367
368 Log("SaveBuffer2File <%s> len:%u", Fullpath, Length);
369
370 Handle = CreateFileA(Fullpath, GENERIC_READ | GENERIC_WRITE,
371 FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, 0, 0);
372 if (Handle == INVALID_HANDLE_VALUE)
373 {
374 Log("Could not create new file, error:%u", GetLastError());
375 goto End;
376 }
377
378 WriteFile(Handle, Buffer, Length, &dwSize, NULL);
379
380 rc = 0;
381
382 End:
383 SAFE_CLOSE_HANDLE(Handle);
384
385 return rc;
386 }
387
388 static int IsUTF8Encode(const char *src)
389 {
390 int i;
391 const UCHAR *Byte = (const UCHAR *)src;
392
393 for (i = 0; i < MAX_PATH && Byte[i]; i++)
394 {
395 if (Byte[i] > 127)
396 {
397 return 1;
398 }
399 }
400
401 return 0;
402 }
403
404 static int Utf8ToUtf16(const char* src, WCHAR * dst)
405 {
406 int size = MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, 0);
407 return MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size + 1);
408 }
409
410 static BOOL IsDirExist(const char *Fmt, ...)
411 {
412 va_list Arg;
413 DWORD Attr;
414 int UTF8 = 0;
415 CHAR FilePathA[MAX_PATH];
416 WCHAR FilePathW[MAX_PATH];
417
418 va_start(Arg, Fmt);
419 vsnprintf_s(FilePathA, sizeof(FilePathA), sizeof(FilePathA), Fmt, Arg);
420 va_end(Arg);
421
422 UTF8 = IsUTF8Encode(FilePathA);
423
424 if (UTF8)
425 {
426 Utf8ToUtf16(FilePathA, FilePathW);
427 Attr = GetFileAttributesW(FilePathW);
428 }
429 else
430 {
431 Attr = GetFileAttributesA(FilePathA);
432 }
433
434 if (Attr != INVALID_FILE_ATTRIBUTES && (Attr & FILE_ATTRIBUTE_DIRECTORY))
435 {
436 return TRUE;
437 }
438
439 return FALSE;
440 }
441
442 static BOOL IsFileExist(const char *Fmt, ...)
443 {
444 va_list Arg;
445 HANDLE hFile;
446 DWORD Attr;
447 BOOL bRet = FALSE;
448 int UTF8 = 0;
449 CHAR FilePathA[MAX_PATH];
450 WCHAR FilePathW[MAX_PATH];
451
452 va_start(Arg, Fmt);
453 vsnprintf_s(FilePathA, sizeof(FilePathA), sizeof(FilePathA), Fmt, Arg);
454 va_end(Arg);
455
456 UTF8 = IsUTF8Encode(FilePathA);
457
458 if (UTF8)
459 {
460 Utf8ToUtf16(FilePathA, FilePathW);
461 hFile = CreateFileW(FilePathW, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
462 }
463 else
464 {
465 hFile = CreateFileA(FilePathA, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
466 }
467 if (INVALID_HANDLE_VALUE == hFile)
468 {
469 goto out;
470 }
471
472 CloseHandle(hFile);
473
474 if (UTF8)
475 {
476 Attr = GetFileAttributesW(FilePathW);
477 }
478 else
479 {
480 Attr = GetFileAttributesA(FilePathA);
481 }
482
483 if (Attr & FILE_ATTRIBUTE_DIRECTORY)
484 {
485 goto out;
486 }
487
488 bRet = TRUE;
489
490 out:
491 Log("File <%s> %s", FilePathA, (bRet ? "exist" : "NOT exist"));
492 return bRet;
493 }
494
495 static int GetPhyDiskUUID(const char LogicalDrive, UINT8 *UUID, UINT32 *DiskSig, DISK_EXTENT *DiskExtent)
496 {
497 BOOL Ret;
498 DWORD dwSize;
499 HANDLE Handle;
500 VOLUME_DISK_EXTENTS DiskExtents;
501 CHAR PhyPath[128];
502 UINT8 SectorBuf[512];
503
504 Log("GetPhyDiskUUID %C", LogicalDrive);
505
506 sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\%C:", LogicalDrive);
507 Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
508 if (Handle == INVALID_HANDLE_VALUE)
509 {
510 Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
511 return 1;
512 }
513
514 Ret = DeviceIoControl(Handle,
515 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
516 NULL,
517 0,
518 &DiskExtents,
519 (DWORD)(sizeof(DiskExtents)),
520 (LPDWORD)&dwSize,
521 NULL);
522 if (!Ret || DiskExtents.NumberOfDiskExtents == 0)
523 {
524 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed, error:%u", GetLastError());
525 CloseHandle(Handle);
526 return 1;
527 }
528 CloseHandle(Handle);
529
530 memcpy(DiskExtent, DiskExtents.Extents, sizeof(DISK_EXTENT));
531 Log("%C: is in PhysicalDrive%d Offset:%llu", LogicalDrive, DiskExtents.Extents[0].DiskNumber,
532 (ULONGLONG)(DiskExtents.Extents[0].StartingOffset.QuadPart));
533
534 sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", DiskExtents.Extents[0].DiskNumber);
535 Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
536 if (Handle == INVALID_HANDLE_VALUE)
537 {
538 Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
539 return 1;
540 }
541
542 if (!ReadFile(Handle, SectorBuf, sizeof(SectorBuf), &dwSize, NULL))
543 {
544 Log("ReadFile failed, dwSize:%u error:%u", dwSize, GetLastError());
545 CloseHandle(Handle);
546 return 1;
547 }
548
549 memcpy(UUID, SectorBuf + 0x180, 16);
550 if (DiskSig)
551 {
552 memcpy(DiskSig, SectorBuf + 0x1B8, 4);
553 }
554
555 CloseHandle(Handle);
556 return 0;
557 }
558
559 static int VentoyMountAnywhere(HANDLE Handle)
560 {
561 DWORD Status;
562 ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters;
563
564 Log("VentoyMountAnywhere");
565
566 memset(&AttachParameters, 0, sizeof(AttachParameters));
567 AttachParameters.Version = ATTACH_VIRTUAL_DISK_VERSION_1;
568
569 Status = AttachVirtualDisk(Handle, NULL, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY | ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME, 0, &AttachParameters, NULL);
570 if (Status != ERROR_SUCCESS)
571 {
572 Log("Failed to attach virtual disk ErrorCode:%u", Status);
573 return 1;
574 }
575
576 return 0;
577 }
578
579 int VentoyMountY(HANDLE Handle)
580 {
581 int i;
582 BOOL bRet = FALSE;
583 DWORD Status;
584 DWORD physicalDriveNameSize;
585 CHAR *Pos = NULL;
586 WCHAR physicalDriveName[MAX_PATH];
587 CHAR physicalDriveNameA[MAX_PATH];
588 CHAR cdromDriveName[MAX_PATH];
589 ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters;
590
591 Log("VentoyMountY");
592
593 memset(&AttachParameters, 0, sizeof(AttachParameters));
594 AttachParameters.Version = ATTACH_VIRTUAL_DISK_VERSION_1;
595
596 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);
597 if (Status != ERROR_SUCCESS)
598 {
599 Log("Failed to attach virtual disk ErrorCode:%u", Status);
600 return 1;
601 }
602
603 memset(physicalDriveName, 0, sizeof(physicalDriveName));
604 memset(physicalDriveNameA, 0, sizeof(physicalDriveNameA));
605
606 physicalDriveNameSize = MAX_PATH;
607 Status = GetVirtualDiskPhysicalPath(Handle, &physicalDriveNameSize, physicalDriveName);
608 if (Status != ERROR_SUCCESS)
609 {
610 Log("Failed GetVirtualDiskPhysicalPath ErrorCode:%u", Status);
611 return 1;
612 }
613
614 for (i = 0; physicalDriveName[i]; i++)
615 {
616 physicalDriveNameA[i] = (CHAR)toupper((CHAR)(physicalDriveName[i]));
617 }
618
619 Log("physicalDriveNameA=<%s>", physicalDriveNameA);
620
621 Pos = strstr(physicalDriveNameA, "CDROM");
622 if (!Pos)
623 {
624 Log("Not cdrom phy drive");
625 return 1;
626 }
627
628 sprintf_s(cdromDriveName, sizeof(cdromDriveName), "\\Device\\%s", Pos);
629 Log("cdromDriveName=<%s>", cdromDriveName);
630
631 for (i = 0; i < 3 && (bRet == FALSE); i++)
632 {
633 Sleep(1000);
634 bRet = DefineDosDeviceA(DDD_RAW_TARGET_PATH, "Y:", cdromDriveName);
635 Log("DefineDosDeviceA %s", bRet ? "success" : "failed");
636 }
637
638 return bRet ? 0 : 1;
639 }
640
641 static BOOL VentoyAPINeedMountY(const char *IsoPath)
642 {
643 (void)IsoPath;
644
645 /* TBD */
646 return FALSE;
647 }
648
649 static int VentoyAttachVirtualDisk(HANDLE Handle, const char *IsoPath)
650 {
651 int DriveYFree;
652 DWORD Drives;
653
654 Drives = GetLogicalDrives();
655 if ((1 << 24) & Drives)
656 {
657 Log("Y: is occupied");
658 DriveYFree = 0;
659 }
660 else
661 {
662 Log("Y: is free now");
663 DriveYFree = 1;
664 }
665
666 if (DriveYFree && VentoyAPINeedMountY(IsoPath))
667 {
668 return VentoyMountY(Handle);
669 }
670 else
671 {
672 return VentoyMountAnywhere(Handle);
673 }
674 }
675
676 int VentoyMountISOByAPI(const char *IsoPath)
677 {
678 int i;
679 HANDLE Handle;
680 DWORD Status;
681 WCHAR wFilePath[512] = { 0 };
682 VIRTUAL_STORAGE_TYPE StorageType;
683 OPEN_VIRTUAL_DISK_PARAMETERS OpenParameters;
684
685 Log("VentoyMountISOByAPI <%s>", IsoPath);
686
687 if (IsUTF8Encode(IsoPath))
688 {
689 Log("This is UTF8 encoding");
690 MultiByteToWideChar(CP_UTF8, 0, IsoPath, (int)strlen(IsoPath), wFilePath, (int)(sizeof(wFilePath) / sizeof(WCHAR)));
691 }
692 else
693 {
694 Log("This is ANSI encoding");
695 MultiByteToWideChar(CP_ACP, 0, IsoPath, (int)strlen(IsoPath), wFilePath, (int)(sizeof(wFilePath) / sizeof(WCHAR)));
696 }
697
698 memset(&StorageType, 0, sizeof(StorageType));
699 memset(&OpenParameters, 0, sizeof(OpenParameters));
700
701 OpenParameters.Version = OPEN_VIRTUAL_DISK_VERSION_1;
702
703 for (i = 0; i < 10; i++)
704 {
705 Status = OpenVirtualDisk(&StorageType, wFilePath, VIRTUAL_DISK_ACCESS_READ, 0, &OpenParameters, &Handle);
706 if (ERROR_FILE_NOT_FOUND == Status || ERROR_PATH_NOT_FOUND == Status)
707 {
708 Log("OpenVirtualDisk ErrorCode:%u, now wait and retry...", Status);
709 Sleep(1000);
710 }
711 else
712 {
713 if (ERROR_SUCCESS == Status)
714 {
715 Log("OpenVirtualDisk success");
716 }
717 else if (ERROR_VIRTDISK_PROVIDER_NOT_FOUND == Status)
718 {
719 Log("VirtualDisk for ISO file is not supported in current system");
720 }
721 else
722 {
723 Log("Failed to open virtual disk ErrorCode:%u", Status);
724 }
725 break;
726 }
727 }
728
729 if (Status != ERROR_SUCCESS)
730 {
731 return 1;
732 }
733
734 Log("OpenVirtualDisk success");
735
736 Status = VentoyAttachVirtualDisk(Handle, IsoPath);
737 if (Status != ERROR_SUCCESS)
738 {
739 Log("Failed to attach virtual disk ErrorCode:%u", Status);
740 CloseHandle(Handle);
741 return 1;
742 }
743
744 Log("VentoyAttachVirtualDisk success");
745
746 CloseHandle(Handle);
747 return 0;
748 }
749
750
751 static HANDLE g_FatPhyDrive;
752 static UINT64 g_Part2StartSec;
753
754 static int CopyFileFromFatDisk(const CHAR* SrcFile, const CHAR *DstFile)
755 {
756 int rc = 1;
757 int size = 0;
758 char *buf = NULL;
759 void *flfile = NULL;
760
761 Log("CopyFileFromFatDisk (%s)==>(%s)", SrcFile, DstFile);
762
763 flfile = fl_fopen(SrcFile, "rb");
764 if (flfile)
765 {
766 fl_fseek(flfile, 0, SEEK_END);
767 size = (int)fl_ftell(flfile);
768 fl_fseek(flfile, 0, SEEK_SET);
769
770 buf = (char *)malloc(size);
771 if (buf)
772 {
773 fl_fread(buf, 1, size, flfile);
774
775 rc = 0;
776 SaveBuffer2File(DstFile, buf, size);
777 free(buf);
778 }
779
780 fl_fclose(flfile);
781 }
782
783 return rc;
784 }
785
786 static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
787 {
788 DWORD dwSize;
789 BOOL bRet;
790 DWORD ReadSize;
791 LARGE_INTEGER liCurrentPosition;
792
793 liCurrentPosition.QuadPart = Sector + g_Part2StartSec;
794 liCurrentPosition.QuadPart *= 512;
795 SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
796
797 ReadSize = (DWORD)(SectorCount * 512);
798
799 bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL);
800 if (bRet == FALSE || dwSize != ReadSize)
801 {
802 Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u", bRet, ReadSize, dwSize, GetLastError());
803 }
804
805 return 1;
806 }
807
808 static BOOL Is2K10PE(void)
809 {
810 BOOL bRet = FALSE;
811 FILE *fp = NULL;
812 CHAR szLine[1024];
813
814 fopen_s(&fp, "X:\\Windows\\System32\\PECMD.INI", "r");
815 if (!fp)
816 {
817 return FALSE;
818 }
819
820 memset(szLine, 0, sizeof(szLine));
821 while (fgets(szLine, sizeof(szLine) - 1, fp))
822 {
823 if (strstr(szLine, "2k10\\"))
824 {
825 bRet = TRUE;
826 break;
827 }
828 }
829
830 fclose(fp);
831 return bRet;
832 }
833
834 static CHAR GetIMDiskMountLogicalDrive(void)
835 {
836 CHAR Letter = 'Y';
837 DWORD Drives;
838 DWORD Mask = 0x1000000;
839
840 // fixed use M as mountpoint for 2K10 PE
841 if (Is2K10PE())
842 {
843 Log("Use M: for 2K10 PE");
844 return 'M';
845 }
846
847 Drives = GetLogicalDrives();
848 Log("Drives=0x%x", Drives);
849
850 while (Mask)
851 {
852 if ((Drives & Mask) == 0)
853 {
854 break;
855 }
856
857 Letter--;
858 Mask >>= 1;
859 }
860
861 return Letter;
862 }
863
864 UINT64 GetVentoyEfiPartStartSector(HANDLE hDrive)
865 {
866 BOOL bRet;
867 DWORD dwSize;
868 MBR_HEAD MBR;
869 VTOY_GPT_INFO *pGpt = NULL;
870 UINT64 StartSector = 0;
871
872 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
873
874 bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);
875 Log("Read MBR Ret:%u Size:%u code:%u", bRet, dwSize, LASTERR);
876
877 if ((!bRet) || (dwSize != sizeof(MBR)))
878 {
879 0;
880 }
881
882 if (MBR.PartTbl[0].FsFlag == 0xEE)
883 {
884 Log("GPT partition style");
885
886 pGpt = malloc(sizeof(VTOY_GPT_INFO));
887 if (!pGpt)
888 {
889 return 0;
890 }
891
892 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
893 bRet = ReadFile(hDrive, pGpt, sizeof(VTOY_GPT_INFO), &dwSize, NULL);
894 if ((!bRet) || (dwSize != sizeof(VTOY_GPT_INFO)))
895 {
896 Log("Failed to read gpt info %d %u %d", bRet, dwSize, LASTERR);
897 return 0;
898 }
899
900 StartSector = pGpt->PartTbl[1].StartLBA;
901 free(pGpt);
902 }
903 else
904 {
905 Log("MBR partition style");
906 StartSector = MBR.PartTbl[1].StartSectorId;
907 }
908
909 Log("GetVentoyEfiPart StartSector: %llu", StartSector);
910 return StartSector;
911 }
912
913 static int VentoyRunImdisk(const char *IsoPath, const char *imdiskexe)
914 {
915 CHAR Letter;
916 CHAR Cmdline[512];
917 WCHAR CmdlineW[512];
918 PROCESS_INFORMATION Pi;
919
920 Log("VentoyRunImdisk <%s> <%s>", IsoPath, imdiskexe);
921
922 Letter = GetIMDiskMountLogicalDrive();
923 sprintf_s(Cmdline, sizeof(Cmdline), "%s -a -o ro -f \"%s\" -m %C:", imdiskexe, IsoPath, Letter);
924 Log("mount iso to %C: use imdisk cmd <%s>", Letter, Cmdline);
925
926 if (IsUTF8Encode(IsoPath))
927 {
928 STARTUPINFOW Si;
929 GetStartupInfoW(&Si);
930 Si.dwFlags |= STARTF_USESHOWWINDOW;
931 Si.wShowWindow = SW_HIDE;
932
933 Utf8ToUtf16(Cmdline, CmdlineW);
934 CreateProcessW(NULL, CmdlineW, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
935
936 Log("This is UTF8 encoding");
937 }
938 else
939 {
940 STARTUPINFOA Si;
941 GetStartupInfoA(&Si);
942 Si.dwFlags |= STARTF_USESHOWWINDOW;
943 Si.wShowWindow = SW_HIDE;
944
945 CreateProcessA(NULL, Cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
946
947 Log("This is ANSI encoding");
948 }
949
950 Log("Wait for imdisk process ...");
951 WaitForSingleObject(Pi.hProcess, INFINITE);
952 Log("imdisk process finished");
953
954 return 0;
955 }
956
957 int VentoyMountISOByImdisk(const char *IsoPath, DWORD PhyDrive)
958 {
959 int rc = 1;
960 BOOL bRet;
961 DWORD dwBytes;
962 HANDLE hDrive;
963 CHAR PhyPath[MAX_PATH];
964 GET_LENGTH_INFORMATION LengthInfo;
965
966 Log("VentoyMountISOByImdisk %s", IsoPath);
967
968 if (IsFileExist("X:\\Windows\\System32\\imdisk.exe"))
969 {
970 Log("imdisk.exe exist, use it directly...");
971 VentoyRunImdisk(IsoPath, "imdisk.exe");
972 return 0;
973 }
974
975 sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", PhyDrive);
976 hDrive = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
977 if (hDrive == INVALID_HANDLE_VALUE)
978 {
979 Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
980 goto End;
981 }
982
983 bRet = DeviceIoControl(hDrive, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &LengthInfo, sizeof(LengthInfo), &dwBytes, NULL);
984 if (!bRet)
985 {
986 Log("Could not get phy disk %s size, error:%u", PhyPath, GetLastError());
987 goto End;
988 }
989
990 g_FatPhyDrive = hDrive;
991 g_Part2StartSec = GetVentoyEfiPartStartSector(hDrive);
992
993 Log("Parse FAT fs...");
994
995 fl_init();
996
997 if (0 == fl_attach_media(VentoyFatDiskRead, NULL))
998 {
999 if (g_system_bit == 64)
1000 {
1001 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.sys", "ventoy\\imdisk.sys");
1002 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.exe", "ventoy\\imdisk.exe");
1003 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.cpl", "ventoy\\imdisk.cpl");
1004 }
1005 else
1006 {
1007 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.sys", "ventoy\\imdisk.sys");
1008 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.exe", "ventoy\\imdisk.exe");
1009 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.cpl", "ventoy\\imdisk.cpl");
1010 }
1011
1012 GetCurrentDirectoryA(sizeof(PhyPath), PhyPath);
1013 strcat_s(PhyPath, sizeof(PhyPath), "\\ventoy\\imdisk.sys");
1014
1015 if (LoadNtDriver(PhyPath) == 0)
1016 {
1017 VentoyRunImdisk(IsoPath, "ventoy\\imdisk.exe");
1018 rc = 0;
1019 }
1020 }
1021 fl_shutdown();
1022
1023 End:
1024
1025 SAFE_CLOSE_HANDLE(hDrive);
1026
1027 return rc;
1028 }
1029
1030 static int GetIsoId(CONST CHAR *IsoPath, IsoId *ids)
1031 {
1032 int i;
1033 int n = 0;
1034 HANDLE hFile;
1035 DWORD dwSize = 0;
1036 BOOL bRet[8];
1037
1038 hFile = CreateFileA(IsoPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
1039 if (hFile == INVALID_HANDLE_VALUE)
1040 {
1041 return 1;
1042 }
1043
1044 SetFilePointer(hFile, 2048 * 16 + 8, NULL, FILE_BEGIN);
1045 bRet[n++] = ReadFile(hFile, ids->SystemId, 32, &dwSize, NULL);
1046
1047 SetFilePointer(hFile, 2048 * 16 + 40, NULL, FILE_BEGIN);
1048 bRet[n++] = ReadFile(hFile, ids->VolumeId, 32, &dwSize, NULL);
1049
1050 SetFilePointer(hFile, 2048 * 16 + 318, NULL, FILE_BEGIN);
1051 bRet[n++] = ReadFile(hFile, ids->PulisherId, 128, &dwSize, NULL);
1052
1053 SetFilePointer(hFile, 2048 * 16 + 446, NULL, FILE_BEGIN);
1054 bRet[n++] = ReadFile(hFile, ids->PreparerId, 128, &dwSize, NULL);
1055
1056 CloseHandle(hFile);
1057
1058
1059 for (i = 0; i < n; i++)
1060 {
1061 if (bRet[i] == FALSE)
1062 {
1063 return 1;
1064 }
1065 }
1066
1067
1068 TrimString(ids->SystemId, FALSE);
1069 TrimString(ids->VolumeId, FALSE);
1070 TrimString(ids->PulisherId, FALSE);
1071 TrimString(ids->PreparerId, FALSE);
1072
1073 Log("ISO ID: System<%s> Volume<%s> Pulisher<%s> Preparer<%s>",
1074 ids->SystemId, ids->VolumeId, ids->PulisherId, ids->PreparerId);
1075
1076 return 0;
1077 }
1078
1079 static int CheckSkipMountIso(CONST CHAR *IsoPath)
1080 {
1081 BOOL InRoot = FALSE;
1082 int slashcnt = 0;
1083 CONST CHAR *p = NULL;
1084 IsoId ID;
1085
1086 // C:\\xxx
1087 for (p = IsoPath; *p; p++)
1088 {
1089 if (*p == '\\' || *p == '/')
1090 {
1091 slashcnt++;
1092 }
1093 }
1094
1095 if (slashcnt == 2)
1096 {
1097 InRoot = TRUE;
1098 }
1099
1100 memset(&ID, 0, sizeof(ID));
1101 if (GetIsoId(IsoPath, &ID))
1102 {
1103 return 0;
1104 }
1105
1106 //Bob.Ombs.Modified.Win10PEx64.iso will auto find ISO file in root, so we can skip the mount
1107 if (InRoot && strcmp(ID.VolumeId, "Modified-Win10PEx64") == 0)
1108 {
1109 return 1;
1110 }
1111
1112 return 0;
1113 }
1114
1115 static int MountIsoFile(CONST CHAR *IsoPath, DWORD PhyDrive)
1116 {
1117 if (CheckSkipMountIso(IsoPath))
1118 {
1119 Log("Skip mount ISO file for <%s>", IsoPath);
1120 return 0;
1121 }
1122
1123 if (IsWindows8OrGreater())
1124 {
1125 Log("This is Windows 8 or latter...");
1126 if (VentoyMountISOByAPI(IsoPath) == 0)
1127 {
1128 Log("Mount iso by API success");
1129 return 0;
1130 }
1131 else
1132 {
1133 Log("Mount iso by API failed, maybe not supported, try imdisk");
1134 return VentoyMountISOByImdisk(IsoPath, PhyDrive);
1135 }
1136 }
1137 else
1138 {
1139 Log("This is before Windows 8 ...");
1140 if (VentoyMountISOByImdisk(IsoPath, PhyDrive) == 0)
1141 {
1142 Log("Mount iso by imdisk success");
1143 return 0;
1144 }
1145 else
1146 {
1147 return VentoyMountISOByAPI(IsoPath);
1148 }
1149 }
1150 }
1151
1152 static int GetPhyDriveByLogicalDrive(int DriveLetter)
1153 {
1154 BOOL Ret;
1155 DWORD dwSize;
1156 HANDLE Handle;
1157 VOLUME_DISK_EXTENTS DiskExtents;
1158 CHAR PhyPath[128];
1159
1160 sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\%C:", (CHAR)DriveLetter);
1161
1162 Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
1163 if (Handle == INVALID_HANDLE_VALUE)
1164 {
1165 Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
1166 return -1;
1167 }
1168
1169 Ret = DeviceIoControl(Handle,
1170 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
1171 NULL,
1172 0,
1173 &DiskExtents,
1174 (DWORD)(sizeof(DiskExtents)),
1175 (LPDWORD)&dwSize,
1176 NULL);
1177
1178 if (!Ret || DiskExtents.NumberOfDiskExtents == 0)
1179 {
1180 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath, GetLastError());
1181 SAFE_CLOSE_HANDLE(Handle);
1182 return -1;
1183 }
1184 SAFE_CLOSE_HANDLE(Handle);
1185
1186 Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",
1187 PhyPath,
1188 DiskExtents.Extents[0].DiskNumber,
1189 DiskExtents.Extents[0].StartingOffset.QuadPart,
1190 DiskExtents.Extents[0].ExtentLength.QuadPart
1191 );
1192
1193 return (int)DiskExtents.Extents[0].DiskNumber;
1194 }
1195
1196
1197 static int DeleteVentoyPart2MountPoint(DWORD PhyDrive)
1198 {
1199 CHAR Letter = 'A';
1200 DWORD Drives;
1201 DWORD PhyDisk;
1202 CHAR DriveName[] = "?:\\";
1203
1204 Log("DeleteVentoyPart2MountPoint Phy%u ...", PhyDrive);
1205
1206 Drives = GetLogicalDrives();
1207 while (Drives)
1208 {
1209 if ((Drives & 0x01) && IsFileExist("%C:\\ventoy\\ventoy.cpio", Letter))
1210 {
1211 Log("File %C:\\ventoy\\ventoy.cpio exist", Letter);
1212
1213 PhyDisk = GetPhyDriveByLogicalDrive(Letter);
1214 Log("PhyDisk=%u for %C", PhyDisk, Letter);
1215
1216 if (PhyDisk == PhyDrive)
1217 {
1218 DriveName[0] = Letter;
1219 DeleteVolumeMountPointA(DriveName);
1220 return 0;
1221 }
1222 }
1223
1224 Letter++;
1225 Drives >>= 1;
1226 }
1227
1228 return 1;
1229 }
1230
1231 static BOOL check_tar_archive(const char *archive, CHAR *tarName)
1232 {
1233 int len;
1234 int nameLen;
1235 const char *pos = archive;
1236 const char *slash = archive;
1237
1238 while (*pos)
1239 {
1240 if (*pos == '\\' || *pos == '/')
1241 {
1242 slash = pos;
1243 }
1244 pos++;
1245 }
1246
1247 len = (int)strlen(slash);
1248
1249 if (len > 7 && (strncmp(slash + len - 7, ".tar.gz", 7) == 0 || strncmp(slash + len - 7, ".tar.xz", 7) == 0))
1250 {
1251 nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);
1252 tarName[nameLen - 3] = 0;
1253 return TRUE;
1254 }
1255 else if (len > 8 && strncmp(slash + len - 8, ".tar.bz2", 8) == 0)
1256 {
1257 nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);
1258 tarName[nameLen - 4] = 0;
1259 return TRUE;
1260 }
1261 else if (len > 9 && strncmp(slash + len - 9, ".tar.lzma", 9) == 0)
1262 {
1263 nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);
1264 tarName[nameLen - 5] = 0;
1265 return TRUE;
1266 }
1267
1268 return FALSE;
1269 }
1270
1271 static UCHAR *g_unxz_buffer = NULL;
1272 static int g_unxz_len = 0;
1273
1274 static void unxz_error(char *x)
1275 {
1276 Log("%s", x);
1277 }
1278
1279 static int unxz_flush(void *src, unsigned int size)
1280 {
1281 memcpy(g_unxz_buffer + g_unxz_len, src, size);
1282 g_unxz_len += (int)size;
1283
1284 return (int)size;
1285 }
1286
1287 static int DecompressInjectionArchive(const char *archive, DWORD PhyDrive)
1288 {
1289 int rc = 1;
1290 int writelen = 0;
1291 UCHAR *Buffer = NULL;
1292 UCHAR *RawBuffer = NULL;
1293 BOOL bRet;
1294 DWORD dwBytes;
1295 DWORD dwSize;
1296 HANDLE hDrive;
1297 HANDLE hOut;
1298 DWORD flags = CREATE_NO_WINDOW;
1299 CHAR StrBuf[MAX_PATH];
1300 CHAR tarName[MAX_PATH];
1301 STARTUPINFOA Si;
1302 PROCESS_INFORMATION Pi;
1303 PROCESS_INFORMATION NewPi;
1304 GET_LENGTH_INFORMATION LengthInfo;
1305 SECURITY_ATTRIBUTES Sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
1306
1307 Log("DecompressInjectionArchive %s", archive);
1308
1309 sprintf_s(StrBuf, sizeof(StrBuf), "\\\\.\\PhysicalDrive%d", PhyDrive);
1310 hDrive = CreateFileA(StrBuf, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
1311 if (hDrive == INVALID_HANDLE_VALUE)
1312 {
1313 Log("Could not open the disk<%s>, error:%u", StrBuf, GetLastError());
1314 goto End;
1315 }
1316
1317 bRet = DeviceIoControl(hDrive, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &LengthInfo, sizeof(LengthInfo), &dwBytes, NULL);
1318 if (!bRet)
1319 {
1320 Log("Could not get phy disk %s size, error:%u", StrBuf, GetLastError());
1321 goto End;
1322 }
1323
1324 g_FatPhyDrive = hDrive;
1325 g_Part2StartSec = GetVentoyEfiPartStartSector(hDrive);
1326
1327 Log("Parse FAT fs...");
1328
1329 fl_init();
1330
1331 if (0 == fl_attach_media(VentoyFatDiskRead, NULL))
1332 {
1333 if (g_system_bit == 64)
1334 {
1335 CopyFileFromFatDisk("/ventoy/7z/64/7za.xz", "ventoy\\7za.xz");
1336 }
1337 else
1338 {
1339 CopyFileFromFatDisk("/ventoy/7z/32/7za.xz", "ventoy\\7za.xz");
1340 }
1341
1342 ReadWholeFile2Buf("ventoy\\7za.xz", &Buffer, &dwSize);
1343 Log("7za.xz file size:%u", dwSize);
1344
1345 RawBuffer = malloc(SIZE_1MB * 4);
1346 if (RawBuffer)
1347 {
1348 g_unxz_buffer = RawBuffer;
1349 g_unxz_len = 0;
1350 unxz(Buffer, (int)dwSize, NULL, unxz_flush, NULL, &writelen, unxz_error);
1351 if (writelen == (int)dwSize)
1352 {
1353 Log("Decompress success 7za.xz(%u) ---> 7za.exe(%d)", dwSize, g_unxz_len);
1354 }
1355 else
1356 {
1357 Log("Decompress failed 7za.xz(%u) ---> 7za.exe(%u)", dwSize, dwSize);
1358 }
1359
1360 SaveBuffer2File("ventoy\\7za.exe", RawBuffer, (DWORD)g_unxz_len);
1361
1362 g_unxz_buffer = NULL;
1363 g_unxz_len = 0;
1364 free(RawBuffer);
1365 }
1366 else
1367 {
1368 Log("Failed to alloc 4MB memory");
1369 }
1370
1371 sprintf_s(StrBuf, sizeof(StrBuf), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", archive);
1372
1373 Log("extract inject to X:");
1374 Log("cmdline:<%s>", StrBuf);
1375
1376 GetStartupInfoA(&Si);
1377
1378 hOut = CreateFileA("ventoy\\7z.log",
1379 FILE_APPEND_DATA,
1380 FILE_SHARE_WRITE | FILE_SHARE_READ,
1381 &Sa,
1382 OPEN_ALWAYS,
1383 FILE_ATTRIBUTE_NORMAL,
1384 NULL);
1385
1386 Si.dwFlags |= STARTF_USESTDHANDLES;
1387
1388 if (hOut != INVALID_HANDLE_VALUE)
1389 {
1390 Si.hStdError = hOut;
1391 Si.hStdOutput = hOut;
1392 }
1393
1394 CreateProcessA(NULL, StrBuf, NULL, NULL, TRUE, flags, NULL, NULL, &Si, &Pi);
1395 WaitForSingleObject(Pi.hProcess, INFINITE);
1396
1397 //
1398 // decompress tar archive, for tar.gz/tar.xz/tar.bz2
1399 //
1400 if (check_tar_archive(archive, tarName))
1401 {
1402 Log("Decompress tar archive...<%s>", tarName);
1403
1404 sprintf_s(StrBuf, sizeof(StrBuf), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", tarName);
1405
1406 CreateProcessA(NULL, StrBuf, NULL, NULL, TRUE, flags, NULL, NULL, &Si, &NewPi);
1407 WaitForSingleObject(NewPi.hProcess, INFINITE);
1408
1409 Log("Now delete %s", tarName);
1410 DeleteFileA(tarName);
1411 }
1412
1413 SAFE_CLOSE_HANDLE(hOut);
1414 }
1415 fl_shutdown();
1416
1417 End:
1418
1419 SAFE_CLOSE_HANDLE(hDrive);
1420
1421 return rc;
1422 }
1423
1424 static int UnattendNeedVarExpand(const char *script)
1425 {
1426 FILE *fp = NULL;
1427 char szLine[4096];
1428
1429 fopen_s(&fp, script, "r");
1430 if (!fp)
1431 {
1432 return 0;
1433 }
1434
1435 szLine[0] = szLine[4095] = 0;
1436
1437 while (fgets(szLine, sizeof(szLine) - 1, fp))
1438 {
1439 if (strstr(szLine, "$$VT_"))
1440 {
1441 fclose(fp);
1442 return 1;
1443 }
1444
1445 szLine[0] = szLine[4095] = 0;
1446 }
1447
1448 fclose(fp);
1449 return 0;
1450 }
1451
1452 static int ExpandSingleVar(VarDiskInfo *pDiskInfo, int DiskNum, const char *var, char *value, int len)
1453 {
1454 int i;
1455 int index = -1;
1456 UINT64 uiDst = 0;
1457 UINT64 uiDelta = 0;
1458 UINT64 uiMaxSize = 0;
1459 UINT64 uiMaxDelta = ULLONG_MAX;
1460
1461 value[0] = 0;
1462
1463 if (strcmp(var, "VT_WINDOWS_DISK_1ST_NONVTOY") == 0)
1464 {
1465 for (i = 0; i < DiskNum; i++)
1466 {
1467 if (pDiskInfo[i].Capacity > 0 && i != g_vtoy_disk_drive)
1468 {
1469 Log("%s=<PhyDrive%d>", var, i);
1470 sprintf_s(value, len, "%d", i);
1471 return 0;
1472 }
1473 }
1474 }
1475 else if (strcmp(var, "VT_WINDOWS_DISK_1ST_NONUSB") == 0)
1476 {
1477 for (i = 0; i < DiskNum; i++)
1478 {
1479 if (pDiskInfo[i].Capacity > 0 && pDiskInfo[i].BusType != BusTypeUsb)
1480 {
1481 Log("%s=<PhyDrive%d>", var, i);
1482 sprintf_s(value, len, "%d", i);
1483 return 0;
1484 }
1485 }
1486 }
1487 else if (strcmp(var, "VT_WINDOWS_DISK_MAX_SIZE") == 0)
1488 {
1489 for (i = 0; i < DiskNum; i++)
1490 {
1491 if (pDiskInfo[i].Capacity > 0 && pDiskInfo[i].Capacity > uiMaxSize)
1492 {
1493 index = i;
1494 uiMaxSize = pDiskInfo[i].Capacity;
1495 }
1496 }
1497
1498 Log("%s=<PhyDrive%d>", var, index);
1499 sprintf_s(value, len, "%d", index);
1500 }
1501 else if (strncmp(var, "VT_WINDOWS_DISK_CLOSEST_", 24) == 0)
1502 {
1503 uiDst = strtoul(var + 24, NULL, 10);
1504 uiDst = uiDst * (1024ULL * 1024ULL * 1024ULL);
1505
1506 for (i = 0; i < DiskNum; i++)
1507 {
1508 if (pDiskInfo[i].Capacity == 0)
1509 {
1510 continue;
1511 }
1512
1513 if (pDiskInfo[i].Capacity > uiDst)
1514 {
1515 uiDelta = pDiskInfo[i].Capacity - uiDst;
1516 }
1517 else
1518 {
1519 uiDelta = uiDst - pDiskInfo[i].Capacity;
1520 }
1521
1522 if (uiDelta < uiMaxDelta)
1523 {
1524 uiMaxDelta = uiDelta;
1525 index = i;
1526 }
1527 }
1528
1529 Log("%s=<PhyDrive%d>", var, index);
1530 sprintf_s(value, len, "%d", index);
1531 }
1532 else
1533 {
1534 Log("Invalid var name <%s>", var);
1535 sprintf_s(value, len, "$$%s$$", var);
1536 }
1537
1538 if (value[0] == 0)
1539 {
1540 sprintf_s(value, len, "$$%s$$", var);
1541 }
1542
1543 return 0;
1544 }
1545
1546 static int GetRegDwordValue(HKEY Key, LPCSTR SubKey, LPCSTR ValueName, DWORD *pValue)
1547 {
1548 HKEY hKey;
1549 DWORD Type;
1550 DWORD Size;
1551 LSTATUS lRet;
1552 DWORD Value;
1553
1554 lRet = RegOpenKeyExA(Key, SubKey, 0, KEY_QUERY_VALUE, &hKey);
1555 Log("RegOpenKeyExA <%s> Ret:%ld", SubKey, lRet);
1556
1557 if (ERROR_SUCCESS == lRet)
1558 {
1559 Size = sizeof(Value);
1560 lRet = RegQueryValueExA(hKey, ValueName, NULL, &Type, (LPBYTE)&Value, &Size);
1561 Log("RegQueryValueExA <%s> ret:%u Size:%u Value:%u", ValueName, lRet, Size, Value);
1562
1563 *pValue = Value;
1564 RegCloseKey(hKey);
1565
1566 return 0;
1567 }
1568 else
1569 {
1570 return 1;
1571 }
1572 }
1573
1574 static const CHAR * GetBusTypeString(int Type)
1575 {
1576 switch (Type)
1577 {
1578 case BusTypeUnknown: return "unknown";
1579 case BusTypeScsi: return "SCSI";
1580 case BusTypeAtapi: return "Atapi";
1581 case BusTypeAta: return "ATA";
1582 case BusType1394: return "1394";
1583 case BusTypeSsa: return "SSA";
1584 case BusTypeFibre: return "Fibre";
1585 case BusTypeUsb: return "USB";
1586 case BusTypeRAID: return "RAID";
1587 case BusTypeiScsi: return "iSCSI";
1588 case BusTypeSas: return "SAS";
1589 case BusTypeSata: return "SATA";
1590 case BusTypeSd: return "SD";
1591 case BusTypeMmc: return "MMC";
1592 case BusTypeVirtual: return "Virtual";
1593 case BusTypeFileBackedVirtual: return "FileBackedVirtual";
1594 case BusTypeSpaces: return "Spaces";
1595 case BusTypeNvme: return "Nvme";
1596 }
1597 return "unknown";
1598 }
1599
1600 static int GetHumanReadableGBSize(UINT64 SizeBytes)
1601 {
1602 int i;
1603 int Pow2 = 1;
1604 double Delta;
1605 double GB = SizeBytes * 1.0 / 1000 / 1000 / 1000;
1606
1607 if ((SizeBytes % 1073741824) == 0)
1608 {
1609 return (int)(SizeBytes / 1073741824);
1610 }
1611
1612 for (i = 0; i < 12; i++)
1613 {
1614 if (Pow2 > GB)
1615 {
1616 Delta = (Pow2 - GB) / Pow2;
1617 }
1618 else
1619 {
1620 Delta = (GB - Pow2) / Pow2;
1621 }
1622
1623 if (Delta < 0.05)
1624 {
1625 return Pow2;
1626 }
1627
1628 Pow2 <<= 1;
1629 }
1630
1631 return (int)GB;
1632 }
1633
1634 static int EnumerateAllDisk(VarDiskInfo **ppDiskInfo, int *pDiskNum)
1635 {
1636 int i;
1637 DWORD Value;
1638 int DiskNum = 0;
1639 BOOL bRet;
1640 DWORD dwBytes;
1641 VarDiskInfo *pDiskInfo = NULL;
1642 HANDLE Handle = INVALID_HANDLE_VALUE;
1643 CHAR PhyDrive[128];
1644 GET_LENGTH_INFORMATION LengthInfo;
1645 STORAGE_PROPERTY_QUERY Query;
1646 STORAGE_DESCRIPTOR_HEADER DevDescHeader;
1647 STORAGE_DEVICE_DESCRIPTOR *pDevDesc;
1648
1649 if (GetRegDwordValue(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\disk\\Enum", "Count", &Value) == 0)
1650 {
1651 DiskNum = (int)Value;
1652 }
1653 else
1654 {
1655 Log("Failed to read disk count");
1656 return 1;
1657 }
1658
1659 Log("Current phy disk count:%d", DiskNum);
1660 if (DiskNum <= 0)
1661 {
1662 return 1;
1663 }
1664
1665 pDiskInfo = malloc(DiskNum * sizeof(VarDiskInfo));
1666 if (!pDiskInfo)
1667 {
1668 Log("Failed to alloc");
1669 return 1;
1670 }
1671 memset(pDiskInfo, 0, DiskNum * sizeof(VarDiskInfo));
1672
1673 for (i = 0; i < DiskNum; i++)
1674 {
1675 SAFE_CLOSE_HANDLE(Handle);
1676
1677 safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", i);
1678 Handle = CreateFileA(PhyDrive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
1679 Log("Create file Handle:%p %s status:%u", Handle, PhyDrive, LASTERR);
1680
1681 if (Handle == INVALID_HANDLE_VALUE)
1682 {
1683 continue;
1684 }
1685
1686 bRet = DeviceIoControl(Handle,
1687 IOCTL_DISK_GET_LENGTH_INFO, NULL,
1688 0,
1689 &LengthInfo,
1690 sizeof(LengthInfo),
1691 &dwBytes,
1692 NULL);
1693 if (!bRet)
1694 {
1695 Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR);
1696 continue;
1697 }
1698
1699 Log("PHYSICALDRIVE%d size %llu bytes", i, (ULONGLONG)LengthInfo.Length.QuadPart);
1700
1701 Query.PropertyId = StorageDeviceProperty;
1702 Query.QueryType = PropertyStandardQuery;
1703
1704 bRet = DeviceIoControl(Handle,
1705 IOCTL_STORAGE_QUERY_PROPERTY,
1706 &Query,
1707 sizeof(Query),
1708 &DevDescHeader,
1709 sizeof(STORAGE_DESCRIPTOR_HEADER),
1710 &dwBytes,
1711 NULL);
1712 if (!bRet)
1713 {
1714 Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR, dwBytes);
1715 continue;
1716 }
1717
1718 if (DevDescHeader.Size < sizeof(STORAGE_DEVICE_DESCRIPTOR))
1719 {
1720 Log("Invalid DevDescHeader.Size:%u", DevDescHeader.Size);
1721 continue;
1722 }
1723
1724 pDevDesc = (STORAGE_DEVICE_DESCRIPTOR *)malloc(DevDescHeader.Size);
1725 if (!pDevDesc)
1726 {
1727 Log("failed to malloc error:%u len:%u", LASTERR, DevDescHeader.Size);
1728 continue;
1729 }
1730
1731 bRet = DeviceIoControl(Handle,
1732 IOCTL_STORAGE_QUERY_PROPERTY,
1733 &Query,
1734 sizeof(Query),
1735 pDevDesc,
1736 DevDescHeader.Size,
1737 &dwBytes,
1738 NULL);
1739 if (!bRet)
1740 {
1741 Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR, dwBytes);
1742 free(pDevDesc);
1743 continue;
1744 }
1745
1746 pDiskInfo[i].RemovableMedia = pDevDesc->RemovableMedia;
1747 pDiskInfo[i].BusType = pDevDesc->BusType;
1748 pDiskInfo[i].DeviceType = pDevDesc->DeviceType;
1749 pDiskInfo[i].Capacity = LengthInfo.Length.QuadPart;
1750
1751 if (pDevDesc->VendorIdOffset)
1752 {
1753 safe_strcpy(pDiskInfo[i].VendorId, (char *)pDevDesc + pDevDesc->VendorIdOffset);
1754 TrimString(pDiskInfo[i].VendorId, TRUE);
1755 }
1756
1757 if (pDevDesc->ProductIdOffset)
1758 {
1759 safe_strcpy(pDiskInfo[i].ProductId, (char *)pDevDesc + pDevDesc->ProductIdOffset);
1760 TrimString(pDiskInfo[i].ProductId, TRUE);
1761 }
1762
1763 if (pDevDesc->ProductRevisionOffset)
1764 {
1765 safe_strcpy(pDiskInfo[i].ProductRev, (char *)pDevDesc + pDevDesc->ProductRevisionOffset);
1766 TrimString(pDiskInfo[i].ProductRev, TRUE);
1767 }
1768
1769 if (pDevDesc->SerialNumberOffset)
1770 {
1771 safe_strcpy(pDiskInfo[i].SerialNumber, (char *)pDevDesc + pDevDesc->SerialNumberOffset);
1772 TrimString(pDiskInfo[i].SerialNumber, TRUE);
1773 }
1774
1775 free(pDevDesc);
1776 SAFE_CLOSE_HANDLE(Handle);
1777 }
1778
1779 Log("########## DUMP DISK BEGIN ##########");
1780 for (i = 0; i < DiskNum; i++)
1781 {
1782 Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s",
1783 i, GetBusTypeString(pDiskInfo[i].BusType), pDiskInfo[i].RemovableMedia,
1784 GetHumanReadableGBSize(pDiskInfo[i].Capacity), pDiskInfo[i].Capacity,
1785 pDiskInfo[i].VendorId, pDiskInfo[i].ProductId);
1786 }
1787 Log("Ventoy disk is PhyDvr%d", g_vtoy_disk_drive);
1788 Log("########## DUMP DISK END ##########");
1789
1790 *ppDiskInfo = pDiskInfo;
1791 *pDiskNum = DiskNum;
1792 return 0;
1793 }
1794
1795 static int UnattendVarExpand(const char *script, const char *tmpfile)
1796 {
1797 FILE *fp = NULL;
1798 FILE *fout = NULL;
1799 char *start = NULL;
1800 char *end = NULL;
1801 char szLine[4096];
1802 char szValue[256];
1803 int DiskNum = 0;
1804 VarDiskInfo *pDiskInfo = NULL;
1805
1806 Log("UnattendVarExpand ...");
1807
1808 if (EnumerateAllDisk(&pDiskInfo, &DiskNum))
1809 {
1810 Log("Failed to EnumerateAllDisk");
1811 return 1;
1812 }
1813
1814 fopen_s(&fp, script, "r");
1815 if (!fp)
1816 {
1817 free(pDiskInfo);
1818 return 0;
1819 }
1820
1821 fopen_s(&fout, tmpfile, "w+");
1822 if (!fout)
1823 {
1824 fclose(fp);
1825 free(pDiskInfo);
1826 return 0;
1827 }
1828
1829 szLine[0] = szLine[4095] = 0;
1830
1831 while (fgets(szLine, sizeof(szLine) - 1, fp))
1832 {
1833 start = strstr(szLine, "$$VT_");
1834 if (start)
1835 {
1836 end = strstr(start + 5, "$$");
1837 }
1838
1839 if (start && end)
1840 {
1841 *start = 0;
1842 fprintf(fout, "%s", szLine);
1843
1844 *end = 0;
1845 ExpandSingleVar(pDiskInfo, DiskNum, start + 2, szValue, sizeof(szValue) - 1);
1846 fprintf(fout, "%s", szValue);
1847
1848 fprintf(fout, "%s", end + 2);
1849 }
1850 else
1851 {
1852 fprintf(fout, "%s", szLine);
1853 }
1854
1855 szLine[0] = szLine[4095] = 0;
1856 }
1857
1858 fclose(fp);
1859 fclose(fout);
1860 free(pDiskInfo);
1861 return 0;
1862 }
1863
1864 //#define VAR_DEBUG 1
1865
1866 static int ProcessUnattendedInstallation(const char *script)
1867 {
1868 DWORD dw;
1869 HKEY hKey;
1870 LSTATUS Ret;
1871 CHAR Letter;
1872 CHAR TmpFile[MAX_PATH];
1873 CHAR CurDir[MAX_PATH];
1874
1875 Log("Copy unattended XML ...");
1876
1877 GetCurrentDirectory(sizeof(CurDir), CurDir);
1878 Letter = CurDir[0];
1879 if ((Letter >= 'A' && Letter <= 'Z') || (Letter >= 'a' && Letter <= 'z'))
1880 {
1881 Log("Current Drive Letter: %C", Letter);
1882 }
1883 else
1884 {
1885 Letter = 'X';
1886 }
1887
1888 #ifdef VAR_DEBUG
1889 sprintf_s(CurDir, sizeof(CurDir), "%C:\\AutounattendXXX.xml", Letter);
1890 #else
1891 sprintf_s(CurDir, sizeof(CurDir), "%C:\\Autounattend.xml", Letter);
1892 #endif
1893
1894 if (UnattendNeedVarExpand(script))
1895 {
1896 sprintf_s(TmpFile, sizeof(TmpFile), "%C:\\__Autounattend", Letter);
1897 UnattendVarExpand(script, TmpFile);
1898
1899 Log("Expand Copy file <%s> --> <%s>", script, CurDir);
1900 CopyFile(TmpFile, CurDir, FALSE);
1901 }
1902 else
1903 {
1904 Log("No var expand copy file <%s> --> <%s>", script, CurDir);
1905 CopyFile(script, CurDir, FALSE);
1906 }
1907
1908 #ifndef VAR_DEBUG
1909 Ret = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "System\\Setup", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dw);
1910 if (ERROR_SUCCESS == Ret)
1911 {
1912 Ret = RegSetValueEx(hKey, "UnattendFile", 0, REG_SZ, CurDir, (DWORD)(strlen(CurDir) + 1));
1913 }
1914 #endif
1915
1916 return 0;
1917 }
1918
1919 static int Windows11BypassCheck(const char *isofile, const char MntLetter)
1920 {
1921 int Ret = 1;
1922 DWORD dwHandle;
1923 DWORD dwSize;
1924 DWORD dwValue = 1;
1925 UINT VerLen = 0;
1926 CHAR *Buffer = NULL;
1927 VS_FIXEDFILEINFO* VerInfo = NULL;
1928 CHAR CheckFile[MAX_PATH];
1929 UINT16 Major, Minor, Build, Revision;
1930
1931 Log("Windows11BypassCheck for <%s> %C:", isofile, MntLetter);
1932
1933 if (FALSE == IsFileExist("%C:\\sources\\boot.wim", MntLetter) ||
1934 FALSE == IsFileExist("%C:\\sources\\compatresources.dll", MntLetter))
1935 {
1936 Log("boot.wim/compatresources.dll not exist, this is not a windows install media.");
1937 goto End;
1938 }
1939
1940 if (FALSE == IsFileExist("%C:\\sources\\install.wim", MntLetter) &&
1941 FALSE == IsFileExist("%C:\\sources\\install.esd", MntLetter))
1942 {
1943 Log("install.wim/install.esd not exist, this is not a windows install media.");
1944 goto End;
1945 }
1946
1947 sprintf_s(CheckFile, sizeof(CheckFile), "%C:\\sources\\compatresources.dll", MntLetter);
1948 dwSize = GetFileVersionInfoSizeA(CheckFile, &dwHandle);
1949 if (0 == dwSize)
1950 {
1951 Log("Failed to get file version info size: %u", LASTERR);
1952 goto End;
1953 }
1954
1955 Buffer = malloc(dwSize);
1956 if (!Buffer)
1957 {
1958 goto End;
1959 }
1960
1961 if (FALSE == GetFileVersionInfoA(CheckFile, dwHandle, dwSize, Buffer))
1962 {
1963 Log("Failed to get file version info : %u", LASTERR);
1964 goto End;
1965 }
1966
1967 if (VerQueryValueA(Buffer, "\\", (LPVOID)&VerInfo, &VerLen) && VerLen != 0)
1968 {
1969 if (VerInfo->dwSignature == VS_FFI_SIGNATURE)
1970 {
1971 Major = HIWORD(VerInfo->dwFileVersionMS);
1972 Minor = LOWORD(VerInfo->dwFileVersionMS);
1973 Build = HIWORD(VerInfo->dwFileVersionLS);
1974 Revision = LOWORD(VerInfo->dwFileVersionLS);
1975
1976 Log("FileVersionze: <%u %u %u %u>", Major, Minor, Build, Revision);
1977
1978 if (Major == 10 && Build > 20000)
1979 {
1980 Major = 11;
1981 }
1982
1983 if (Major != 11)
1984 {
1985 Log("This is not Windows 11, not need to bypass.", Major);
1986 goto End;
1987 }
1988 }
1989 }
1990
1991 //Now we really need to bypass windows 11 check. create registry
1992 HKEY hKey = NULL;
1993 HKEY hSubKey = NULL;
1994 LSTATUS Status;
1995
1996 Status = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "System\\Setup", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwSize);
1997 if (ERROR_SUCCESS != Status)
1998 {
1999 Log("Failed to create reg key System\\Setup %u %u", LASTERR, Status);
2000 goto End;
2001 }
2002
2003 Status = RegCreateKeyExA(hKey, "LabConfig", 0, NULL, 0, KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_CREATE_SUB_KEY, NULL, &hSubKey, &dwSize);
2004 if (ERROR_SUCCESS != Status)
2005 {
2006 Log("Failed to create LabConfig reg %u %u", LASTERR, Status);
2007 goto End;
2008 }
2009
2010 //set reg value
2011 Status += RegSetValueExA(hSubKey, "BypassRAMCheck", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));
2012 Status += RegSetValueExA(hSubKey, "BypassTPMCheck", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));
2013 Status += RegSetValueExA(hSubKey, "BypassSecureBootCheck", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));
2014 Status += RegSetValueExA(hSubKey, "BypassStorageCheck", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));
2015 Status += RegSetValueExA(hSubKey, "BypassCPUCheck", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));
2016
2017 Log("Create bypass registry %s %u", (Status == ERROR_SUCCESS) ? "SUCCESS" : "FAILED", Status);
2018
2019 Ret = 0;
2020
2021 End:
2022 if (Buffer)
2023 {
2024 free(Buffer);
2025 }
2026
2027 return Ret;
2028 }
2029
2030 static BOOL CheckVentoyDisk(DWORD DiskNum)
2031 {
2032 DWORD dwSize = 0;
2033 CHAR PhyPath[128];
2034 UINT8 SectorBuf[512];
2035 HANDLE Handle;
2036 UINT8 check[8] = { 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44 };
2037
2038 sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", DiskNum);
2039 Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
2040 if (Handle == INVALID_HANDLE_VALUE)
2041 {
2042 Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
2043 return FALSE;
2044 }
2045
2046 if (!ReadFile(Handle, SectorBuf, sizeof(SectorBuf), &dwSize, NULL))
2047 {
2048 Log("ReadFile failed, dwSize:%u error:%u", dwSize, GetLastError());
2049 CloseHandle(Handle);
2050 return FALSE;
2051 }
2052
2053 CloseHandle(Handle);
2054
2055 if (memcmp(SectorBuf + 0x190, check, 8) == 0)
2056 {
2057 return TRUE;
2058 }
2059
2060 return FALSE;
2061 }
2062
2063
2064 static int VentoyHook(ventoy_os_param *param)
2065 {
2066 int i;
2067 int rc;
2068 BOOL find = FALSE;
2069 BOOL vtoyfind = FALSE;
2070 CHAR Letter;
2071 CHAR MntLetter;
2072 CHAR VtoyLetter;
2073 DWORD Drives;
2074 DWORD NewDrives;
2075 DWORD VtoyDiskNum;
2076 UINT32 DiskSig;
2077 UINT32 VtoySig;
2078 DISK_EXTENT DiskExtent;
2079 DISK_EXTENT VtoyDiskExtent;
2080 UINT8 UUID[16];
2081 CHAR IsoPath[MAX_PATH];
2082
2083 Log("VentoyHook Path:<%s>", param->vtoy_img_path);
2084
2085 if (IsUTF8Encode(param->vtoy_img_path))
2086 {
2087 Log("This file is UTF8 encoding");
2088 }
2089
2090 for (i = 0; i < 5; i++)
2091 {
2092 Letter = 'A';
2093 Drives = GetLogicalDrives();
2094 Log("Logic Drives: 0x%x", Drives);
2095
2096 while (Drives)
2097 {
2098 if (Drives & 0x01)
2099 {
2100 sprintf_s(IsoPath, sizeof(IsoPath), "%C:\\%s", Letter, param->vtoy_img_path);
2101 if (IsFileExist("%s", IsoPath))
2102 {
2103 Log("File exist under %C:", Letter);
2104 memset(UUID, 0, sizeof(UUID));
2105 memset(&DiskExtent, 0, sizeof(DiskExtent));
2106 if (GetPhyDiskUUID(Letter, UUID, NULL, &DiskExtent) == 0)
2107 {
2108 if (memcmp(UUID, param->vtoy_disk_guid, 16) == 0)
2109 {
2110 Log("Disk UUID match");
2111 find = TRUE;
2112 break;
2113 }
2114 }
2115 }
2116 else
2117 {
2118 Log("File NOT exist under %C:", Letter);
2119 }
2120 }
2121
2122 Drives >>= 1;
2123 Letter++;
2124 }
2125
2126 if (find)
2127 {
2128 break;
2129 }
2130 else
2131 {
2132 Log("Now wait and retry ...");
2133 Sleep(1000);
2134 }
2135 }
2136
2137 if (find == FALSE)
2138 {
2139 Log("Failed to find ISO file");
2140 return 1;
2141 }
2142
2143 Log("Find ISO file <%s>", IsoPath);
2144
2145 //Find VtoyLetter in Vlnk Mode
2146 if (g_os_param_reserved[6] == 1)
2147 {
2148 memcpy(&VtoySig, g_os_param_reserved + 7, 4);
2149 for (i = 0; i < 5; i++)
2150 {
2151 VtoyLetter = 'A';
2152 Drives = GetLogicalDrives();
2153 Log("Logic Drives: 0x%x VentoySig:%08X", Drives, VtoySig);
2154
2155 while (Drives)
2156 {
2157 if (Drives & 0x01)
2158 {
2159 memset(UUID, 0, sizeof(UUID));
2160 memset(&VtoyDiskExtent, 0, sizeof(VtoyDiskExtent));
2161 DiskSig = 0;
2162 if (GetPhyDiskUUID(VtoyLetter, UUID, &DiskSig, &VtoyDiskExtent) == 0)
2163 {
2164 Log("DiskSig=%08X PartStart=%lld", DiskSig, VtoyDiskExtent.StartingOffset.QuadPart);
2165 if (DiskSig == VtoySig && VtoyDiskExtent.StartingOffset.QuadPart == SIZE_1MB)
2166 {
2167 Log("Ventoy Disk Sig match");
2168 vtoyfind = TRUE;
2169 break;
2170 }
2171 }
2172 }
2173
2174 Drives >>= 1;
2175 VtoyLetter++;
2176 }
2177
2178 if (vtoyfind)
2179 {
2180 Log("Find Ventoy Letter: %C", VtoyLetter);
2181 break;
2182 }
2183 else
2184 {
2185 Log("Now wait and retry ...");
2186 Sleep(1000);
2187 }
2188 }
2189
2190 if (vtoyfind == FALSE)
2191 {
2192 Log("Failed to find ventoy disk");
2193 return 1;
2194 }
2195
2196 VtoyDiskNum = VtoyDiskExtent.DiskNumber;
2197 }
2198 else
2199 {
2200 VtoyLetter = Letter;
2201 Log("No vlnk mode %C", Letter);
2202
2203 VtoyDiskNum = DiskExtent.DiskNumber;
2204 }
2205
2206 if (CheckVentoyDisk(VtoyDiskNum))
2207 {
2208 Log("Disk check OK %C: %u", VtoyLetter, VtoyDiskNum);
2209 }
2210 else
2211 {
2212 Log("Failed to check ventoy disk %u", VtoyDiskNum);
2213 return 1;
2214 }
2215
2216 g_vtoy_disk_drive = VtoyDiskNum;
2217
2218 Drives = GetLogicalDrives();
2219 Log("Drives before mount: 0x%x", Drives);
2220
2221 rc = MountIsoFile(IsoPath, VtoyDiskNum);
2222
2223 NewDrives = GetLogicalDrives();
2224 Log("Drives after mount: 0x%x (0x%x)", NewDrives, (NewDrives ^ Drives));
2225
2226 MntLetter = 'A';
2227 NewDrives = (NewDrives ^ Drives);
2228 while (NewDrives)
2229 {
2230 if (NewDrives & 0x01)
2231 {
2232 if ((NewDrives >> 1) == 0)
2233 {
2234 Log("The ISO file is mounted at %C:", MntLetter);
2235 }
2236 else
2237 {
2238 Log("Maybe the ISO file is mounted at %C:", MntLetter);
2239 }
2240 break;
2241 }
2242
2243 NewDrives >>= 1;
2244 MntLetter++;
2245 }
2246
2247 Log("Mount ISO FILE: %s", rc == 0 ? "SUCCESS" : "FAILED");
2248
2249 //Windows 11 bypass check
2250 if (g_windows_data.windows11_bypass_check == 1)
2251 {
2252 Windows11BypassCheck(IsoPath, MntLetter);
2253 }
2254
2255 // for protect
2256 rc = DeleteVentoyPart2MountPoint(VtoyDiskNum);
2257 Log("Delete ventoy mountpoint: %s", rc == 0 ? "SUCCESS" : "NO NEED");
2258
2259 if (g_windows_data.auto_install_script[0])
2260 {
2261 if (IsFileExist("%s", VTOY_AUTO_FILE))
2262 {
2263 Log("use auto install script %s...", VTOY_AUTO_FILE);
2264 ProcessUnattendedInstallation(VTOY_AUTO_FILE);
2265 }
2266 else
2267 {
2268 Log("auto install script %s not exist", IsoPath);
2269 }
2270 }
2271 else
2272 {
2273 Log("auto install no need");
2274 }
2275
2276 if (g_windows_data.injection_archive[0])
2277 {
2278 sprintf_s(IsoPath, sizeof(IsoPath), "%C:%s", VtoyLetter, g_windows_data.injection_archive);
2279 if (IsFileExist("%s", IsoPath))
2280 {
2281 Log("decompress injection archive %s...", IsoPath);
2282 DecompressInjectionArchive(IsoPath, VtoyDiskNum);
2283
2284 if (IsFileExist("%s", AUTO_RUN_BAT))
2285 {
2286 HANDLE hOut;
2287 DWORD flags = CREATE_NO_WINDOW;
2288 CHAR StrBuf[1024];
2289 STARTUPINFOA Si;
2290 PROCESS_INFORMATION Pi;
2291 SECURITY_ATTRIBUTES Sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
2292
2293 Log("%s exist, now run it...", AUTO_RUN_BAT);
2294
2295 GetStartupInfoA(&Si);
2296
2297 hOut = CreateFileA(AUTO_RUN_LOG,
2298 FILE_APPEND_DATA,
2299 FILE_SHARE_WRITE | FILE_SHARE_READ,
2300 &Sa,
2301 OPEN_ALWAYS,
2302 FILE_ATTRIBUTE_NORMAL,
2303 NULL);
2304
2305 Si.dwFlags |= STARTF_USESTDHANDLES;
2306 if (hOut != INVALID_HANDLE_VALUE)
2307 {
2308 Si.hStdError = hOut;
2309 Si.hStdOutput = hOut;
2310 }
2311
2312 sprintf_s(IsoPath, sizeof(IsoPath), "%C:\\%s", Letter, param->vtoy_img_path);
2313 sprintf_s(StrBuf, sizeof(StrBuf), "cmd.exe /c %s \"%s\" %C", AUTO_RUN_BAT, IsoPath, MntLetter);
2314 CreateProcessA(NULL, StrBuf, NULL, NULL, TRUE, flags, NULL, NULL, &Si, &Pi);
2315 WaitForSingleObject(Pi.hProcess, INFINITE);
2316
2317 SAFE_CLOSE_HANDLE(hOut);
2318 }
2319 else
2320 {
2321 Log("%s not exist...", AUTO_RUN_BAT);
2322 }
2323 }
2324 else
2325 {
2326 Log("injection archive %s not exist", IsoPath);
2327 }
2328 }
2329 else
2330 {
2331 Log("no injection archive found");
2332 }
2333
2334 return 0;
2335 }
2336
2337 static int ExtractWindowsDataFile(char *databuf)
2338 {
2339 int len = 0;
2340 char *filedata = NULL;
2341 ventoy_windows_data *pdata = (ventoy_windows_data *)databuf;
2342
2343 Log("ExtractWindowsDataFile: auto install <%s:%d>", pdata->auto_install_script, pdata->auto_install_len);
2344
2345 filedata = databuf + sizeof(ventoy_windows_data);
2346
2347 if (pdata->auto_install_script[0] && pdata->auto_install_len > 0)
2348 {
2349 SaveBuffer2File(VTOY_AUTO_FILE, filedata, pdata->auto_install_len);
2350 filedata += pdata->auto_install_len;
2351 len = pdata->auto_install_len;
2352 }
2353
2354 return len;
2355 }
2356
2357 static int ventoy_check_create_directory(void)
2358 {
2359 if (IsDirExist("ventoy"))
2360 {
2361 Log("ventoy directory already exist");
2362 }
2363 else
2364 {
2365 Log("ventoy directory not exist, now create it.");
2366 if (!CreateDirectoryA("ventoy", NULL))
2367 {
2368 Log("Failed to create ventoy directory err:%u", GetLastError());
2369 return 1;
2370 }
2371 }
2372
2373 return 0;
2374 }
2375
2376 int VentoyJump(INT argc, CHAR **argv, CHAR *LunchFile)
2377 {
2378 int rc = 1;
2379 int stat = 0;
2380 int exlen = 0;
2381 DWORD Pos;
2382 DWORD PeStart;
2383 DWORD FileSize;
2384 DWORD LockStatus = 0;
2385 BYTE *Buffer = NULL;
2386 CHAR ExeFileName[MAX_PATH];
2387
2388 sprintf_s(ExeFileName, sizeof(ExeFileName), "%s", argv[0]);
2389 if (!IsFileExist("%s", ExeFileName))
2390 {
2391 Log("File %s NOT exist, now try %s.exe", ExeFileName, ExeFileName);
2392 sprintf_s(ExeFileName, sizeof(ExeFileName), "%s.exe", argv[0]);
2393
2394 Log("File %s exist ? %s", ExeFileName, IsFileExist("%s", ExeFileName) ? "YES" : "NO");
2395 }
2396
2397 if (ReadWholeFile2Buf(ExeFileName, (void **)&Buffer, &FileSize))
2398 {
2399 goto End;
2400 }
2401
2402 Log("VentoyJump %dbit", g_system_bit);
2403
2404 MUTEX_LOCK(g_vtoyins_mutex);
2405 stat = ventoy_check_create_directory();
2406 MUTEX_UNLOCK(g_vtoyins_mutex);
2407
2408 if (stat != 0)
2409 {
2410 goto End;
2411 }
2412
2413 for (PeStart = 0; PeStart < FileSize; PeStart += 16)
2414 {
2415 if (CheckOsParam((ventoy_os_param *)(Buffer + PeStart)) &&
2416 CheckPeHead(Buffer, FileSize, PeStart + sizeof(ventoy_os_param)))
2417 {
2418 Log("Find os pararm at %u", PeStart);
2419
2420 memcpy(&g_os_param, Buffer + PeStart, sizeof(ventoy_os_param));
2421 memcpy(&g_windows_data, Buffer + PeStart + sizeof(ventoy_os_param), sizeof(ventoy_windows_data));
2422 exlen = ExtractWindowsDataFile(Buffer + PeStart + sizeof(ventoy_os_param));
2423 memcpy(g_os_param_reserved, g_os_param.vtoy_reserved, sizeof(g_os_param_reserved));
2424
2425 if (g_os_param_reserved[0] == 1)
2426 {
2427 Log("break here for debug .....");
2428 goto End;
2429 }
2430
2431 // convert / to \\
2432 for (Pos = 0; Pos < sizeof(g_os_param.vtoy_img_path) && g_os_param.vtoy_img_path[Pos]; Pos++)
2433 {
2434 if (g_os_param.vtoy_img_path[Pos] == '/')
2435 {
2436 g_os_param.vtoy_img_path[Pos] = '\\';
2437 }
2438 }
2439
2440 PeStart += sizeof(ventoy_os_param) + sizeof(ventoy_windows_data) + exlen;
2441 sprintf_s(LunchFile, MAX_PATH, "ventoy\\%s", GetFileNameInPath(ExeFileName));
2442
2443 MUTEX_LOCK(g_vtoyins_mutex);
2444 if (IsFileExist("%s", LunchFile))
2445 {
2446 Log("vtoyjump multiple call ...");
2447 rc = 0;
2448 MUTEX_UNLOCK(g_vtoyins_mutex);
2449 goto End;
2450 }
2451
2452 SaveBuffer2File(LunchFile, Buffer + PeStart, FileSize - PeStart);
2453 MUTEX_UNLOCK(g_vtoyins_mutex);
2454
2455 break;
2456 }
2457 }
2458
2459 if (PeStart >= FileSize)
2460 {
2461 Log("OS param not found");
2462 goto End;
2463 }
2464
2465 if (g_os_param_reserved[0] == 2)
2466 {
2467 Log("skip hook for debug .....");
2468 rc = 0;
2469 goto End;
2470 }
2471
2472 rc = VentoyHook(&g_os_param);
2473
2474 End:
2475
2476 if (Buffer)
2477 {
2478 free(Buffer);
2479 }
2480
2481 return rc;
2482 }
2483
2484
2485 static int vtoy_cmd_delete_file(char *File)
2486 {
2487 CHAR szCmd[MAX_PATH];
2488 STARTUPINFOA Si;
2489 PROCESS_INFORMATION Pi;
2490
2491 GetStartupInfoA(&Si);
2492 Si.dwFlags |= STARTF_USESHOWWINDOW;
2493 Si.wShowWindow = SW_HIDE;
2494 sprintf_s(szCmd, sizeof(szCmd), "cmd.exe /c del /F /Q %s", File);
2495 CreateProcessA(NULL, szCmd, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
2496 WaitForSingleObject(Pi.hProcess, INFINITE);
2497
2498 return 0;
2499 }
2500
2501 int real_main(int argc, char **argv)
2502 {
2503 int i = 0;
2504 int rc = 0;
2505 CHAR NewFile[MAX_PATH];
2506 CHAR LunchFile[MAX_PATH];
2507 CHAR CallParam[1024] = { 0 };
2508 STARTUPINFOA Si;
2509 PROCESS_INFORMATION Pi;
2510
2511 Log("#### real_main #### argc = %d", argc);
2512 Log("program full path: <%s>", g_prog_full_path);
2513 Log("program dir: <%s>", g_prog_dir);
2514 Log("program name: <%s>", g_prog_name);
2515
2516 Log("argc = %d", argc);
2517 for (i = 0; i < argc; i++)
2518 {
2519 Log("argv[%d]=<%s>", i, argv[i]);
2520 if (i > 0)
2521 {
2522 strcat_s(CallParam, sizeof(CallParam), " ");
2523 strcat_s(CallParam, sizeof(CallParam), argv[i]);
2524 }
2525 }
2526
2527 GetStartupInfoA(&Si);
2528 memset(LunchFile, 0, sizeof(LunchFile));
2529
2530 rc = VentoyJump(argc, argv, LunchFile);
2531
2532 Log("LunchFile=<%s> CallParam=<%s>", LunchFile, CallParam);
2533
2534 if (_stricmp(g_prog_name, "winpeshl.exe") != 0 && IsFileExist("ventoy\\%s", g_prog_name))
2535 {
2536 sprintf_s(NewFile, sizeof(NewFile), "%s_BACK.EXE", g_prog_full_path);
2537 MoveFileA(g_prog_full_path, NewFile);
2538 Log("Move <%s> to <%s>", g_prog_full_path, NewFile);
2539
2540 sprintf_s(NewFile, sizeof(NewFile), "ventoy\\%s", g_prog_name);
2541 CopyFileA(NewFile, g_prog_full_path, TRUE);
2542 Log("Copy <%s> to <%s>", NewFile, g_prog_full_path);
2543
2544 sprintf_s(LunchFile, sizeof(LunchFile), "%s", g_prog_full_path);
2545 Log("Final lunchFile is <%s>", LunchFile);
2546 }
2547 else
2548 {
2549 Log("We don't need to recover original <%s>", g_prog_name);
2550 }
2551
2552 if (g_os_param_reserved[0] == 3)
2553 {
2554 Log("Open log for debug ...");
2555 sprintf_s(LunchFile, sizeof(LunchFile), "%s", "notepad.exe ventoy.log");
2556 }
2557 else
2558 {
2559 if (CallParam[0])
2560 {
2561 strcat_s(LunchFile, sizeof(LunchFile), CallParam);
2562 }
2563 else if (NULL == strstr(LunchFile, "setup.exe"))
2564 {
2565 Log("Not setup.exe, hide windows.");
2566 Si.dwFlags |= STARTF_USESHOWWINDOW;
2567 Si.wShowWindow = SW_HIDE;
2568 }
2569
2570 Log("Ventoy jump %s ...", rc == 0 ? "success" : "failed");
2571 }
2572
2573 Log("Now launch <%s> ...", LunchFile);
2574
2575 if (g_os_param_reserved[0] == 4)
2576 {
2577 Log("Open cmd for debug ...");
2578 sprintf_s(LunchFile, sizeof(LunchFile), "%s", "cmd.exe");
2579 }
2580
2581 if (IsFileExist(ORG_PECMD_BK_PATH))
2582 {
2583 Log("Delete backup file <%s>", ORG_PECMD_BK_PATH);
2584 vtoy_cmd_delete_file(ORG_PECMD_BK_PATH);
2585 }
2586
2587 Log("Backup log at this point");
2588 CopyFileA(LOG_FILE, "X:\\Windows\\ventoy.backup", TRUE);
2589
2590 CreateProcessA(NULL, LunchFile, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
2591
2592 for (i = 0; rc && i < 1800; i++)
2593 {
2594 Log("Ventoy hook failed, now wait and retry ...");
2595 Sleep(1000);
2596 rc = VentoyHook(&g_os_param);
2597 }
2598
2599 Log("Wait process...");
2600 WaitForSingleObject(Pi.hProcess, INFINITE);
2601
2602 Log("vtoyjump finished");
2603 return 0;
2604 }
2605
2606 static void VentoyToUpper(CHAR *str)
2607 {
2608 int i;
2609 for (i = 0; str[i]; i++)
2610 {
2611 str[i] = (CHAR)toupper(str[i]);
2612 }
2613 }
2614
2615 static int vtoy_remove_duplicate_file(char *File)
2616 {
2617 CHAR szCmd[MAX_PATH];
2618 CHAR NewFile[MAX_PATH];
2619 STARTUPINFOA Si;
2620 PROCESS_INFORMATION Pi;
2621
2622 Log("<1> Copy New file", File);
2623 sprintf_s(NewFile, sizeof(NewFile), "%s_NEW", File);
2624 CopyFileA(File, NewFile, FALSE);
2625
2626 Log("<2> Remove file <%s>", File);
2627 GetStartupInfoA(&Si);
2628 Si.dwFlags |= STARTF_USESHOWWINDOW;
2629 Si.wShowWindow = SW_HIDE;
2630 sprintf_s(szCmd, sizeof(szCmd), "cmd.exe /c del /F /Q %s", File);
2631 CreateProcessA(NULL, szCmd, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
2632 WaitForSingleObject(Pi.hProcess, INFINITE);
2633
2634 Log("<3> Copy back file <%s>", File);
2635 MoveFileA(NewFile, File);
2636
2637 return 0;
2638 }
2639
2640 int main(int argc, char **argv)
2641 {
2642 int i;
2643 STARTUPINFOA Si;
2644 PROCESS_INFORMATION Pi;
2645 CHAR CurDir[MAX_PATH];
2646 CHAR NewArgv0[MAX_PATH];
2647 CHAR CallParam[1024] = { 0 };
2648
2649 g_vtoylog_mutex = CreateMutexA(NULL, FALSE, "VTOYLOG_LOCK");
2650 g_vtoyins_mutex = CreateMutexA(NULL, FALSE, "VTOYINS_LOCK");
2651
2652 Log("######## VentoyJump %dbit ##########", g_system_bit);
2653
2654 GetCurrentDirectoryA(sizeof(CurDir), CurDir);
2655 Log("Current directory is <%s>", CurDir);
2656
2657 GetModuleFileNameA(NULL, g_prog_full_path, MAX_PATH);
2658 split_path_name(g_prog_full_path, g_prog_dir, g_prog_name);
2659
2660 Log("EXE path: <%s> dir:<%s> name:<%s>", g_prog_full_path, g_prog_dir, g_prog_name);
2661
2662 if (IsFileExist(WIMBOOT_FILE))
2663 {
2664 Log("This is wimboot mode ...");
2665 g_wimboot_mode = TRUE;
2666
2667 if (!IsFileExist(WIMBOOT_DONE))
2668 {
2669 vtoy_remove_duplicate_file(g_prog_full_path);
2670 SaveBuffer2File(WIMBOOT_DONE, g_prog_full_path, 1);
2671 }
2672 }
2673 else
2674 {
2675 Log("This is normal mode ...");
2676 }
2677
2678 if (_stricmp(g_prog_name, "WinLogon.exe") == 0)
2679 {
2680 Log("This time is rejump back ...");
2681
2682 strcpy_s(g_prog_full_path, sizeof(g_prog_full_path), argv[1]);
2683 split_path_name(g_prog_full_path, g_prog_dir, g_prog_name);
2684
2685 return real_main(argc - 1, argv + 1);
2686 }
2687 else if (_stricmp(g_prog_name, "PECMD.exe") == 0)
2688 {
2689 strcpy_s(NewArgv0, sizeof(NewArgv0), g_prog_dir);
2690 VentoyToUpper(NewArgv0);
2691
2692 if (NULL == strstr(NewArgv0, "SYSTEM32") && IsFileExist(ORG_PECMD_BK_PATH))
2693 {
2694 Log("Just call original pecmd.exe");
2695 strcpy_s(CallParam, sizeof(CallParam), ORG_PECMD_PATH);
2696 }
2697 else
2698 {
2699 Log("We need to rejump for pecmd ...");
2700
2701 ventoy_check_create_directory();
2702 CopyFileA(g_prog_full_path, "ventoy\\WinLogon.exe", TRUE);
2703
2704 sprintf_s(CallParam, sizeof(CallParam), "ventoy\\WinLogon.exe %s", g_prog_full_path);
2705 }
2706
2707 for (i = 1; i < argc; i++)
2708 {
2709 strcat_s(CallParam, sizeof(CallParam), " ");
2710 strcat_s(CallParam, sizeof(CallParam), argv[i]);
2711 }
2712
2713 Log("Now rejump to <%s> ...", CallParam);
2714 GetStartupInfoA(&Si);
2715 CreateProcessA(NULL, CallParam, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
2716
2717 Log("Wait rejump process...");
2718 WaitForSingleObject(Pi.hProcess, INFINITE);
2719 Log("rejump finished");
2720 return 0;
2721 }
2722 else
2723 {
2724 Log("We don't need to rejump ...");
2725
2726 ventoy_check_create_directory();
2727 strcpy_s(NewArgv0, sizeof(NewArgv0), g_prog_full_path);
2728 argv[0] = NewArgv0;
2729
2730 return real_main(argc, argv);
2731 }
2732 }
2733