]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - vtoyjump/vtoyjump/vtoyjump.c
e4abc4f9095bb286a6c5b1f85ad855fc4eee0d81
[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 = 'Y';
496 DWORD Drives;
497 DWORD Mask = 0x1000000;
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 BOOL check_tar_archive(const char *archive, CHAR *tarName)
708 {
709 int len;
710 int nameLen;
711 const char *pos = archive;
712 const char *slash = archive;
713
714 while (*pos)
715 {
716 if (*pos == '\\' || *pos == '/')
717 {
718 slash = pos;
719 }
720 pos++;
721 }
722
723 len = (int)strlen(slash);
724
725 if (len > 7 && (strncmp(slash + len - 7, ".tar.gz", 7) == 0 || strncmp(slash + len - 7, ".tar.xz", 7) == 0))
726 {
727 nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);
728 tarName[nameLen - 3] = 0;
729 return TRUE;
730 }
731 else if (len > 8 && strncmp(slash + len - 8, ".tar.bz2", 8) == 0)
732 {
733 nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);
734 tarName[nameLen - 4] = 0;
735 return TRUE;
736 }
737 else if (len > 9 && strncmp(slash + len - 9, ".tar.lzma", 9) == 0)
738 {
739 nameLen = (int)sprintf_s(tarName, MAX_PATH, "X:%s", slash);
740 tarName[nameLen - 5] = 0;
741 return TRUE;
742 }
743
744 return FALSE;
745 }
746
747 static int DecompressInjectionArchive(const char *archive, DWORD PhyDrive)
748 {
749 int rc = 1;
750 BOOL bRet;
751 DWORD dwBytes;
752 HANDLE hDrive;
753 HANDLE hOut;
754 DWORD flags = CREATE_NO_WINDOW;
755 CHAR StrBuf[MAX_PATH];
756 CHAR tarName[MAX_PATH];
757 STARTUPINFOA Si;
758 PROCESS_INFORMATION Pi;
759 PROCESS_INFORMATION NewPi;
760 GET_LENGTH_INFORMATION LengthInfo;
761 SECURITY_ATTRIBUTES Sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
762
763 Log("DecompressInjectionArchive %s", archive);
764
765 sprintf_s(StrBuf, sizeof(StrBuf), "\\\\.\\PhysicalDrive%d", PhyDrive);
766 hDrive = CreateFileA(StrBuf, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
767 if (hDrive == INVALID_HANDLE_VALUE)
768 {
769 Log("Could not open the disk<%s>, error:%u", StrBuf, GetLastError());
770 goto End;
771 }
772
773 bRet = DeviceIoControl(hDrive, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &LengthInfo, sizeof(LengthInfo), &dwBytes, NULL);
774 if (!bRet)
775 {
776 Log("Could not get phy disk %s size, error:%u", StrBuf, GetLastError());
777 goto End;
778 }
779
780 g_FatPhyDrive = hDrive;
781 g_Part2StartSec = (LengthInfo.Length.QuadPart - VENTOY_EFI_PART_SIZE) / 512;
782
783 Log("Parse FAT fs...");
784
785 fl_init();
786
787 if (0 == fl_attach_media(VentoyFatDiskRead, NULL))
788 {
789 if (g_64bit_system)
790 {
791 CopyFileFromFatDisk("/ventoy/7z/64/7za.exe", "ventoy\\7za.exe");
792 }
793 else
794 {
795 CopyFileFromFatDisk("/ventoy/7z/32/7za.exe", "ventoy\\7za.exe");
796 }
797
798 sprintf_s(StrBuf, sizeof(StrBuf), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", archive);
799
800 Log("extract inject to X:");
801 Log("cmdline:<%s>", StrBuf);
802
803 GetStartupInfoA(&Si);
804
805 hOut = CreateFileA("ventoy\\7z.log",
806 FILE_APPEND_DATA,
807 FILE_SHARE_WRITE | FILE_SHARE_READ,
808 &Sa,
809 OPEN_ALWAYS,
810 FILE_ATTRIBUTE_NORMAL,
811 NULL);
812
813 Si.dwFlags |= STARTF_USESTDHANDLES;
814
815 if (hOut != INVALID_HANDLE_VALUE)
816 {
817 Si.hStdError = hOut;
818 Si.hStdOutput = hOut;
819 }
820
821 CreateProcessA(NULL, StrBuf, NULL, NULL, TRUE, flags, NULL, NULL, &Si, &Pi);
822 WaitForSingleObject(Pi.hProcess, INFINITE);
823
824 //
825 // decompress tar archive, for tar.gz/tar.xz/tar.bz2
826 //
827 if (check_tar_archive(archive, tarName))
828 {
829 Log("Decompress tar archive...<%s>", tarName);
830
831 sprintf_s(StrBuf, sizeof(StrBuf), "ventoy\\7za.exe x -y -aoa -oX:\\ %s", tarName);
832
833 CreateProcessA(NULL, StrBuf, NULL, NULL, TRUE, flags, NULL, NULL, &Si, &NewPi);
834 WaitForSingleObject(NewPi.hProcess, INFINITE);
835
836 Log("Now delete %s", tarName);
837 DeleteFileA(tarName);
838 }
839
840 SAFE_CLOSE_HANDLE(hOut);
841 }
842 fl_shutdown();
843
844 End:
845
846 SAFE_CLOSE_HANDLE(hDrive);
847
848 return rc;
849 }
850
851 static int ProcessUnattendedInstallation(const char *script)
852 {
853 DWORD dw;
854 HKEY hKey;
855 LSTATUS Ret;
856 CHAR Letter;
857 CHAR CurDir[MAX_PATH];
858
859 Log("Copy unattended XML ...");
860
861 GetCurrentDirectory(sizeof(CurDir), CurDir);
862 Letter = CurDir[0];
863 if ((Letter >= 'A' && Letter <= 'Z') || (Letter >= 'a' && Letter <= 'z'))
864 {
865 Log("Current Drive Letter: %C", Letter);
866 }
867 else
868 {
869 Letter = 'X';
870 }
871
872 sprintf_s(CurDir, sizeof(CurDir), "%C:\\Autounattend.xml", Letter);
873 Log("Copy file <%s> --> <%s>", script, CurDir);
874 CopyFile(script, CurDir, FALSE);
875
876 Ret = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "System\\Setup", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dw);
877 if (ERROR_SUCCESS == Ret)
878 {
879 Ret = RegSetValueEx(hKey, "UnattendFile", 0, REG_SZ, CurDir, (DWORD)(strlen(CurDir) + 1));
880 }
881
882 return 0;
883 }
884
885 static int VentoyHook(ventoy_os_param *param)
886 {
887 int rc;
888 CHAR Letter = 'A';
889 DISK_EXTENT DiskExtent;
890 DWORD Drives = GetLogicalDrives();
891 UINT8 UUID[16];
892 CHAR IsoPath[MAX_PATH];
893
894 Log("Logical Drives=0x%x Path:<%s>", Drives, param->vtoy_img_path);
895
896 while (Drives)
897 {
898 if (Drives & 0x01)
899 {
900 sprintf_s(IsoPath, sizeof(IsoPath), "%C:\\%s", Letter, param->vtoy_img_path);
901 if (IsPathExist(FALSE, "%s", IsoPath))
902 {
903 Log("File exist under %C:", Letter);
904 if (GetPhyDiskUUID(Letter, UUID, &DiskExtent) == 0)
905 {
906 if (memcmp(UUID, param->vtoy_disk_guid, 16) == 0)
907 {
908 Log("Disk UUID match");
909 break;
910 }
911 }
912 }
913 else
914 {
915 Log("File NOT exist under %C:", Letter);
916 }
917 }
918
919 Drives >>= 1;
920 Letter++;
921 }
922
923 if (Drives == 0)
924 {
925 Log("Failed to find ISO file");
926 return 1;
927 }
928
929 Log("Find ISO file <%s>", IsoPath);
930
931 rc = MountIsoFile(IsoPath, DiskExtent.DiskNumber);
932 Log("Mount ISO FILE: %s", rc == 0 ? "SUCCESS" : "FAILED");
933
934 // for protect
935 rc = DeleteVentoyPart2MountPoint(DiskExtent.DiskNumber);
936 Log("Delete ventoy mountpoint: %s", rc == 0 ? "SUCCESS" : "NO NEED");
937
938 if (g_windows_data.auto_install_script[0])
939 {
940 sprintf_s(IsoPath, sizeof(IsoPath), "%C:%s", Letter, g_windows_data.auto_install_script);
941 if (IsPathExist(FALSE, "%s", IsoPath))
942 {
943 Log("use auto install script %s...", IsoPath);
944 ProcessUnattendedInstallation(IsoPath);
945 }
946 else
947 {
948 Log("auto install script %s not exist", IsoPath);
949 }
950 }
951 else
952 {
953 Log("auto install no need");
954 }
955
956 if (g_windows_data.injection_archive[0])
957 {
958 sprintf_s(IsoPath, sizeof(IsoPath), "%C:%s", Letter, g_windows_data.injection_archive);
959 if (IsPathExist(FALSE, "%s", IsoPath))
960 {
961 Log("decompress injection archive %s...", IsoPath);
962 DecompressInjectionArchive(IsoPath, DiskExtent.DiskNumber);
963 }
964 else
965 {
966 Log("injection archive %s not exist", IsoPath);
967 }
968 }
969 else
970 {
971 Log("no injection archive found");
972 }
973
974 return 0;
975 }
976
977 const char * GetFileNameInPath(const char *fullpath)
978 {
979 int i;
980 const char *pos = NULL;
981
982 if (strstr(fullpath, ":"))
983 {
984 for (i = (int)strlen(fullpath); i > 0; i--)
985 {
986 if (fullpath[i - 1] == '/' || fullpath[i - 1] == '\\')
987 {
988 return fullpath + i;
989 }
990 }
991 }
992
993 return fullpath;
994 }
995
996 int VentoyJump(INT argc, CHAR **argv, CHAR *LunchFile)
997 {
998 int rc = 1;
999 DWORD Pos;
1000 DWORD PeStart;
1001 DWORD FileSize;
1002 BYTE *Buffer = NULL;
1003 CHAR ExeFileName[MAX_PATH];
1004
1005 sprintf_s(ExeFileName, sizeof(ExeFileName), "%s", argv[0]);
1006 if (!IsPathExist(FALSE, "%s", ExeFileName))
1007 {
1008 Log("File %s NOT exist, now try %s.exe", ExeFileName, ExeFileName);
1009 sprintf_s(ExeFileName, sizeof(ExeFileName), "%s.exe", argv[0]);
1010
1011 Log("File %s exist ? %s", ExeFileName, IsPathExist(FALSE, "%s", ExeFileName) ? "YES" : "NO");
1012 }
1013
1014 if (ReadWholeFile2Buf(ExeFileName, (void **)&Buffer, &FileSize))
1015 {
1016 goto End;
1017 }
1018
1019 g_64bit_system = IsPe64(Buffer);
1020
1021 if (!IsPathExist(TRUE, "ventoy"))
1022 {
1023 if (!CreateDirectoryA("ventoy", NULL))
1024 {
1025 Log("Failed to create ventoy directory err:%u", GetLastError());
1026 goto End;
1027 }
1028 }
1029
1030 for (PeStart = 0; PeStart < FileSize; PeStart += 16)
1031 {
1032 if (CheckOsParam((ventoy_os_param *)(Buffer + PeStart)) &&
1033 CheckPeHead(Buffer + PeStart + sizeof(ventoy_os_param) + sizeof(ventoy_windows_data)))
1034 {
1035 Log("Find os pararm at %u", PeStart);
1036
1037 memcpy(&g_os_param, Buffer + PeStart, sizeof(ventoy_os_param));
1038 memcpy(&g_windows_data, Buffer + PeStart + sizeof(ventoy_os_param), sizeof(ventoy_windows_data));
1039 memcpy(g_os_param_reserved, g_os_param.vtoy_reserved, sizeof(g_os_param_reserved));
1040
1041 if (g_os_param_reserved[0] == 1)
1042 {
1043 Log("break here for debug .....");
1044 goto End;
1045 }
1046
1047 // convert / to \\
1048 for (Pos = 0; Pos < sizeof(g_os_param.vtoy_img_path) && g_os_param.vtoy_img_path[Pos]; Pos++)
1049 {
1050 if (g_os_param.vtoy_img_path[Pos] == '/')
1051 {
1052 g_os_param.vtoy_img_path[Pos] = '\\';
1053 }
1054 }
1055
1056 PeStart += sizeof(ventoy_os_param) + sizeof(ventoy_windows_data);
1057 sprintf_s(LunchFile, MAX_PATH, "ventoy\\%s", GetFileNameInPath(ExeFileName));
1058 SaveBuffer2File(LunchFile, Buffer + PeStart, FileSize - PeStart);
1059 break;
1060 }
1061 }
1062
1063 if (PeStart >= FileSize)
1064 {
1065 Log("OS param not found");
1066 goto End;
1067 }
1068
1069 if (g_os_param_reserved[0] == 2)
1070 {
1071 Log("skip hook for debug .....");
1072 rc = 0;
1073 goto End;
1074 }
1075
1076 rc = VentoyHook(&g_os_param);
1077
1078 End:
1079
1080 if (Buffer)
1081 {
1082 free(Buffer);
1083 }
1084
1085 return rc;
1086 }
1087
1088 int main(int argc, char **argv)
1089 {
1090 int i = 0;
1091 int rc = 0;
1092 CHAR *Pos = NULL;
1093 CHAR CurDir[MAX_PATH];
1094 CHAR LunchFile[MAX_PATH];
1095 STARTUPINFOA Si;
1096 PROCESS_INFORMATION Pi;
1097
1098 if (argv[0] && argv[0][0] && argv[0][1] == ':')
1099 {
1100 GetCurrentDirectoryA(sizeof(CurDir), CurDir);
1101
1102 strcpy_s(LunchFile, sizeof(LunchFile), argv[0]);
1103 Pos = (char *)GetFileNameInPath(LunchFile);
1104
1105 strcat_s(CurDir, sizeof(CurDir), "\\");
1106 strcat_s(CurDir, sizeof(CurDir), Pos);
1107
1108 if (_stricmp(argv[0], CurDir) != 0)
1109 {
1110 *Pos = 0;
1111 SetCurrentDirectoryA(LunchFile);
1112 }
1113 }
1114
1115 Log("######## VentoyJump ##########");
1116 Log("argc = %d argv[0] = <%s>", argc, argv[0]);
1117
1118 if (Pos && *Pos == 0)
1119 {
1120 Log("Old current directory = <%s>", CurDir);
1121 Log("New current directory = <%s>", LunchFile);
1122 }
1123 else
1124 {
1125 GetCurrentDirectoryA(sizeof(CurDir), CurDir);
1126 Log("Current directory = <%s>", CurDir);
1127 }
1128
1129 GetStartupInfoA(&Si);
1130
1131 memset(LunchFile, 0, sizeof(LunchFile));
1132 rc = VentoyJump(argc, argv, LunchFile);
1133
1134 if (g_os_param_reserved[0] == 3)
1135 {
1136 Log("Open log for debug ...");
1137 sprintf_s(LunchFile, sizeof(LunchFile), "%s", "notepad.exe ventoy.log");
1138 }
1139 else
1140 {
1141 Si.dwFlags |= STARTF_USESHOWWINDOW;
1142 Si.wShowWindow = SW_HIDE;
1143 Log("Ventoy jump %s ...", rc == 0 ? "success" : "failed");
1144 }
1145
1146 CreateProcessA(NULL, LunchFile, NULL, NULL, FALSE, 0, NULL, NULL, &Si, &Pi);
1147
1148 while (rc)
1149 {
1150 Log("Ventoy hook failed, now wait and retry ...");
1151 Sleep(1000);
1152
1153 rc = VentoyHook(&g_os_param);
1154 }
1155
1156 WaitForSingleObject(Pi.hProcess, INFINITE);
1157
1158 return 0;
1159 }