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