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