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