]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - vtoyjump/vtoyjump/vtoyjump.c
ffc31210eadedf25a192fb498554a42c6f48a1c2
[Ventoy.git] / vtoyjump / vtoyjump / vtoyjump.c
1 /******************************************************************************
2 * vtoyjump.c
3 *
4 * Copyright (c) 2020, 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 BOOL g_64bit_system = FALSE;
35 static ventoy_guid g_ventoy_guid = VENTOY_GUID;
36
37 void Log(const char *Fmt, ...)
38 {
39 va_list Arg;
40 int Len = 0;
41 FILE *File = NULL;
42 SYSTEMTIME Sys;
43 char szBuf[1024];
44
45 GetLocalTime(&Sys);
46 Len += sprintf_s(szBuf, sizeof(szBuf),
47 "[%4d/%02d/%02d %02d:%02d:%02d.%03d] ",
48 Sys.wYear, Sys.wMonth, Sys.wDay,
49 Sys.wHour, Sys.wMinute, Sys.wSecond,
50 Sys.wMilliseconds);
51
52 va_start(Arg, Fmt);
53 Len += vsnprintf_s(szBuf + Len, sizeof(szBuf)-Len, sizeof(szBuf)-Len, Fmt, Arg);
54 va_end(Arg);
55
56 fopen_s(&File, "ventoy.log", "a+");
57 if (File)
58 {
59 fwrite(szBuf, 1, Len, File);
60 fwrite("\n", 1, 1, File);
61 fclose(File);
62 }
63 }
64
65
66 static int LoadNtDriver(const char *DrvBinPath)
67 {
68 int i;
69 int rc = 0;
70 BOOL Ret;
71 DWORD Status;
72 SC_HANDLE hServiceMgr;
73 SC_HANDLE hService;
74 char name[256] = { 0 };
75
76 for (i = (int)strlen(DrvBinPath) - 1; i >= 0; i--)
77 {
78 if (DrvBinPath[i] == '\\' || DrvBinPath[i] == '/')
79 {
80 sprintf_s(name, sizeof(name), "%s", DrvBinPath + i + 1);
81 break;
82 }
83 }
84
85 Log("Load NT driver: %s %s", DrvBinPath, name);
86
87 hServiceMgr = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
88 if (hServiceMgr == NULL)
89 {
90 Log("OpenSCManager failed Error:%u", GetLastError());
91 return 1;
92 }
93
94 Log("OpenSCManager OK");
95
96 hService = CreateServiceA(hServiceMgr,
97 name,
98 name,
99 SERVICE_ALL_ACCESS,
100 SERVICE_KERNEL_DRIVER,
101 SERVICE_DEMAND_START,
102 SERVICE_ERROR_NORMAL,
103 DrvBinPath,
104 NULL, NULL, NULL, NULL, NULL);
105 if (hService == NULL)
106 {
107 Status = GetLastError();
108 if (Status != ERROR_IO_PENDING && Status != ERROR_SERVICE_EXISTS)
109 {
110 Log("CreateService failed v %u", Status);
111 CloseServiceHandle(hServiceMgr);
112 return 1;
113 }
114
115 hService = OpenServiceA(hServiceMgr, name, SERVICE_ALL_ACCESS);
116 if (hService == NULL)
117 {
118 Log("OpenService failed %u", Status);
119 CloseServiceHandle(hServiceMgr);
120 return 1;
121 }
122 }
123
124 Log("CreateService imdisk OK");
125
126 Ret = StartServiceA(hService, 0, NULL);
127 if (Ret)
128 {
129 Log("StartService OK");
130 }
131 else
132 {
133 Status = GetLastError();
134 if (Status == ERROR_SERVICE_ALREADY_RUNNING)
135 {
136 rc = 0;
137 }
138 else
139 {
140 Log("StartService error %u", Status);
141 rc = 1;
142 }
143 }
144
145 CloseServiceHandle(hService);
146 CloseServiceHandle(hServiceMgr);
147
148 Log("Load NT driver %s", rc ? "failed" : "success");
149
150 return rc;
151 }
152
153 static int ReadWholeFile2Buf(const char *Fullpath, void **Data, DWORD *Size)
154 {
155 int rc = 1;
156 DWORD FileSize;
157 DWORD dwSize;
158 HANDLE Handle;
159 BYTE *Buffer = NULL;
160
161 Log("ReadWholeFile2Buf <%s>", Fullpath);
162
163 Handle = CreateFileA(Fullpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
164 if (Handle == INVALID_HANDLE_VALUE)
165 {
166 Log("Could not open the file<%s>, error:%u", Fullpath, GetLastError());
167 goto End;
168 }
169
170 FileSize = SetFilePointer(Handle, 0, NULL, FILE_END);
171
172 Buffer = malloc(FileSize);
173 if (!Buffer)
174 {
175 Log("Failed to alloc memory size:%u", FileSize);
176 goto End;
177 }
178
179 SetFilePointer(Handle, 0, NULL, FILE_BEGIN);
180 if (!ReadFile(Handle, Buffer, FileSize, &dwSize, NULL))
181 {
182 Log("ReadFile failed, dwSize:%u error:%u", dwSize, GetLastError());
183 goto End;
184 }
185
186 *Data = Buffer;
187 *Size = FileSize;
188
189 Log("Success read file size:%u", FileSize);
190
191 rc = 0;
192
193 End:
194 SAFE_CLOSE_HANDLE(Handle);
195
196 return rc;
197 }
198
199 static BOOL CheckPeHead(BYTE *Head)
200 {
201 UINT32 PeOffset;
202
203 if (Head[0] != 'M' || Head[1] != 'Z')
204 {
205 return FALSE;
206 }
207
208 PeOffset = *(UINT32 *)(Head + 60);
209 if (*(UINT32 *)(Head + PeOffset) != 0x00004550)
210 {
211 return FALSE;
212 }
213
214 return TRUE;
215 }
216
217 static BOOL IsPe64(BYTE *buffer)
218 {
219 DWORD pe_off;
220
221 if (!CheckPeHead(buffer))
222 {
223 return FALSE;
224 }
225
226 pe_off = *(UINT32 *)(buffer + 60);
227 if (*(UINT16 *)(buffer + pe_off + 24) == 0x020b)
228 {
229 return TRUE;
230 }
231
232 return FALSE;
233 }
234
235
236 static BOOL CheckOsParam(ventoy_os_param *param)
237 {
238 UINT32 i;
239 BYTE Sum = 0;
240
241 if (memcmp(&param->guid, &g_ventoy_guid, sizeof(ventoy_guid)))
242 {
243 return FALSE;
244 }
245
246 for (i = 0; i < sizeof(ventoy_os_param); i++)
247 {
248 Sum += *((BYTE *)param + i);
249 }
250
251 if (Sum)
252 {
253 return FALSE;
254 }
255
256 if (param->vtoy_img_location_addr % 4096)
257 {
258 return FALSE;
259 }
260
261 return TRUE;
262 }
263
264 static int SaveBuffer2File(const char *Fullpath, void *Buffer, DWORD Length)
265 {
266 int rc = 1;
267 DWORD dwSize;
268 HANDLE Handle;
269
270 Log("SaveBuffer2File <%s> len:%u", Fullpath, Length);
271
272 Handle = CreateFileA(Fullpath, GENERIC_READ | GENERIC_WRITE,
273 FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, 0, 0);
274 if (Handle == INVALID_HANDLE_VALUE)
275 {
276 Log("Could not create new file, error:%u", GetLastError());
277 goto End;
278 }
279
280 WriteFile(Handle, Buffer, Length, &dwSize, NULL);
281
282 rc = 0;
283
284 End:
285 SAFE_CLOSE_HANDLE(Handle);
286
287 return rc;
288 }
289
290 static BOOL IsPathExist(BOOL Dir, const char *Fmt, ...)
291 {
292 va_list Arg;
293 HANDLE hFile;
294 DWORD Attr;
295 CHAR FilePath[MAX_PATH];
296
297 va_start(Arg, Fmt);
298 vsnprintf_s(FilePath, sizeof(FilePath), sizeof(FilePath), Fmt, Arg);
299 va_end(Arg);
300
301 hFile = CreateFileA(FilePath, FILE_READ_EA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
302 if (INVALID_HANDLE_VALUE == hFile)
303 {
304 return FALSE;
305 }
306
307 CloseHandle(hFile);
308
309 Attr = GetFileAttributesA(FilePath);
310
311 if (Dir)
312 {
313 if ((Attr & FILE_ATTRIBUTE_DIRECTORY) == 0)
314 {
315 return FALSE;
316 }
317 }
318 else
319 {
320 if (Attr & FILE_ATTRIBUTE_DIRECTORY)
321 {
322 return FALSE;
323 }
324 }
325
326 return TRUE;
327 }
328
329 static int GetPhyDiskUUID(const char LogicalDrive, UINT8 *UUID, DISK_EXTENT *DiskExtent)
330 {
331 BOOL Ret;
332 DWORD dwSize;
333 HANDLE Handle;
334 VOLUME_DISK_EXTENTS DiskExtents;
335 CHAR PhyPath[128];
336 UINT8 SectorBuf[512];
337
338 Log("GetPhyDiskUUID %C", LogicalDrive);
339
340 sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\%C:", LogicalDrive);
341 Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
342 if (Handle == INVALID_HANDLE_VALUE)
343 {
344 Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
345 return 1;
346 }
347
348 Ret = DeviceIoControl(Handle,
349 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
350 NULL,
351 0,
352 &DiskExtents,
353 (DWORD)(sizeof(DiskExtents)),
354 (LPDWORD)&dwSize,
355 NULL);
356 if (!Ret || DiskExtents.NumberOfDiskExtents == 0)
357 {
358 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed, error:%u", GetLastError());
359 CloseHandle(Handle);
360 return 1;
361 }
362 CloseHandle(Handle);
363
364 memcpy(DiskExtent, DiskExtents.Extents, sizeof(DiskExtent));
365 Log("%C: is in PhysicalDrive%d ", LogicalDrive, DiskExtents.Extents[0].DiskNumber);
366
367 sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", DiskExtents.Extents[0].DiskNumber);
368 Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
369 if (Handle == INVALID_HANDLE_VALUE)
370 {
371 Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
372 return 1;
373 }
374
375 if (!ReadFile(Handle, SectorBuf, sizeof(SectorBuf), &dwSize, NULL))
376 {
377 Log("ReadFile failed, dwSize:%u error:%u", dwSize, GetLastError());
378 CloseHandle(Handle);
379 return 1;
380 }
381
382 memcpy(UUID, SectorBuf + 0x180, 16);
383 CloseHandle(Handle);
384 return 0;
385 }
386
387 int VentoyMountISOByAPI(const char *IsoPath)
388 {
389 HANDLE Handle;
390 DWORD Status;
391 WCHAR wFilePath[512] = { 0 };
392 VIRTUAL_STORAGE_TYPE StorageType;
393 OPEN_VIRTUAL_DISK_PARAMETERS OpenParameters;
394 ATTACH_VIRTUAL_DISK_PARAMETERS AttachParameters;
395
396 Log("VentoyMountISOByAPI <%s>", IsoPath);
397
398 MultiByteToWideChar(CP_ACP, 0, IsoPath, (int)strlen(IsoPath), wFilePath, (int)(sizeof(wFilePath) / sizeof(WCHAR)));
399
400 memset(&StorageType, 0, sizeof(StorageType));
401 memset(&OpenParameters, 0, sizeof(OpenParameters));
402 memset(&AttachParameters, 0, sizeof(AttachParameters));
403
404 OpenParameters.Version = OPEN_VIRTUAL_DISK_VERSION_1;
405 AttachParameters.Version = ATTACH_VIRTUAL_DISK_VERSION_1;
406
407 Status = OpenVirtualDisk(&StorageType, wFilePath, VIRTUAL_DISK_ACCESS_READ, 0, &OpenParameters, &Handle);
408 if (Status != ERROR_SUCCESS)
409 {
410 if (ERROR_VIRTDISK_PROVIDER_NOT_FOUND == Status)
411 {
412 Log("VirtualDisk for ISO file is not supported in current system");
413 }
414 else
415 {
416 Log("Failed to open virtual disk ErrorCode:%u", Status);
417 }
418 return 1;
419 }
420
421 Log("OpenVirtualDisk success");
422
423 Status = AttachVirtualDisk(Handle, NULL, ATTACH_VIRTUAL_DISK_FLAG_READ_ONLY | ATTACH_VIRTUAL_DISK_FLAG_PERMANENT_LIFETIME, 0, &AttachParameters, NULL);
424 if (Status != ERROR_SUCCESS)
425 {
426 Log("Failed to attach virtual disk ErrorCode:%u", Status);
427 CloseHandle(Handle);
428 return 1;
429 }
430
431 CloseHandle(Handle);
432 return 0;
433 }
434
435
436 static HANDLE g_FatPhyDrive;
437 static UINT64 g_Part2StartSec;
438
439 static int CopyFileFromFatDisk(const CHAR* SrcFile, const CHAR *DstFile)
440 {
441 int rc = 1;
442 int size = 0;
443 char *buf = NULL;
444 void *flfile = NULL;
445
446 Log("CopyFileFromFatDisk (%s)==>(%s)", SrcFile, DstFile);
447
448 flfile = fl_fopen(SrcFile, "rb");
449 if (flfile)
450 {
451 fl_fseek(flfile, 0, SEEK_END);
452 size = (int)fl_ftell(flfile);
453 fl_fseek(flfile, 0, SEEK_SET);
454
455 buf = (char *)malloc(size);
456 if (buf)
457 {
458 fl_fread(buf, 1, size, flfile);
459
460 rc = 0;
461 SaveBuffer2File(DstFile, buf, size);
462 free(buf);
463 }
464
465 fl_fclose(flfile);
466 }
467
468 return rc;
469 }
470
471 static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
472 {
473 DWORD dwSize;
474 BOOL bRet;
475 DWORD ReadSize;
476 LARGE_INTEGER liCurrentPosition;
477
478 liCurrentPosition.QuadPart = Sector + g_Part2StartSec;
479 liCurrentPosition.QuadPart *= 512;
480 SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
481
482 ReadSize = (DWORD)(SectorCount * 512);
483
484 bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL);
485 if (bRet == FALSE || dwSize != ReadSize)
486 {
487 Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet, ReadSize, dwSize, GetLastError());
488 }
489
490 return 1;
491 }
492
493 static CHAR GetMountLogicalDrive(void)
494 {
495 CHAR Letter = 'Z';
496 DWORD Drives;
497 DWORD Mask = 0x2000000;
498
499 Drives = GetLogicalDrives();
500 Log("Drives=0x%x", Drives);
501
502 while (Mask)
503 {
504 if ((Drives & Mask) == 0)
505 {
506 break;
507 }
508
509 Letter--;
510 Mask >>= 1;
511 }
512
513 return Letter;
514 }
515
516 int VentoyMountISOByImdisk(const char *IsoPath, DWORD PhyDrive)
517 {
518 int rc = 1;
519 BOOL bRet;
520 CHAR Letter;
521 DWORD dwBytes;
522 HANDLE hDrive;
523 CHAR PhyPath[MAX_PATH];
524 STARTUPINFOA Si;
525 PROCESS_INFORMATION Pi;
526 GET_LENGTH_INFORMATION LengthInfo;
527
528 Log("VentoyMountISOByImdisk %s", IsoPath);
529
530 sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\PhysicalDrive%d", PhyDrive);
531 hDrive = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
532 if (hDrive == INVALID_HANDLE_VALUE)
533 {
534 Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
535 goto End;
536 }
537
538 bRet = DeviceIoControl(hDrive, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &LengthInfo, sizeof(LengthInfo), &dwBytes, NULL);
539 if (!bRet)
540 {
541 Log("Could not get phy disk %s size, error:%u", PhyPath, GetLastError());
542 goto End;
543 }
544
545 g_FatPhyDrive = hDrive;
546 g_Part2StartSec = (LengthInfo.Length.QuadPart - VENTOY_EFI_PART_SIZE) / 512;
547
548 Log("Parse FAT fs...");
549
550 fl_init();
551
552 if (0 == fl_attach_media(VentoyFatDiskRead, NULL))
553 {
554 if (g_64bit_system)
555 {
556 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.sys", "ventoy\\imdisk.sys");
557 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.exe", "ventoy\\imdisk.exe");
558 CopyFileFromFatDisk("/ventoy/imdisk/64/imdisk.cpl", "ventoy\\imdisk.cpl");
559 }
560 else
561 {
562 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.sys", "ventoy\\imdisk.sys");
563 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.exe", "ventoy\\imdisk.exe");
564 CopyFileFromFatDisk("/ventoy/imdisk/32/imdisk.cpl", "ventoy\\imdisk.cpl");
565 }
566
567 GetCurrentDirectoryA(sizeof(PhyPath), PhyPath);
568 strcat_s(PhyPath, sizeof(PhyPath), "\\ventoy\\imdisk.sys");
569
570 if (LoadNtDriver(PhyPath) == 0)
571 {
572 rc = 0;
573
574 Letter = GetMountLogicalDrive();
575 sprintf_s(PhyPath, sizeof(PhyPath), "ventoy\\imdisk.exe -a -o ro -f %s -m %C:", IsoPath, Letter);
576
577 Log("mount iso to %C: use imdisk cmd <%s>", Letter, PhyPath);
578
579 GetStartupInfoA(&Si);
580
581 Si.dwFlags |= STARTF_USESHOWWINDOW;
582 Si.wShowWindow = SW_HIDE;
583
584 CreateProcessA(NULL, PhyPath, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
585 WaitForSingleObject(Pi.hProcess, INFINITE);
586 }
587 }
588 fl_shutdown();
589
590 End:
591
592 SAFE_CLOSE_HANDLE(hDrive);
593
594 return rc;
595 }
596
597 static int MountIsoFile(CONST CHAR *IsoPath, DWORD PhyDrive)
598 {
599 if (IsWindows8OrGreater())
600 {
601 Log("This is Windows 8 or latter...");
602 if (VentoyMountISOByAPI(IsoPath) == 0)
603 {
604 Log("Mount iso by API success");
605 return 0;
606 }
607 else
608 {
609 Log("Mount iso by API failed, maybe not supported, try imdisk");
610 return VentoyMountISOByImdisk(IsoPath, PhyDrive);
611 }
612 }
613 else
614 {
615 Log("This is before Windows 8 ...");
616 if (VentoyMountISOByImdisk(IsoPath, PhyDrive) == 0)
617 {
618 Log("Mount iso by imdisk success");
619 return 0;
620 }
621 else
622 {
623 return VentoyMountISOByAPI(IsoPath);
624 }
625 }
626 }
627
628 static int GetPhyDriveByLogicalDrive(int DriveLetter)
629 {
630 BOOL Ret;
631 DWORD dwSize;
632 HANDLE Handle;
633 VOLUME_DISK_EXTENTS DiskExtents;
634 CHAR PhyPath[128];
635
636 sprintf_s(PhyPath, sizeof(PhyPath), "\\\\.\\%C:", (CHAR)DriveLetter);
637
638 Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
639 if (Handle == INVALID_HANDLE_VALUE)
640 {
641 Log("Could not open the disk<%s>, error:%u", PhyPath, GetLastError());
642 return -1;
643 }
644
645 Ret = DeviceIoControl(Handle,
646 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
647 NULL,
648 0,
649 &DiskExtents,
650 (DWORD)(sizeof(DiskExtents)),
651 (LPDWORD)&dwSize,
652 NULL);
653
654 if (!Ret || DiskExtents.NumberOfDiskExtents == 0)
655 {
656 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath, GetLastError());
657 SAFE_CLOSE_HANDLE(Handle);
658 return -1;
659 }
660 SAFE_CLOSE_HANDLE(Handle);
661
662 Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",
663 PhyPath,
664 DiskExtents.Extents[0].DiskNumber,
665 DiskExtents.Extents[0].StartingOffset.QuadPart,
666 DiskExtents.Extents[0].ExtentLength.QuadPart
667 );
668
669 return (int)DiskExtents.Extents[0].DiskNumber;
670 }
671
672
673 static int DeleteVentoyPart2MountPoint(DWORD PhyDrive)
674 {
675 CHAR Letter = 'A';
676 DWORD Drives;
677 DWORD PhyDisk;
678 CHAR DriveName[] = "?:\\";
679
680 Log("DeleteVentoyPart2MountPoint Phy%u ...", PhyDrive);
681
682 Drives = GetLogicalDrives();
683 while (Drives)
684 {
685 if ((Drives & 0x01) && IsPathExist(FALSE, "%C:\\ventoy\\ventoy.cpio", Letter))
686 {
687 Log("File %C:\\ventoy\\ventoy.cpio exist", Letter);
688
689 PhyDisk = GetPhyDriveByLogicalDrive(Letter);
690 Log("PhyDisk=%u for %C", PhyDisk, Letter);
691
692 if (PhyDisk == PhyDrive)
693 {
694 DriveName[0] = Letter;
695 DeleteVolumeMountPointA(DriveName);
696 return 0;
697 }
698 }
699
700 Letter++;
701 Drives >>= 1;
702 }
703
704 return 1;
705 }
706
707 static int ProcessUnattendedInstallation(const char *script)
708 {
709 DWORD dw;
710 HKEY hKey;
711 LSTATUS Ret;
712 CHAR Letter;
713 CHAR CurDir[MAX_PATH];
714
715 Log("Copy unattended XML ...");
716
717 GetCurrentDirectory(sizeof(CurDir), CurDir);
718 Letter = CurDir[0];
719 if ((Letter >= 'A' && Letter <= 'Z') || (Letter >= 'a' && Letter <= 'z'))
720 {
721 Log("Current Drive Letter: %C", Letter);
722 }
723 else
724 {
725 Letter = 'X';
726 }
727
728 sprintf_s(CurDir, sizeof(CurDir), "%C:\\Autounattend.xml", Letter);
729 Log("Copy file <%s> --> <%s>", script, CurDir);
730 CopyFile(script, CurDir, FALSE);
731
732 Ret = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "System\\Setup", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dw);
733 if (ERROR_SUCCESS == Ret)
734 {
735 Ret = RegSetValueEx(hKey, "UnattendFile", 0, REG_SZ, CurDir, (DWORD)(strlen(CurDir) + 1));
736 }
737
738 return 0;
739 }
740
741 static int VentoyHook(ventoy_os_param *param)
742 {
743 int rc;
744 CHAR Letter = 'A';
745 DISK_EXTENT DiskExtent;
746 DWORD Drives = GetLogicalDrives();
747 UINT8 UUID[16];
748 CHAR IsoPath[MAX_PATH];
749
750 Log("Logical Drives=0x%x Path:<%s>", Drives, param->vtoy_img_path);
751
752 while (Drives)
753 {
754 if (Drives & 0x01)
755 {
756 sprintf_s(IsoPath, sizeof(IsoPath), "%C:\\%s", Letter, param->vtoy_img_path);
757 if (IsPathExist(FALSE, "%s", IsoPath))
758 {
759 Log("File exist under %C:", Letter);
760 if (GetPhyDiskUUID(Letter, UUID, &DiskExtent) == 0)
761 {
762 if (memcmp(UUID, param->vtoy_disk_guid, 16) == 0)
763 {
764 Log("Disk UUID match");
765 break;
766 }
767 }
768 }
769 else
770 {
771 Log("File NOT exist under %C:", Letter);
772 }
773 }
774
775 Drives >>= 1;
776 Letter++;
777 }
778
779 if (Drives == 0)
780 {
781 Log("Failed to find ISO file");
782 return 1;
783 }
784
785 Log("Find ISO file <%s>", IsoPath);
786
787 rc = MountIsoFile(IsoPath, DiskExtent.DiskNumber);
788 Log("Mount ISO FILE: %s", rc == 0 ? "SUCCESS" : "FAILED");
789
790 // for protect
791 rc = DeleteVentoyPart2MountPoint(DiskExtent.DiskNumber);
792 Log("Delete ventoy mountpoint: %s", rc == 0 ? "SUCCESS" : "NO NEED");
793
794 if (g_windows_data.auto_install_script[0])
795 {
796 sprintf_s(IsoPath, sizeof(IsoPath), "%C:%s", Letter, g_windows_data.auto_install_script);
797 if (IsPathExist(FALSE, "%s", IsoPath))
798 {
799 Log("use auto install script %s...", IsoPath);
800 ProcessUnattendedInstallation(IsoPath);
801 }
802 else
803 {
804 Log("auto install script %s not exist", IsoPath);
805 }
806 }
807 else
808 {
809 Log("auto install no need");
810 }
811
812 return 0;
813 }
814
815 const char * GetFileNameInPath(const char *fullpath)
816 {
817 int i;
818 const char *pos = NULL;
819
820 if (strstr(fullpath, ":"))
821 {
822 for (i = (int)strlen(fullpath); i > 0; i--)
823 {
824 if (fullpath[i - 1] == '/' || fullpath[i - 1] == '\\')
825 {
826 return fullpath + i;
827 }
828 }
829 }
830
831 return fullpath;
832 }
833
834 int VentoyJump(INT argc, CHAR **argv, CHAR *LunchFile)
835 {
836 int rc = 1;
837 DWORD Pos;
838 DWORD PeStart;
839 DWORD FileSize;
840 BYTE *Buffer = NULL;
841 CHAR ExeFileName[MAX_PATH];
842
843 sprintf_s(ExeFileName, sizeof(ExeFileName), "%s", argv[0]);
844 if (!IsPathExist(FALSE, "%s", ExeFileName))
845 {
846 Log("File %s NOT exist, now try %s.exe", ExeFileName, ExeFileName);
847 sprintf_s(ExeFileName, sizeof(ExeFileName), "%s.exe", argv[0]);
848
849 Log("File %s exist ? %s", ExeFileName, IsPathExist(FALSE, "%s", ExeFileName) ? "YES" : "NO");
850 }
851
852 if (ReadWholeFile2Buf(ExeFileName, (void **)&Buffer, &FileSize))
853 {
854 goto End;
855 }
856
857 g_64bit_system = IsPe64(Buffer);
858
859 if (!IsPathExist(TRUE, "ventoy"))
860 {
861 if (!CreateDirectoryA("ventoy", NULL))
862 {
863 Log("Failed to create ventoy directory err:%u", GetLastError());
864 goto End;
865 }
866 }
867
868 for (PeStart = 0; PeStart < FileSize; PeStart += 16)
869 {
870 if (CheckOsParam((ventoy_os_param *)(Buffer + PeStart)) &&
871 CheckPeHead(Buffer + PeStart + sizeof(ventoy_os_param) + sizeof(ventoy_windows_data)))
872 {
873 Log("Find os pararm at %u", PeStart);
874
875 memcpy(&g_os_param, Buffer + PeStart, sizeof(ventoy_os_param));
876 memcpy(&g_windows_data, Buffer + PeStart + sizeof(ventoy_os_param), sizeof(ventoy_windows_data));
877 memcpy(g_os_param_reserved, g_os_param.vtoy_reserved, sizeof(g_os_param_reserved));
878
879 if (g_os_param_reserved[0] == 1)
880 {
881 Log("break here for debug .....");
882 goto End;
883 }
884
885 // convert / to \\
886 for (Pos = 0; Pos < sizeof(g_os_param.vtoy_img_path) && g_os_param.vtoy_img_path[Pos]; Pos++)
887 {
888 if (g_os_param.vtoy_img_path[Pos] == '/')
889 {
890 g_os_param.vtoy_img_path[Pos] = '\\';
891 }
892 }
893
894 PeStart += sizeof(ventoy_os_param) + sizeof(ventoy_windows_data);
895 sprintf_s(LunchFile, MAX_PATH, "ventoy\\%s", GetFileNameInPath(ExeFileName));
896 SaveBuffer2File(LunchFile, Buffer + PeStart, FileSize - PeStart);
897 break;
898 }
899 }
900
901 if (PeStart >= FileSize)
902 {
903 Log("OS param not found");
904 goto End;
905 }
906
907 if (g_os_param_reserved[0] == 2)
908 {
909 Log("skip hook for debug .....");
910 rc = 0;
911 goto End;
912 }
913
914 rc = VentoyHook(&g_os_param);
915
916 End:
917
918 if (Buffer)
919 {
920 free(Buffer);
921 }
922
923 return rc;
924 }
925
926 int main(int argc, char **argv)
927 {
928 int i = 0;
929 int rc = 0;
930 CHAR *Pos = NULL;
931 CHAR CurDir[MAX_PATH];
932 CHAR LunchFile[MAX_PATH];
933 STARTUPINFOA Si;
934 PROCESS_INFORMATION Pi;
935
936 if (argv[0] && argv[0][0] && argv[0][1] == ':')
937 {
938 GetCurrentDirectoryA(sizeof(CurDir), CurDir);
939
940 strcpy_s(LunchFile, sizeof(LunchFile), argv[0]);
941 Pos = (char *)GetFileNameInPath(LunchFile);
942
943 strcat_s(CurDir, sizeof(CurDir), "\\");
944 strcat_s(CurDir, sizeof(CurDir), Pos);
945
946 if (_stricmp(argv[0], CurDir) != 0)
947 {
948 *Pos = 0;
949 SetCurrentDirectoryA(LunchFile);
950 }
951 }
952
953 Log("######## VentoyJump ##########");
954 Log("argc = %d argv[0] = <%s>", argc, argv[0]);
955
956 if (Pos && *Pos == 0)
957 {
958 Log("Old current directory = <%s>", CurDir);
959 Log("New current directory = <%s>", LunchFile);
960 }
961 else
962 {
963 GetCurrentDirectoryA(sizeof(CurDir), CurDir);
964 Log("Current directory = <%s>", CurDir);
965 }
966
967 GetStartupInfoA(&Si);
968
969 memset(LunchFile, 0, sizeof(LunchFile));
970 rc = VentoyJump(argc, argv, LunchFile);
971
972 if (g_os_param_reserved[0] == 3)
973 {
974 Log("Open log for debug ...");
975 sprintf_s(LunchFile, sizeof(LunchFile), "%s", "notepad.exe ventoy.log");
976 }
977 else
978 {
979 Si.dwFlags |= STARTF_USESHOWWINDOW;
980 Si.wShowWindow = SW_HIDE;
981 Log("Ventoy jump %s ...", rc == 0 ? "success" : "failed");
982 }
983
984 CreateProcessA(NULL, LunchFile, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
985
986 while (rc)
987 {
988 Log("Ventoy hook failed, now wait and retry ...");
989 Sleep(1000);
990
991 rc = VentoyHook(&g_os_param);
992 }
993
994 WaitForSingleObject(Pi.hProcess, INFINITE);
995
996 return 0;
997 }