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