]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - vtoyjump/vtoyjump/vtoyjump.c
b9d82cb0a6f132b4f1a491c50ff3ddb416531099
[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 CHAR g_prog_full_path[MAX_PATH];
40 static CHAR g_prog_dir[MAX_PATH];
41 static CHAR g_prog_name[MAX_PATH];
42
43 #define AUTO_RUN_BAT "X:\\VentoyAutoRun.bat"
44 #define AUTO_RUN_LOG "X:\\VentoyAutoRun.log"
45
46 #define LOG_FILE "X:\\Windows\\system32\\ventoy.log"
47 #define MUTEX_LOCK(hmutex) if (hmutex != NULL) LockStatus = WaitForSingleObject(hmutex, INFINITE)
48 #define MUTEX_UNLOCK(hmutex) if (hmutex != NULL && WAIT_OBJECT_0 == LockStatus) ReleaseMutex(hmutex)
49
50 static const char * GetFileNameInPath(const char *fullpath)
51 {
52 int i;
53
54 if (strstr(fullpath, ":"))
55 {
56 for (i = (int)strlen(fullpath); i > 0; i--)
57 {
58 if (fullpath[i - 1] == '/' || fullpath[i - 1] == '\\')
59 {
60 return fullpath + i;
61 }
62 }
63 }
64
65 return fullpath;
66 }
67
68 static int split_path_name(char *fullpath, char *dir, char *name)
69 {
70 CHAR ch;
71 CHAR *Pos = NULL;
72
73 Pos = (CHAR *)GetFileNameInPath(fullpath);
74
75 strcpy_s(name, MAX_PATH, Pos);
76
77 ch = *(Pos - 1);
78 *(Pos - 1) = 0;
79 strcpy_s(dir, MAX_PATH, fullpath);
80 *(Pos - 1) = ch;
81
82 return 0;
83 }
84
85
86 void Log(const char *Fmt, ...)
87 {
88 va_list Arg;
89 int Len = 0;
90 FILE *File = NULL;
91 SYSTEMTIME Sys;
92 char szBuf[1024];
93 DWORD LockStatus = 0;
94 DWORD PID = GetCurrentProcessId();
95
96 GetLocalTime(&Sys);
97 Len += sprintf_s(szBuf, sizeof(szBuf),
98 "[%4d/%02d/%02d %02d:%02d:%02d.%03d] [%u] ",
99 Sys.wYear, Sys.wMonth, Sys.wDay,
100 Sys.wHour, Sys.wMinute, Sys.wSecond,
101 Sys.wMilliseconds, PID);
102
103 va_start(Arg, Fmt);
104 Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len, sizeof(szBuf)-Len, Fmt, Arg);
105 va_end(Arg);
106
107 MUTEX_LOCK(g_vtoylog_mutex);
108
109 fopen_s(&File, LOG_FILE, "a+");
110 if (File)
111 {
112 fwrite(szBuf, 1, Len, File);
113 fwrite("\n", 1, 1, File);
114 fclose(File);
115 }
116
117 MUTEX_UNLOCK(g_vtoylog_mutex);
118 }
119
120
121 static int LoadNtDriver(const char *DrvBinPath)
122 {
123 int i;
124 int rc = 0;
125 BOOL Ret;
126 DWORD Status;
127 SC_HANDLE hServiceMgr;
128 SC_HANDLE hService;
129 char name[256] = { 0 };
130
131 for (i = (int)strlen(DrvBinPath) - 1; i >= 0; i--)
132 {
133 if (DrvBinPath[i] == '\\' || DrvBinPath[i] == '/')
134 {
135 sprintf_s(name, sizeof(name), "%s", DrvBinPath + i + 1);
136 break;
137 }
138 }
139
140 Log("Load NT driver: %s %s", DrvBinPath, name);
141
142 hServiceMgr = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
143 if (hServiceMgr == NULL)
144 {
145 Log("OpenSCManager failed Error:%u", GetLastError());
146 return 1;
147 }
148
149 Log("OpenSCManager OK");
150
151 hService = CreateServiceA(hServiceMgr,
152 name,
153 name,
154 SERVICE_ALL_ACCESS,
155 SERVICE_KERNEL_DRIVER,
156 SERVICE_DEMAND_START,
157 SERVICE_ERROR_NORMAL,
158 DrvBinPath,
159 NULL, NULL, NULL, NULL, NULL);
160 if (hService == NULL)
161 {
162 Status = GetLastError();
163 if (Status != ERROR_IO_PENDING && Status != ERROR_SERVICE_EXISTS)
164 {
165 Log("CreateService failed v %u", Status);
166 CloseServiceHandle(hServiceMgr);
167 return 1;
168 }
169
170 hService = OpenServiceA(hServiceMgr, name, SERVICE_ALL_ACCESS);
171 if (hService == NULL)
172 {
173 Log("OpenService failed %u", Status);
174 CloseServiceHandle(hServiceMgr);
175 return 1;
176 }
177 }
178
179 Log("CreateService imdisk OK");
180
181 Ret = StartServiceA(hService, 0, NULL);
182 if (Ret)
183 {
184 Log("StartService OK");
185 }
186 else
187 {
188 Status = GetLastError();
189 if (Status == ERROR_SERVICE_ALREADY_RUNNING)
190 {
191 rc = 0;
192 }
193 else
194 {
195 Log("StartService error %u", Status);
196 rc = 1;
197 }
198 }
199
200 CloseServiceHandle(hService);
201 CloseServiceHandle(hServiceMgr);
202
203 Log("Load NT driver %s", rc ? "failed" : "success");
204
205 return rc;
206 }
207
208 static int ReadWholeFile2Buf(const char *Fullpath, void **Data, DWORD *Size)
209 {
210 int rc = 1;
211 DWORD FileSize;
212 DWORD dwSize;
213 HANDLE Handle;
214 BYTE *Buffer = NULL;
215
216 Log("ReadWholeFile2Buf <%s>", Fullpath);
217
218 Handle = CreateFileA(Fullpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
219 if (Handle == INVALID_HANDLE_VALUE)
220 {
221 Log("Could not open the file<%s>, error:%u", Fullpath, GetLastError());
222 goto End;
223 }
224
225 FileSize = SetFilePointer(Handle, 0, NULL, FILE_END);
226
227 Buffer = malloc(FileSize);
228 if (!Buffer)
229 {
230 Log("Failed to alloc memory size:%u", FileSize);
231 goto End;
232 }
233
234 SetFilePointer(Handle, 0, NULL, FILE_BEGIN);
235 if (!ReadFile(Handle, Buffer, FileSize, &dwSize, NULL))
236 {
237 Log("ReadFile failed, dwSize:%u error:%u", dwSize, GetLastError());
238 goto End;
239 }
240
241 *Data = Buffer;
242 *Size = FileSize;
243
244 Log("Success read file size:%u", FileSize);
245
246 rc = 0;
247
248 End:
249 SAFE_CLOSE_HANDLE(Handle);
250
251 return rc;
252 }
253
254 static BOOL CheckPeHead(BYTE *Head)
255 {
256 UINT32 PeOffset;
257
258 if (Head[0] != 'M' || Head[1] != 'Z')
259 {
260 return FALSE;
261 }
262
263 PeOffset = *(UINT32 *)(Head + 60);
264 if (*(UINT32 *)(Head + PeOffset) != 0x00004550)
265 {
266 return FALSE;
267 }
268
269 return TRUE;
270 }
271
272
273 static BOOL CheckOsParam(ventoy_os_param *param)
274 {
275 UINT32 i;
276 BYTE Sum = 0;
277
278 if (memcmp(&param->guid, &g_ventoy_guid, sizeof(ventoy_guid)))
279 {
280 return FALSE;
281 }
282
283 for (i = 0; i < sizeof(ventoy_os_param); i++)
284 {
285 Sum += *((BYTE *)param + i);
286 }
287
288 if (Sum)
289 {
290 return FALSE;
291 }
292
293 if (param->vtoy_img_location_addr % 4096)
294 {
295 return FALSE;
296 }
297
298 return TRUE;
299 }
300
301 static int SaveBuffer2File(const char *Fullpath, void *Buffer, DWORD Length)
302 {
303 int rc = 1;
304 DWORD dwSize;
305 HANDLE Handle;
306
307 Log("SaveBuffer2File <%s> len:%u", Fullpath, Length);
308
309 Handle = CreateFileA(Fullpath, GENERIC_READ | GENERIC_WRITE,
310 FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, 0, 0);
311 if (Handle == INVALID_HANDLE_VALUE)
312 {
313 Log("Could not create new file, error:%u", GetLastError());
314 goto End;
315 }
316
317 WriteFile(Handle, Buffer, Length, &dwSize, NULL);
318
319 rc = 0;
320
321 End:
322 SAFE_CLOSE_HANDLE(Handle);
323
324 return rc;
325 }
326
327 static int IsUTF8Encode(const char *src)
328 {
329 int i;
330 const UCHAR *Byte = (const UCHAR *)src;
331
332 for (i = 0; i < MAX_PATH && Byte[i]; i++)
333 {
334 if (Byte[i] > 127)
335 {
336 return 1;
337 }
338 }
339
340 return 0;
341 }
342
343 static int Utf8ToUtf16(const char* src, WCHAR * dst)
344 {
345 int size = MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, 0);
346 return MultiByteToWideChar(CP_UTF8, 0, src, -1, dst, size + 1);
347 }
348
349 static BOOL IsDirExist(const char *Fmt, ...)
350 {
351 va_list Arg;
352 DWORD Attr;
353 int UTF8 = 0;
354 CHAR FilePathA[MAX_PATH];
355 WCHAR FilePathW[MAX_PATH];
356
357 va_start(Arg, Fmt);
358 vsnprintf_s(FilePathA, sizeof(FilePathA), sizeof(FilePathA), Fmt, Arg);
359 va_end(Arg);
360
361 UTF8 = IsUTF8Encode(FilePathA);
362
363 if (UTF8)
364 {
365 Utf8ToUtf16(FilePathA, FilePathW);
366 Attr = GetFileAttributesW(FilePathW);
367 }
368 else
369 {
370 Attr = GetFileAttributesA(FilePathA);
371 }
372
373 if (Attr != INVALID_FILE_ATTRIBUTES && (Attr & FILE_ATTRIBUTE_DIRECTORY))
374 {
375 return TRUE;
376 }
377
378 return FALSE;
379 }
380
381 static BOOL IsFileExist(const char *Fmt, ...)
382 {
383 va_list Arg;
384 HANDLE hFile;
385 DWORD Attr;
386 BOOL bRet = FALSE;
387 int UTF8 = 0;
388 CHAR FilePathA[MAX_PATH];
389 WCHAR FilePathW[MAX_PATH];
390
391 va_start(Arg, Fmt);
392 vsnprintf_s(FilePathA, sizeof(FilePathA), sizeof(FilePathA), Fmt, Arg);
393 va_end(Arg);
394
395 UTF8 = IsUTF8Encode(FilePathA);
396
397 if (UTF8)
398 {
399 Utf8ToUtf16(FilePathA, FilePathW);
400 hFile = CreateFileW(FilePathW, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
401 }
402 else
403 {
404 hFile = CreateFileA(FilePathA, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
405 }
406 if (INVALID_HANDLE_VALUE == hFile)
407 {
408 goto out;
409 }
410
411 CloseHandle(hFile);
412
413 if (UTF8)
414 {
415 Attr = GetFileAttributesW(FilePathW);
416 }
417 else
418 {
419 Attr = GetFileAttributesA(FilePathA);
420 }
421
422 if (Attr & FILE_ATTRIBUTE_DIRECTORY)
423 {
424 goto out;
425 }
426
427 bRet = TRUE;
428
429 out:
430 Log("File <%s> %s", FilePathA, (bRet ? "exist" : "NOT exist"));
431 return bRet;
432 }
433
434 static int GetPhyDiskUUID(const char LogicalDrive, UINT8 *UUID, DISK_EXTENT *DiskExtent)
435 {
436 BOOL Ret;
437 DWORD dwSize;
438 HANDLE Handle;
439 VOLUME_DISK_EXTENTS DiskExtents;
440 CHAR PhyPath[128];
441 UINT8 SectorBuf[512];
442
443 Log("GetPhyDiskUUID %C", LogicalDrive);
444
445 sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\%C:", LogicalDrive);
446 Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
447 if (Handle == INVALID_HANDLE_VALUE)
448 {
449 Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
450 return 1;
451 }
452
453 Ret = DeviceIoControl(Handle,
454 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
455 NULL,
456 0,
457 &DiskExtents,
458 (DWORD)(sizeof(DiskExtents)),
459 (LPDWORD)&dwSize,
460 NULL);
461 if (!Ret || DiskExtents.NumberOfDiskExtents == 0)
462 {
463 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed, error:%u", GetLastError());
464 CloseHandle(Handle);
465 return 1;
466 }
467 CloseHandle(Handle);
468
469 memcpy(DiskExtent, DiskExtents.Extents, sizeof(DiskExtent));
470 Log("%C: is in PhysicalDrive%d ", LogicalDrive, DiskExtents.Extents[0].DiskNumber);
471
472 sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", DiskExtents.Extents[0].DiskNumber);
473 Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
474 if (Handle == INVALID_HANDLE_VALUE)
475 {
476 Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
477 return 1;
478 }
479
480 if (!ReadFile(Handle, SectorBuf, sizeof(SectorBuf), &dwSize, NULL))
481 {
482 Log("ReadFile failed, dwSize:%u error:%u", dwSize, GetLastError());
483 CloseHandle(Handle);
484 return 1;
485 }
486
487 memcpy(UUID, SectorBuf + 0x180, 16);
488 CloseHandle(Handle);
489 return 0;
490 }
491
492 static int VentoyMountAnywhere(HANDLE Handle)
493 {
494 DWORD Status;
495 ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters;
496
497 Log("VentoyMountAnywhere");
498
499 memset(&AttachParameters, 0, sizeof(AttachParameters));
500 AttachParameters.Version = ATTACH_VIRTUAL_DISK_VERSION_1;
501
502 Status = AttachVirtualDisk(Handle, NULL, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY | ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME, 0, &AttachParameters, NULL);
503 if (Status != ERROR_SUCCESS)
504 {
505 Log("Failed to attach virtual disk ErrorCode:%u", Status);
506 return 1;
507 }
508
509 return 0;
510 }
511
512 int VentoyMountY(HANDLE Handle)
513 {
514 int i;
515 BOOL bRet = FALSE;
516 DWORD Status;
517 DWORD physicalDriveNameSize;
518 CHAR *Pos = NULL;
519 WCHAR physicalDriveName[MAX_PATH];
520 CHAR physicalDriveNameA[MAX_PATH];
521 CHAR cdromDriveName[MAX_PATH];
522 ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters;
523
524 Log("VentoyMountY");
525
526 memset(&AttachParameters, 0, sizeof(AttachParameters));
527 AttachParameters.Version = ATTACH_VIRTUAL_DISK_VERSION_1;
528
529 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);
530 if (Status != ERROR_SUCCESS)
531 {
532 Log("Failed to attach virtual disk ErrorCode:%u", Status);
533 return 1;
534 }
535
536 memset(physicalDriveName, 0, sizeof(physicalDriveName));
537 memset(physicalDriveNameA, 0, sizeof(physicalDriveNameA));
538
539 physicalDriveNameSize = MAX_PATH;
540 Status = GetVirtualDiskPhysicalPath(Handle, &physicalDriveNameSize, physicalDriveName);
541 if (Status != ERROR_SUCCESS)
542 {
543 Log("Failed GetVirtualDiskPhysicalPath ErrorCode:%u", Status);
544 return 1;
545 }
546
547 for (i = 0; physicalDriveName[i]; i++)
548 {
549 physicalDriveNameA[i] = (CHAR)toupper((CHAR)(physicalDriveName[i]));
550 }
551
552 Log("physicalDriveNameA=<%s>", physicalDriveNameA);
553
554 Pos = strstr(physicalDriveNameA, "CDROM");
555 if (!Pos)
556 {
557 Log("Not cdrom phy drive");
558 return 1;
559 }
560
561 sprintf_s(cdromDriveName, sizeof(cdromDriveName), "\\Device\\%s", Pos);
562 Log("cdromDriveName=<%s>", cdromDriveName);
563
564 for (i = 0; i < 3 && (bRet == FALSE); i++)
565 {
566 Sleep(1000);
567 bRet = DefineDosDeviceA(DDD_RAW_TARGET_PATH, "Y:", cdromDriveName);
568 Log("DefineDosDeviceA %s", bRet ? "success" : "failed");
569 }
570
571 return bRet ? 0 : 1;
572 }
573
574 static BOOL VentoyAPINeedMountY(const char *IsoPath)
575 {
576 (void)IsoPath;
577
578 /* TBD */
579 return FALSE;
580 }
581
582 static int VentoyAttachVirtualDisk(HANDLE Handle, const char *IsoPath)
583 {
584 int DriveYFree;
585 DWORD Drives;
586
587 Drives = GetLogicalDrives();
588 if ((1 << 24) & Drives)
589 {
590 Log("Y: is occupied");
591 DriveYFree = 0;
592 }
593 else
594 {
595 Log("Y: is free now");
596 DriveYFree = 1;
597 }
598
599 if (DriveYFree && VentoyAPINeedMountY(IsoPath))
600 {
601 return VentoyMountY(Handle);
602 }
603 else
604 {
605 return VentoyMountAnywhere(Handle);
606 }
607 }
608
609 int VentoyMountISOByAPI(const char *IsoPath)
610 {
611 int i;
612 HANDLE Handle;
613 DWORD Status;
614 WCHAR wFilePath[512] = { 0 };
615 VIRTUAL_STORAGE_TYPE StorageType;
616 OPEN_VIRTUAL_DISK_PARAMETERS OpenParameters;
617
618 Log("VentoyMountISOByAPI <%s>", IsoPath);
619
620 if (IsUTF8Encode(IsoPath))
621 {
622 Log("This is UTF8 encoding");
623 MultiByteToWideChar(CP_UTF8, 0, IsoPath, (int)strlen(IsoPath), wFilePath, (int)(sizeof(wFilePath) / sizeof(WCHAR)));
624 }
625 else
626 {
627 Log("This is ANSI encoding");
628 MultiByteToWideChar(CP_ACP, 0, IsoPath, (int)strlen(IsoPath), wFilePath, (int)(sizeof(wFilePath) / sizeof(WCHAR)));
629 }
630
631 memset(&StorageType, 0, sizeof(StorageType));
632 memset(&OpenParameters, 0, sizeof(OpenParameters));
633
634 OpenParameters.Version = OPEN_VIRTUAL_DISK_VERSION_1;
635
636 for (i = 0; i < 10; i++)
637 {
638 Status = OpenVirtualDisk(&StorageType, wFilePath, VIRTUAL_DISK_ACCESS_READ, 0, &OpenParameters, &Handle);
639 if (ERROR_FILE_NOT_FOUND == Status || ERROR_PATH_NOT_FOUND == Status)
640 {
641 Log("OpenVirtualDisk ErrorCode:%u, now wait and retry...", Status);
642 Sleep(1000);
643 }
644 else
645 {
646 if (ERROR_SUCCESS == Status)
647 {
648 Log("OpenVirtualDisk success");
649 }
650 else if (ERROR_VIRTDISK_PROVIDER_NOT_FOUND == Status)
651 {
652 Log("VirtualDisk for ISO file is not supported in current system");
653 }
654 else
655 {
656 Log("Failed to open virtual disk ErrorCode:%u", Status);
657 }
658 break;
659 }
660 }
661
662 if (Status != ERROR_SUCCESS)
663 {
664 return 1;
665 }
666
667 Log("OpenVirtualDisk success");
668
669 Status = VentoyAttachVirtualDisk(Handle, IsoPath);
670 if (Status != ERROR_SUCCESS)
671 {
672 Log("Failed to attach virtual disk ErrorCode:%u", Status);
673 CloseHandle(Handle);
674 return 1;
675 }
676
677 Log("VentoyAttachVirtualDisk success");
678
679 CloseHandle(Handle);
680 return 0;
681 }
682
683
684 static HANDLE g_FatPhyDrive;
685 static UINT64 g_Part2StartSec;
686
687 static int CopyFileFromFatDisk(const CHAR* SrcFile, const CHAR *DstFile)
688 {
689 int rc = 1;
690 int size = 0;
691 char *buf = NULL;
692 void *flfile = NULL;
693
694 Log("CopyFileFromFatDisk (%s)==>(%s)", SrcFile, DstFile);
695
696 flfile = fl_fopen(SrcFile, "rb");
697 if (flfile)
698 {
699 fl_fseek(flfile, 0, SEEK_END);
700 size = (int)fl_ftell(flfile);
701 fl_fseek(flfile, 0, SEEK_SET);
702
703 buf = (char *)malloc(size);
704 if (buf)
705 {
706 fl_fread(buf, 1, size, flfile);
707
708 rc = 0;
709 SaveBuffer2File(DstFile, buf, size);
710 free(buf);
711 }
712
713 fl_fclose(flfile);
714 }
715
716 return rc;
717 }
718
719 static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
720 {
721 DWORD dwSize;
722 BOOL bRet;
723 DWORD ReadSize;
724 LARGE_INTEGER liCurrentPosition;
725
726 liCurrentPosition.QuadPart = Sector + g_Part2StartSec;
727 liCurrentPosition.QuadPart *= 512;
728 SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
729
730 ReadSize = (DWORD)(SectorCount * 512);
731
732 bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL);
733 if (bRet == FALSE || dwSize != ReadSize)
734 {
735 Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet, ReadSize, dwSize, GetLastError());
736 }
737
738 return 1;
739 }
740
741 static BOOL Is2K10PE(void)
742 {
743 BOOL bRet = FALSE;
744 FILE *fp = NULL;
745 CHAR szLine[1024];
746
747 fopen_s(&fp, "X:\\Windows\\System32\\PECMD.INI", "r");
748 if (!fp)
749 {
750 return FALSE;
751 }
752
753 memset(szLine, 0, sizeof(szLine));
754 while (fgets(szLine, sizeof(szLine) - 1, fp))
755 {
756 if (strstr(szLine, "2k10\\"))
757 {
758 bRet = TRUE;
759 break;
760 }
761 }
762
763 fclose(fp);
764 return bRet;
765 }
766
767 static CHAR GetIMDiskMountLogicalDrive(void)
768 {
769 CHAR Letter = 'Y';
770 DWORD Drives;
771 DWORD Mask = 0x1000000;
772
773 // fixed use M as mountpoint for 2K10 PE
774 if (Is2K10PE())
775 {
776 Log("Use M: for 2K10 PE");
777 return 'M';
778 }
779
780 Drives = GetLogicalDrives();
781 Log("Drives=0x%x", Drives);
782
783 while (Mask)
784 {
785 if ((Drives & Mask) == 0)
786 {
787 break;
788 }
789
790 Letter--;
791 Mask >>= 1;
792 }
793
794 return Letter;
795 }
796
797 UINT64 GetVentoyEfiPartStartSector(HANDLE hDrive)
798 {
799 BOOL bRet;
800 DWORD dwSize;
801 MBR_HEAD MBR;
802 VTOY_GPT_INFO *pGpt = NULL;
803 UINT64 StartSector = 0;
804
805 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
806
807 bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);
808 Log("Read MBR Ret:%u Size:%u code:%u", bRet, dwSize, LASTERR);
809
810 if ((!bRet) || (dwSize != sizeof(MBR)))
811 {
812 0;
813 }
814
815 if (MBR.PartTbl[0].FsFlag == 0xEE)
816 {
817 Log("GPT partition style");
818
819 pGpt = malloc(sizeof(VTOY_GPT_INFO));
820 if (!pGpt)
821 {
822 return 0;
823 }
824
825 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
826 bRet = ReadFile(hDrive, pGpt, sizeof(VTOY_GPT_INFO), &dwSize, NULL);
827 if ((!bRet) || (dwSize != sizeof(VTOY_GPT_INFO)))
828 {
829 Log("Failed to read gpt info %d %u %d", bRet, dwSize, LASTERR);
830 return 0;
831 }
832
833 StartSector = pGpt->PartTbl[1].StartLBA;
834 free(pGpt);
835 }
836 else
837 {
838 Log("MBR partition style");
839 StartSector = MBR.PartTbl[1].StartSectorId;
840 }
841
842 Log("GetVentoyEfiPart StartSector: %llu", StartSector);
843 return StartSector;
844 }
845
846 static int VentoyRunImdisk(const char *IsoPath, const char *imdiskexe)
847 {
848 CHAR Letter;
849 CHAR Cmdline[512];
850 WCHAR CmdlineW[512];
851 PROCESS_INFORMATION Pi;
852
853 Log("VentoyRunImdisk <%s> <%s>", IsoPath, imdiskexe);
854
855 Letter = GetIMDiskMountLogicalDrive();
856 sprintf_s(Cmdline, sizeof(Cmdline), "%s -a -o ro -f \"%s\" -m %C:", imdiskexe, IsoPath, Letter);
857 Log("mount iso to %C: use imdisk cmd <%s>", Letter, Cmdline);
858
859 if (IsUTF8Encode(IsoPath))
860 {
861 STARTUPINFOW Si;
862 GetStartupInfoW(&Si);
863 Si.dwFlags |= STARTF_USESHOWWINDOW;
864 Si.wShowWindow = SW_HIDE;
865
866 Utf8ToUtf16(Cmdline, CmdlineW);
867 CreateProcessW(NULL, CmdlineW, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
868
869 Log("This is UTF8 encoding");
870 }
871 else
872 {
873 STARTUPINFOA Si;
874 GetStartupInfoA(&Si);
875 Si.dwFlags |= STARTF_USESHOWWINDOW;
876 Si.wShowWindow = SW_HIDE;
877
878 CreateProcessA(NULL, Cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
879
880 Log("This is ANSI encoding");
881 }
882
883 Log("Wait for imdisk process ...");
884 WaitForSingleObject(Pi.hProcess, INFINITE);
885 Log("imdisk process finished");
886
887 return 0;
888 }
889
890 int VentoyMountISOByImdisk(const char *IsoPath, DWORD PhyDrive)
891 {
892 int rc = 1;
893 BOOL bRet;
894 DWORD dwBytes;
895 HANDLE hDrive;
896 CHAR PhyPath[MAX_PATH];
897 GET_LENGTH_INFORMATION LengthInfo;
898
899 Log("VentoyMountISOByImdisk %s", IsoPath);
900
901 if (IsFileExist("X:\\Windows\\System32\\imdisk.exe"))
902 {
903 Log("imdisk.exe exist, use it directly...");
904 VentoyRunImdisk(IsoPath, "imdisk.exe");
905 return 0;
906 }
907
908 sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", PhyDrive);
909 hDrive = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
910 if (hDrive == INVALID_HANDLE_VALUE)
911 {
912 Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
913 goto End;
914 }
915
916 bRet = DeviceIoControl(hDrive, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &LengthInfo, sizeof(LengthInfo), &dwBytes, NULL);
917 if (!bRet)
918 {
919 Log("Could not get phy disk %s size, error:%u", PhyPath, GetLastError());
920 goto End;
921 }
922
923 g_FatPhyDrive = hDrive;
924 g_Part2StartSec = GetVentoyEfiPartStartSector(hDrive);
925
926 Log("Parse FAT fs...");
927
928 fl_init();
929
930 if (0 == fl_attach_media(VentoyFatDiskRead, NULL))
931 {
932 if (g_system_bit == 64)
933 {
934 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.sys", "ventoy\\imdisk.sys");
935 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.exe", "ventoy\\imdisk.exe");
936 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.cpl", "ventoy\\imdisk.cpl");
937 }
938 else
939 {
940 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.sys", "ventoy\\imdisk.sys");
941 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.exe", "ventoy\\imdisk.exe");
942 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.cpl", "ventoy\\imdisk.cpl");
943 }
944
945 GetCurrentDirectoryA(sizeof(PhyPath), PhyPath);
946 strcat_s(PhyPath, sizeof(PhyPath), "\\ventoy\\imdisk.sys");
947
948 if (LoadNtDriver(PhyPath) == 0)
949 {
950 VentoyRunImdisk(IsoPath, "ventoy\\imdisk.exe");
951 rc = 0;
952 }
953 }
954 fl_shutdown();
955
956 End:
957
958 SAFE_CLOSE_HANDLE(hDrive);
959
960 return rc;
961 }
962
963 static int MountIsoFile(CONST CHAR *IsoPath, DWORD PhyDrive)
964 {
965 if (IsWindows8OrGreater())
966 {
967 Log("This is Windows 8 or latter...");
968 if (VentoyMountISOByAPI(IsoPath) == 0)
969 {
970 Log("Mount iso by API success");
971 return 0;
972 }
973 else
974 {
975 Log("Mount iso by API failed, maybe not supported, try imdisk");
976 return VentoyMountISOByImdisk(IsoPath, PhyDrive);
977 }
978 }
979 else
980 {
981 Log("This is before Windows 8 ...");
982 if (VentoyMountISOByImdisk(IsoPath, PhyDrive) == 0)
983 {
984 Log("Mount iso by imdisk success");
985 return 0;
986 }
987 else
988 {
989 return VentoyMountISOByAPI(IsoPath);
990 }
991 }
992 }
993
994 static int GetPhyDriveByLogicalDrive(int DriveLetter)
995 {
996 BOOL Ret;
997 DWORD dwSize;
998 HANDLE Handle;
999 VOLUME_DISK_EXTENTS DiskExtents;
1000 CHAR PhyPath[128];
1001
1002 sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\%C:", (CHAR)DriveLetter);
1003
1004 Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
1005 if (Handle == INVALID_HANDLE_VALUE)
1006 {
1007 Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
1008 return -1;
1009 }
1010
1011 Ret = DeviceIoControl(Handle,
1012 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
1013 NULL,
1014 0,
1015 &DiskExtents,
1016 (DWORD)(sizeof(DiskExtents)),
1017 (LPDWORD)&dwSize,
1018 NULL);
1019
1020 if (!Ret || DiskExtents.NumberOfDiskExtents == 0)
1021 {
1022 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath, GetLastError());
1023 SAFE_CLOSE_HANDLE(Handle);
1024 return -1;
1025 }
1026 SAFE_CLOSE_HANDLE(Handle);
1027
1028 Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",
1029 PhyPath,
1030 DiskExtents.Extents[0].DiskNumber,
1031 DiskExtents.Extents[0].StartingOffset.QuadPart,
1032 DiskExtents.Extents[0].ExtentLength.QuadPart
1033 );
1034
1035 return (int)DiskExtents.Extents[0].DiskNumber;
1036 }
1037
1038
1039 static int DeleteVentoyPart2MountPoint(DWORD PhyDrive)
1040 {
1041 CHAR Letter = 'A';
1042 DWORD Drives;
1043 DWORD PhyDisk;
1044 CHAR DriveName[] = "?:\\";
1045
1046 Log("DeleteVentoyPart2MountPoint Phy%u ...", PhyDrive);
1047
1048 Drives = GetLogicalDrives();
1049 while (Drives)
1050 {
1051 if ((Drives & 0x01) && IsFileExist("%C:\\ventoy\\ventoy.cpio", Letter))
1052 {
1053 Log("File %C:\\ventoy\\ventoy.cpio exist", Letter);
1054
1055 PhyDisk = GetPhyDriveByLogicalDrive(Letter);
1056 Log("PhyDisk=%u for %C", PhyDisk, Letter);
1057
1058 if (PhyDisk == PhyDrive)
1059 {
1060 DriveName[0] = Letter;
1061 DeleteVolumeMountPointA(DriveName);
1062 return 0;
1063 }
1064 }
1065
1066 Letter++;
1067 Drives >>= 1;
1068 }
1069
1070 return 1;
1071 }
1072
1073 static BOOL check_tar_archive(const char *archive, CHAR *tarName)
1074 {
1075 int len;
1076 int nameLen;
1077 const char *pos = archive;
1078 const char *slash = archive;
1079
1080 while (*pos)
1081 {
1082 if (*pos == '\\' || *pos == '/')
1083 {
1084 slash = pos;
1085 }
1086 pos++;
1087 }
1088
1089 len = (int)strlen(slash);
1090
1091 if (len > 7 && (strncmp(slash + len - 7, ".tar.gz", 7) == 0 || strncmp(slash + len - 7, ".tar.xz", 7) == 0))
1092 {
1093 nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);
1094 tarName[nameLen - 3] = 0;
1095 return TRUE;
1096 }
1097 else if (len > 8 && strncmp(slash + len - 8, ".tar.bz2", 8) == 0)
1098 {
1099 nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);
1100 tarName[nameLen - 4] = 0;
1101 return TRUE;
1102 }
1103 else if (len > 9 && strncmp(slash + len - 9, ".tar.lzma", 9) == 0)
1104 {
1105 nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);
1106 tarName[nameLen - 5] = 0;
1107 return TRUE;
1108 }
1109
1110 return FALSE;
1111 }
1112
1113 static UCHAR *g_unxz_buffer = NULL;
1114 static int g_unxz_len = 0;
1115
1116 static void unxz_error(char *x)
1117 {
1118 Log("%s", x);
1119 }
1120
1121 static int unxz_flush(void *src, unsigned int size)
1122 {
1123 memcpy(g_unxz_buffer + g_unxz_len, src, size);
1124 g_unxz_len += (int)size;
1125
1126 return (int)size;
1127 }
1128
1129 static int DecompressInjectionArchive(const char *archive, DWORD PhyDrive)
1130 {
1131 int rc = 1;
1132 int writelen = 0;
1133 UCHAR *Buffer = NULL;
1134 UCHAR *RawBuffer = NULL;
1135 BOOL bRet;
1136 DWORD dwBytes;
1137 DWORD dwSize;
1138 HANDLE hDrive;
1139 HANDLE hOut;
1140 DWORD flags = CREATE_NO_WINDOW;
1141 CHAR StrBuf[MAX_PATH];
1142 CHAR tarName[MAX_PATH];
1143 STARTUPINFOA Si;
1144 PROCESS_INFORMATION Pi;
1145 PROCESS_INFORMATION NewPi;
1146 GET_LENGTH_INFORMATION LengthInfo;
1147 SECURITY_ATTRIBUTES Sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
1148
1149 Log("DecompressInjectionArchive %s", archive);
1150
1151 sprintf_s(StrBuf, sizeof(StrBuf), "\\\\.\\PhysicalDrive%d", PhyDrive);
1152 hDrive = CreateFileA(StrBuf, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
1153 if (hDrive == INVALID_HANDLE_VALUE)
1154 {
1155 Log("Could not open the disk<%s>, error:%u", StrBuf, GetLastError());
1156 goto End;
1157 }
1158
1159 bRet = DeviceIoControl(hDrive, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &LengthInfo, sizeof(LengthInfo), &dwBytes, NULL);
1160 if (!bRet)
1161 {
1162 Log("Could not get phy disk %s size, error:%u", StrBuf, GetLastError());
1163 goto End;
1164 }
1165
1166 g_FatPhyDrive = hDrive;
1167 g_Part2StartSec = GetVentoyEfiPartStartSector(hDrive);
1168
1169 Log("Parse FAT fs...");
1170
1171 fl_init();
1172
1173 if (0 == fl_attach_media(VentoyFatDiskRead, NULL))
1174 {
1175 if (g_system_bit == 64)
1176 {
1177 CopyFileFromFatDisk("/ventoy/7z/64/7za.xz", "ventoy\\7za.xz");
1178 }
1179 else
1180 {
1181 CopyFileFromFatDisk("/ventoy/7z/32/7za.xz", "ventoy\\7za.xz");
1182 }
1183
1184 ReadWholeFile2Buf("ventoy\\7za.xz", &Buffer, &dwSize);
1185 Log("7za.xz file size:%u", dwSize);
1186
1187 RawBuffer = malloc(SIZE_1MB * 4);
1188 if (RawBuffer)
1189 {
1190 g_unxz_buffer = RawBuffer;
1191 g_unxz_len = 0;
1192 unxz(Buffer, (int)dwSize, NULL, unxz_flush, NULL, &writelen, unxz_error);
1193 if (writelen == (int)dwSize)
1194 {
1195 Log("Decompress success 7za.xz(%u) ---> 7za.exe(%d)", dwSize, g_unxz_len);
1196 }
1197 else
1198 {
1199 Log("Decompress failed 7za.xz(%u) ---> 7za.exe(%u)", dwSize, dwSize);
1200 }
1201
1202 SaveBuffer2File("ventoy\\7za.exe", RawBuffer, (DWORD)g_unxz_len);
1203
1204 g_unxz_buffer = NULL;
1205 g_unxz_len = 0;
1206 free(RawBuffer);
1207 }
1208 else
1209 {
1210 Log("Failed to alloc 4MB memory");
1211 }
1212
1213 sprintf_s(StrBuf, sizeof(StrBuf), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", archive);
1214
1215 Log("extract inject to X:");
1216 Log("cmdline:<%s>", StrBuf);
1217
1218 GetStartupInfoA(&Si);
1219
1220 hOut = CreateFileA("ventoy\\7z.log",
1221 FILE_APPEND_DATA,
1222 FILE_SHARE_WRITE | FILE_SHARE_READ,
1223 &Sa,
1224 OPEN_ALWAYS,
1225 FILE_ATTRIBUTE_NORMAL,
1226 NULL);
1227
1228 Si.dwFlags |= STARTF_USESTDHANDLES;
1229
1230 if (hOut != INVALID_HANDLE_VALUE)
1231 {
1232 Si.hStdError = hOut;
1233 Si.hStdOutput = hOut;
1234 }
1235
1236 CreateProcessA(NULL, StrBuf, NULL, NULL, TRUE, flags, NULL, NULL, &Si, &Pi);
1237 WaitForSingleObject(Pi.hProcess, INFINITE);
1238
1239 //
1240 // decompress tar archive, for tar.gz/tar.xz/tar.bz2
1241 //
1242 if (check_tar_archive(archive, tarName))
1243 {
1244 Log("Decompress tar archive...<%s>", tarName);
1245
1246 sprintf_s(StrBuf, sizeof(StrBuf), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", tarName);
1247
1248 CreateProcessA(NULL, StrBuf, NULL, NULL, TRUE, flags, NULL, NULL, &Si, &NewPi);
1249 WaitForSingleObject(NewPi.hProcess, INFINITE);
1250
1251 Log("Now delete %s", tarName);
1252 DeleteFileA(tarName);
1253 }
1254
1255 SAFE_CLOSE_HANDLE(hOut);
1256 }
1257 fl_shutdown();
1258
1259 End:
1260
1261 SAFE_CLOSE_HANDLE(hDrive);
1262
1263 return rc;
1264 }
1265
1266 static int ProcessUnattendedInstallation(const char *script)
1267 {
1268 DWORD dw;
1269 HKEY hKey;
1270 LSTATUS Ret;
1271 CHAR Letter;
1272 CHAR CurDir[MAX_PATH];
1273
1274 Log("Copy unattended XML ...");
1275
1276 GetCurrentDirectory(sizeof(CurDir), CurDir);
1277 Letter = CurDir[0];
1278 if ((Letter >= 'A' && Letter <= 'Z') || (Letter >= 'a' && Letter <= 'z'))
1279 {
1280 Log("Current Drive Letter: %C", Letter);
1281 }
1282 else
1283 {
1284 Letter = 'X';
1285 }
1286
1287 sprintf_s(CurDir, sizeof(CurDir), "%C:\\Autounattend.xml", Letter);
1288 Log("Copy file <%s> --> <%s>", script, CurDir);
1289 CopyFile(script, CurDir, FALSE);
1290
1291 Ret = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "System\\Setup", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dw);
1292 if (ERROR_SUCCESS == Ret)
1293 {
1294 Ret = RegSetValueEx(hKey, "UnattendFile", 0, REG_SZ, CurDir, (DWORD)(strlen(CurDir) + 1));
1295 }
1296
1297 return 0;
1298 }
1299
1300 static int Windows11BypassCheck(const char *isofile, const char MntLetter)
1301 {
1302 int Ret = 1;
1303 DWORD dwHandle;
1304 DWORD dwSize;
1305 DWORD dwValue = 1;
1306 UINT VerLen = 0;
1307 CHAR *Buffer = NULL;
1308 VS_FIXEDFILEINFO* VerInfo = NULL;
1309 CHAR CheckFile[MAX_PATH];
1310 UINT16 Major, Minor, Build, Revision;
1311
1312 Log("Windows11BypassCheck for <%s> %C:", isofile, MntLetter);
1313
1314 if (FALSE == IsFileExist("%C:\\sources\\boot.wim", MntLetter) ||
1315 FALSE == IsFileExist("%C:\\sources\\compatresources.dll", MntLetter))
1316 {
1317 Log("boot.wim/compatresources.dll not exist, this is not a windows install media.");
1318 goto End;
1319 }
1320
1321 if (FALSE == IsFileExist("%C:\\sources\\install.wim", MntLetter) &&
1322 FALSE == IsFileExist("%C:\\sources\\install.esd", MntLetter))
1323 {
1324 Log("install.wim/install.esd not exist, this is not a windows install media.");
1325 goto End;
1326 }
1327
1328 sprintf_s(CheckFile, sizeof(CheckFile), "%C:\\sources\\compatresources.dll", MntLetter);
1329 dwSize = GetFileVersionInfoSizeA(CheckFile, &dwHandle);
1330 if (0 == dwSize)
1331 {
1332 Log("Failed to get file version info size: %u", LASTERR);
1333 goto End;
1334 }
1335
1336 Buffer = malloc(dwSize);
1337 if (!Buffer)
1338 {
1339 goto End;
1340 }
1341
1342 if (FALSE == GetFileVersionInfoA(CheckFile, dwHandle, dwSize, Buffer))
1343 {
1344 Log("Failed to get file version info : %u", LASTERR);
1345 goto End;
1346 }
1347
1348 if (VerQueryValueA(Buffer, "\\", (LPVOID)&VerInfo, &VerLen) && VerLen != 0)
1349 {
1350 if (VerInfo->dwSignature == VS_FFI_SIGNATURE)
1351 {
1352 Major = HIWORD(VerInfo->dwFileVersionMS);
1353 Minor = LOWORD(VerInfo->dwFileVersionMS);
1354 Build = HIWORD(VerInfo->dwFileVersionLS);
1355 Revision = LOWORD(VerInfo->dwFileVersionLS);
1356
1357 Log("FileVersionze: <%u %u %u %u>", Major, Minor, Build, Revision);
1358
1359 if (Major == 10 && Build > 20000)
1360 {
1361 Major = 11;
1362 }
1363
1364 if (Major != 11)
1365 {
1366 Log("This is not Windows 11, not need to bypass.", Major);
1367 goto End;
1368 }
1369 }
1370 }
1371
1372 //Now we really need to bypass windows 11 check. create registry
1373 HKEY hKey = NULL;
1374 HKEY hSubKey = NULL;
1375 LSTATUS Status;
1376
1377 Status = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "System\\Setup", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwSize);
1378 if (ERROR_SUCCESS != Status)
1379 {
1380 Log("Failed to create reg key System\\Setup %u %u", LASTERR, Status);
1381 goto End;
1382 }
1383
1384 Status = RegCreateKeyExA(hKey, "LabConfig", 0, NULL, 0, KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_CREATE_SUB_KEY, NULL, &hSubKey, &dwSize);
1385 if (ERROR_SUCCESS != Status)
1386 {
1387 Log("Failed to create LabConfig reg %u %u", LASTERR, Status);
1388 goto End;
1389 }
1390
1391 //set reg value
1392 Status += RegSetValueExA(hSubKey, "BypassRAMCheck", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));
1393 Status += RegSetValueExA(hSubKey, "BypassTPMCheck", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));
1394 Status += RegSetValueExA(hSubKey, "BypassSecureBootCheck", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));
1395 Status += RegSetValueExA(hSubKey, "BypassStorageCheck", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));
1396 Status += RegSetValueExA(hSubKey, "BypassCPUCheck", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));
1397
1398 Log("Create bypass registry %s %u", (Status == ERROR_SUCCESS) ? "SUCCESS" : "FAILED", Status);
1399
1400 Ret = 0;
1401
1402 End:
1403 if (Buffer)
1404 {
1405 free(Buffer);
1406 }
1407
1408 return Ret;
1409 }
1410
1411 static int VentoyHook(ventoy_os_param *param)
1412 {
1413 int i;
1414 int rc;
1415 BOOL find = FALSE;
1416 CHAR Letter;
1417 CHAR MntLetter;
1418 DWORD Drives;
1419 DWORD NewDrives;
1420 DISK_EXTENT DiskExtent;
1421 UINT8 UUID[16];
1422 CHAR IsoPath[MAX_PATH];
1423
1424 Log("VentoyHook Path:<%s>", param->vtoy_img_path);
1425
1426 if (IsUTF8Encode(param->vtoy_img_path))
1427 {
1428 Log("This file is UTF8 encoding\n");
1429 }
1430
1431 for (i = 0; i < 5; i++)
1432 {
1433 Letter = 'A';
1434 Drives = GetLogicalDrives();
1435 Log("Logic Drives: 0x%x", Drives);
1436
1437 while (Drives)
1438 {
1439 if (Drives & 0x01)
1440 {
1441 sprintf_s(IsoPath, sizeof(IsoPath), "%C:\\%s", Letter, param->vtoy_img_path);
1442 if (IsFileExist("%s", IsoPath))
1443 {
1444 Log("File exist under %C:", Letter);
1445 if (GetPhyDiskUUID(Letter, UUID, &DiskExtent) == 0)
1446 {
1447 if (memcmp(UUID, param->vtoy_disk_guid, 16) == 0)
1448 {
1449 Log("Disk UUID match");
1450 find = TRUE;
1451 break;
1452 }
1453 }
1454 }
1455 else
1456 {
1457 Log("File NOT exist under %C:", Letter);
1458 }
1459 }
1460
1461 Drives >>= 1;
1462 Letter++;
1463 }
1464
1465 if (find)
1466 {
1467 break;
1468 }
1469 else
1470 {
1471 Log("Now wait and retry ...");
1472 Sleep(1000);
1473 }
1474 }
1475
1476 if (find == FALSE)
1477 {
1478 Log("Failed to find ISO file");
1479 return 1;
1480 }
1481
1482 Log("Find ISO file <%s>", IsoPath);
1483
1484 Drives = GetLogicalDrives();
1485 Log("Drives before mount: 0x%x", Drives);
1486
1487 rc = MountIsoFile(IsoPath, DiskExtent.DiskNumber);
1488
1489 NewDrives = GetLogicalDrives();
1490 Log("Drives after mount: 0x%x (0x%x)", NewDrives, (NewDrives ^ Drives));
1491
1492 MntLetter = 'A';
1493 NewDrives = (NewDrives ^ Drives);
1494 while (NewDrives)
1495 {
1496 if (NewDrives & 0x01)
1497 {
1498 if ((NewDrives >> 1) == 0)
1499 {
1500 Log("The ISO file is mounted at %C:", MntLetter);
1501 }
1502 else
1503 {
1504 Log("Maybe the ISO file is mounted at %C:", MntLetter);
1505 }
1506 break;
1507 }
1508
1509 NewDrives >>= 1;
1510 MntLetter++;
1511 }
1512
1513 Log("Mount ISO FILE: %s", rc == 0 ? "SUCCESS" : "FAILED");
1514
1515 //Windows 11 bypass check
1516 if (g_windows_data.windows11_bypass_check == 1)
1517 {
1518 Windows11BypassCheck(IsoPath, MntLetter);
1519 }
1520
1521 // for protect
1522 rc = DeleteVentoyPart2MountPoint(DiskExtent.DiskNumber);
1523 Log("Delete ventoy mountpoint: %s", rc == 0 ? "SUCCESS" : "NO NEED");
1524
1525 if (g_windows_data.auto_install_script[0])
1526 {
1527 sprintf_s(IsoPath, sizeof(IsoPath), "%C:%s", Letter, g_windows_data.auto_install_script);
1528 if (IsFileExist("%s", IsoPath))
1529 {
1530 Log("use auto install script %s...", IsoPath);
1531 ProcessUnattendedInstallation(IsoPath);
1532 }
1533 else
1534 {
1535 Log("auto install script %s not exist", IsoPath);
1536 }
1537 }
1538 else
1539 {
1540 Log("auto install no need");
1541 }
1542
1543 if (g_windows_data.injection_archive[0])
1544 {
1545 sprintf_s(IsoPath, sizeof(IsoPath), "%C:%s", Letter, g_windows_data.injection_archive);
1546 if (IsFileExist("%s", IsoPath))
1547 {
1548 Log("decompress injection archive %s...", IsoPath);
1549 DecompressInjectionArchive(IsoPath, DiskExtent.DiskNumber);
1550
1551 if (IsFileExist("%s", AUTO_RUN_BAT))
1552 {
1553 HANDLE hOut;
1554 DWORD flags = CREATE_NO_WINDOW;
1555 CHAR StrBuf[1024];
1556 STARTUPINFOA Si;
1557 PROCESS_INFORMATION Pi;
1558 SECURITY_ATTRIBUTES Sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
1559
1560 Log("%s exist, now run it...", AUTO_RUN_BAT);
1561
1562 GetStartupInfoA(&Si);
1563
1564 hOut = CreateFileA(AUTO_RUN_LOG,
1565 FILE_APPEND_DATA,
1566 FILE_SHARE_WRITE | FILE_SHARE_READ,
1567 &Sa,
1568 OPEN_ALWAYS,
1569 FILE_ATTRIBUTE_NORMAL,
1570 NULL);
1571
1572 Si.dwFlags |= STARTF_USESTDHANDLES;
1573 if (hOut != INVALID_HANDLE_VALUE)
1574 {
1575 Si.hStdError = hOut;
1576 Si.hStdOutput = hOut;
1577 }
1578
1579 sprintf_s(IsoPath, sizeof(IsoPath), "%C:\\%s", Letter, param->vtoy_img_path);
1580 sprintf_s(StrBuf, sizeof(StrBuf), "cmd.exe /c %s \"%s\" %C", AUTO_RUN_BAT, IsoPath, MntLetter);
1581 CreateProcessA(NULL, StrBuf, NULL, NULL, TRUE, flags, NULL, NULL, &Si, &Pi);
1582 WaitForSingleObject(Pi.hProcess, INFINITE);
1583
1584 SAFE_CLOSE_HANDLE(hOut);
1585 }
1586 else
1587 {
1588 Log("%s not exist...", AUTO_RUN_BAT);
1589 }
1590 }
1591 else
1592 {
1593 Log("injection archive %s not exist", IsoPath);
1594 }
1595 }
1596 else
1597 {
1598 Log("no injection archive found");
1599 }
1600
1601 return 0;
1602 }
1603
1604
1605 int VentoyJumpWimboot(INT argc, CHAR **argv, CHAR *LunchFile)
1606 {
1607 int rc = 1;
1608 char *buf = NULL;
1609 DWORD size = 0;
1610 DWORD Pos;
1611
1612 Log("VentoyJumpWimboot %dbit", g_system_bit);
1613
1614 sprintf_s(LunchFile, MAX_PATH, "X:\\setup.exe");
1615
1616 ReadWholeFile2Buf("wimboot.data", &buf, &size);
1617 Log("wimboot.data size:%d", size);
1618
1619 memcpy(&g_os_param, buf, sizeof(ventoy_os_param));
1620 memcpy(&g_windows_data, buf + sizeof(ventoy_os_param), sizeof(ventoy_windows_data));
1621 memcpy(g_os_param_reserved, g_os_param.vtoy_reserved, sizeof(g_os_param_reserved));
1622
1623 if (g_os_param_reserved[0] == 1)
1624 {
1625 Log("break here for debug .....");
1626 goto End;
1627 }
1628
1629 // convert / to \\
1630 for (Pos = 0; Pos < sizeof(g_os_param.vtoy_img_path) && g_os_param.vtoy_img_path[Pos]; Pos++)
1631 {
1632 if (g_os_param.vtoy_img_path[Pos] == '/')
1633 {
1634 g_os_param.vtoy_img_path[Pos] = '\\';
1635 }
1636 }
1637
1638 if (g_os_param_reserved[0] == 2)
1639 {
1640 Log("skip hook for debug .....");
1641 rc = 0;
1642 goto End;
1643 }
1644
1645 rc = VentoyHook(&g_os_param);
1646
1647 End:
1648
1649 if (buf)
1650 {
1651 free(buf);
1652 }
1653
1654 return rc;
1655 }
1656
1657 static int ventoy_check_create_directory(void)
1658 {
1659 if (IsDirExist("ventoy"))
1660 {
1661 Log("ventoy directory already exist");
1662 }
1663 else
1664 {
1665 Log("ventoy directory not exist, now create it.");
1666 if (!CreateDirectoryA("ventoy", NULL))
1667 {
1668 Log("Failed to create ventoy directory err:%u", GetLastError());
1669 return 1;
1670 }
1671 }
1672
1673 return 0;
1674 }
1675
1676 int VentoyJump(INT argc, CHAR **argv, CHAR *LunchFile)
1677 {
1678 int rc = 1;
1679 int stat = 0;
1680 DWORD Pos;
1681 DWORD PeStart;
1682 DWORD FileSize;
1683 DWORD LockStatus = 0;
1684 BYTE *Buffer = NULL;
1685 CHAR ExeFileName[MAX_PATH];
1686
1687 sprintf_s(ExeFileName, sizeof(ExeFileName), "%s", argv[0]);
1688 if (!IsFileExist("%s", ExeFileName))
1689 {
1690 Log("File %s NOT exist, now try %s.exe", ExeFileName, ExeFileName);
1691 sprintf_s(ExeFileName, sizeof(ExeFileName), "%s.exe", argv[0]);
1692
1693 Log("File %s exist ? %s", ExeFileName, IsFileExist("%s", ExeFileName) ? "YES" : "NO");
1694 }
1695
1696 if (ReadWholeFile2Buf(ExeFileName, (void **)&Buffer, &FileSize))
1697 {
1698 goto End;
1699 }
1700
1701 Log("VentoyJump %dbit", g_system_bit);
1702
1703 MUTEX_LOCK(g_vtoyins_mutex);
1704 stat = ventoy_check_create_directory();
1705 MUTEX_UNLOCK(g_vtoyins_mutex);
1706
1707 if (stat != 0)
1708 {
1709 goto End;
1710 }
1711
1712 for (PeStart = 0; PeStart < FileSize; PeStart += 16)
1713 {
1714 if (CheckOsParam((ventoy_os_param *)(Buffer + PeStart)) &&
1715 CheckPeHead(Buffer + PeStart + sizeof(ventoy_os_param) + sizeof(ventoy_windows_data)))
1716 {
1717 Log("Find os pararm at %u", PeStart);
1718
1719 memcpy(&g_os_param, Buffer + PeStart, sizeof(ventoy_os_param));
1720 memcpy(&g_windows_data, Buffer + PeStart + sizeof(ventoy_os_param), sizeof(ventoy_windows_data));
1721 memcpy(g_os_param_reserved, g_os_param.vtoy_reserved, sizeof(g_os_param_reserved));
1722
1723 if (g_os_param_reserved[0] == 1)
1724 {
1725 Log("break here for debug .....");
1726 goto End;
1727 }
1728
1729 // convert / to \\
1730 for (Pos = 0; Pos < sizeof(g_os_param.vtoy_img_path) && g_os_param.vtoy_img_path[Pos]; Pos++)
1731 {
1732 if (g_os_param.vtoy_img_path[Pos] == '/')
1733 {
1734 g_os_param.vtoy_img_path[Pos] = '\\';
1735 }
1736 }
1737
1738 PeStart += sizeof(ventoy_os_param) + sizeof(ventoy_windows_data);
1739 sprintf_s(LunchFile, MAX_PATH, "ventoy\\%s", GetFileNameInPath(ExeFileName));
1740
1741 MUTEX_LOCK(g_vtoyins_mutex);
1742 if (IsFileExist("%s", LunchFile))
1743 {
1744 Log("vtoyjump multiple call ...");
1745 rc = 0;
1746 MUTEX_UNLOCK(g_vtoyins_mutex);
1747 goto End;
1748 }
1749
1750 SaveBuffer2File(LunchFile, Buffer + PeStart, FileSize - PeStart);
1751 MUTEX_UNLOCK(g_vtoyins_mutex);
1752
1753 break;
1754 }
1755 }
1756
1757 if (PeStart >= FileSize)
1758 {
1759 Log("OS param not found");
1760 goto End;
1761 }
1762
1763 if (g_os_param_reserved[0] == 2)
1764 {
1765 Log("skip hook for debug .....");
1766 rc = 0;
1767 goto End;
1768 }
1769
1770 rc = VentoyHook(&g_os_param);
1771
1772 End:
1773
1774 if (Buffer)
1775 {
1776 free(Buffer);
1777 }
1778
1779 return rc;
1780 }
1781
1782
1783 int real_main(int argc, char **argv)
1784 {
1785 int i = 0;
1786 int rc = 0;
1787 CHAR NewFile[MAX_PATH];
1788 CHAR LunchFile[MAX_PATH];
1789 CHAR CallParam[1024] = { 0 };
1790 STARTUPINFOA Si;
1791 PROCESS_INFORMATION Pi;
1792
1793 Log("#### real_main #### argc = %d", argc);
1794 Log("program full path: <%s>", g_prog_full_path);
1795 Log("program dir: <%s>", g_prog_dir);
1796 Log("program name:: <%s>", g_prog_name);
1797
1798 Log("argc = %d", argc);
1799 for (i = 0; i < argc; i++)
1800 {
1801 Log("argv[%d]=<%s>", i, argv[i]);
1802 if (i > 0)
1803 {
1804 strcat_s(CallParam, sizeof(CallParam), " ");
1805 strcat_s(CallParam, sizeof(CallParam), argv[i]);
1806 }
1807 }
1808
1809 GetStartupInfoA(&Si);
1810 memset(LunchFile, 0, sizeof(LunchFile));
1811
1812 if (strstr(argv[0], "vtoyjump.exe"))
1813 {
1814 rc = VentoyJumpWimboot(argc, argv, LunchFile);
1815 }
1816 else
1817 {
1818 rc = VentoyJump(argc, argv, LunchFile);
1819 }
1820
1821 Log("LunchFile=<%s> CallParam=<%s>", LunchFile, CallParam);
1822
1823 if (_stricmp(g_prog_name, "winpeshl.exe") != 0 && IsFileExist("ventoy\\%s", g_prog_name))
1824 {
1825 sprintf_s(NewFile, sizeof(NewFile), "%s_BACK.EXE", g_prog_full_path);
1826 MoveFileA(g_prog_full_path, NewFile);
1827 Log("Move <%s> to <%s>", g_prog_full_path, NewFile);
1828
1829 sprintf_s(NewFile, sizeof(NewFile), "ventoy\\%s", g_prog_name);
1830 CopyFileA(NewFile, g_prog_full_path, TRUE);
1831 Log("Copy <%s> to <%s>", NewFile, g_prog_full_path);
1832
1833 sprintf_s(LunchFile, sizeof(LunchFile), "%s", g_prog_full_path);
1834 Log("Final lunchFile is <%s>", LunchFile);
1835 }
1836 else
1837 {
1838 Log("We don't need to recover original <%s>", g_prog_name);
1839 }
1840
1841 if (g_os_param_reserved[0] == 3)
1842 {
1843 Log("Open log for debug ...");
1844 sprintf_s(LunchFile, sizeof(LunchFile), "%s", "notepad.exe ventoy.log");
1845 }
1846 else
1847 {
1848 if (CallParam[0])
1849 {
1850 strcat_s(LunchFile, sizeof(LunchFile), CallParam);
1851 }
1852 else if (NULL == strstr(LunchFile, "setup.exe"))
1853 {
1854 Log("Not setup.exe, hide windows.");
1855 Si.dwFlags |= STARTF_USESHOWWINDOW;
1856 Si.wShowWindow = SW_HIDE;
1857 }
1858
1859 Log("Ventoy jump %s ...", rc == 0 ? "success" : "failed");
1860 }
1861
1862 Log("Now launch <%s> ...", LunchFile);
1863
1864 if (g_os_param_reserved[0] == 4)
1865 {
1866 Log("Open cmd for debug ...");
1867 sprintf_s(LunchFile, sizeof(LunchFile), "%s", "cmd.exe");
1868 }
1869
1870 Log("Backup log at this point");
1871 CopyFileA(LOG_FILE, "X:\\Windows\\ventoy.backup", TRUE);
1872
1873 CreateProcessA(NULL, LunchFile, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
1874
1875 for (i = 0; rc && i < 1800; i++)
1876 {
1877 Log("Ventoy hook failed, now wait and retry ...");
1878 Sleep(1000);
1879 rc = VentoyHook(&g_os_param);
1880 }
1881
1882 Log("Wait process...");
1883 WaitForSingleObject(Pi.hProcess, INFINITE);
1884
1885 Log("vtoyjump finished");
1886 return 0;
1887 }
1888
1889
1890 int main(int argc, char **argv)
1891 {
1892 int i;
1893 STARTUPINFOA Si;
1894 PROCESS_INFORMATION Pi;
1895 CHAR CurDir[MAX_PATH];
1896 CHAR NewArgv0[MAX_PATH];
1897 CHAR CallParam[1024] = { 0 };
1898
1899 g_vtoylog_mutex = CreateMutexA(NULL, FALSE, "VTOYLOG_LOCK");
1900 g_vtoyins_mutex = CreateMutexA(NULL, FALSE, "VTOYINS_LOCK");
1901
1902 Log("######## VentoyJump %dbit ##########", g_system_bit);
1903
1904 GetCurrentDirectoryA(sizeof(CurDir), CurDir);
1905 Log("Current directory is <%s>", CurDir);
1906
1907 GetModuleFileNameA(NULL, g_prog_full_path, MAX_PATH);
1908 split_path_name(g_prog_full_path, g_prog_dir, g_prog_name);
1909
1910 Log("EXE path: <%s> dir:<%s> name:<%s>", g_prog_full_path, g_prog_dir, g_prog_name);
1911
1912 if (_stricmp(g_prog_name, "WinLogon.exe") == 0)
1913 {
1914 Log("This time is rejump back ...");
1915
1916 strcpy_s(g_prog_full_path, sizeof(g_prog_full_path), argv[1]);
1917 split_path_name(g_prog_full_path, g_prog_dir, g_prog_name);
1918
1919 return real_main(argc - 1, argv + 1);
1920 }
1921 else if (_stricmp(g_prog_name, "PECMD.exe") == 0)
1922 {
1923 Log("We need to rejump for pecmd ...");
1924
1925 ventoy_check_create_directory();
1926 CopyFileA(g_prog_full_path, "ventoy\\WinLogon.exe", TRUE);
1927
1928 sprintf_s(CallParam, sizeof(CallParam), "ventoy\\WinLogon.exe %s", g_prog_full_path);
1929 for (i = 1; i < argc; i++)
1930 {
1931 strcat_s(CallParam, sizeof(CallParam), " ");
1932 strcat_s(CallParam, sizeof(CallParam), argv[i]);
1933 }
1934
1935 Log("Now rejump to <%s> ...", CallParam);
1936 GetStartupInfoA(&Si);
1937 CreateProcessA(NULL, CallParam, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
1938
1939 Log("Wait rejump process...");
1940 WaitForSingleObject(Pi.hProcess, INFINITE);
1941 Log("rejump finished");
1942 return 0;
1943 }
1944 else
1945 {
1946 Log("We don't need to rejump ...");
1947
1948 strcpy_s(NewArgv0, sizeof(NewArgv0), g_prog_full_path);
1949 argv[0] = NewArgv0;
1950
1951 return real_main(argc, argv);
1952 }
1953 }
1954
1955