mirror of
https://github.com/ventoy/Ventoy.git
synced 2025-09-18 01:41:15 +00:00
Add experimental support for Non-destructive Installation in Windows.
This commit is contained in:
@@ -33,6 +33,34 @@
|
||||
|
||||
static int g_backup_bin_index = 0;
|
||||
|
||||
|
||||
static BOOL WriteDataToPhyDisk(HANDLE hDrive, UINT64 Offset, VOID *buffer, DWORD len)
|
||||
{
|
||||
BOOL bRet;
|
||||
DWORD dwSize = 0;
|
||||
LARGE_INTEGER liCurPosition;
|
||||
LARGE_INTEGER liNewPosition;
|
||||
|
||||
liCurPosition.QuadPart = (LONGLONG)Offset;
|
||||
liNewPosition.QuadPart = 0;
|
||||
if (0 == SetFilePointerEx(hDrive, liCurPosition, &liNewPosition, FILE_BEGIN) ||
|
||||
liNewPosition.QuadPart != liCurPosition.QuadPart)
|
||||
{
|
||||
Log("SetFilePointerEx Failed %u", LASTERR);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bRet = WriteFile(hDrive, buffer, len, &dwSize, NULL);
|
||||
if (bRet == FALSE || dwSize != len)
|
||||
{
|
||||
Log("Write file error %u %u", dwSize, LASTERR);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static DWORD GetVentoyVolumeName(int PhyDrive, UINT64 StartSectorId, CHAR *NameBuf, UINT32 BufLen, BOOL DelSlash)
|
||||
{
|
||||
size_t len;
|
||||
@@ -129,7 +157,7 @@ static int GetLettersBelongPhyDrive(int PhyDrive, char *DriveLetters, size_t Len
|
||||
|
||||
for (Pos = StringBuf; *Pos; Pos += strlen(Pos) + 1)
|
||||
{
|
||||
if (n < (int)Length && PhyDrive == GetPhyDriveByLogicalDrive(Pos[0]))
|
||||
if (n < (int)Length && PhyDrive == GetPhyDriveByLogicalDrive(Pos[0], NULL))
|
||||
{
|
||||
Log("%C: is belong to phydrive%d", Pos[0], PhyDrive);
|
||||
DriveLetters[n++] = Pos[0];
|
||||
@@ -140,7 +168,7 @@ static int GetLettersBelongPhyDrive(int PhyDrive, char *DriveLetters, size_t Len
|
||||
return 0;
|
||||
}
|
||||
|
||||
static HANDLE GetPhysicalHandle(int Drive, BOOLEAN bLockDrive, BOOLEAN bWriteAccess, BOOLEAN bWriteShare)
|
||||
HANDLE GetPhysicalHandle(int Drive, BOOLEAN bLockDrive, BOOLEAN bWriteAccess, BOOLEAN bWriteShare)
|
||||
{
|
||||
int i;
|
||||
DWORD dwSize;
|
||||
@@ -260,7 +288,7 @@ End:
|
||||
return hDrive;
|
||||
}
|
||||
|
||||
int GetPhyDriveByLogicalDrive(int DriveLetter)
|
||||
int GetPhyDriveByLogicalDrive(int DriveLetter, UINT64 *Offset)
|
||||
{
|
||||
BOOL Ret;
|
||||
DWORD dwSize;
|
||||
@@ -301,6 +329,11 @@ int GetPhyDriveByLogicalDrive(int DriveLetter)
|
||||
DiskExtents.Extents[0].ExtentLength.QuadPart
|
||||
);
|
||||
|
||||
if (Offset)
|
||||
{
|
||||
*Offset = (UINT64)(DiskExtents.Extents[0].StartingOffset.QuadPart);
|
||||
}
|
||||
|
||||
return (int)DiskExtents.Extents[0].DiskNumber;
|
||||
}
|
||||
|
||||
@@ -335,7 +368,7 @@ int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO *pDriveList, DWORD *pDriveCount)
|
||||
{
|
||||
if (dwBytes & 0x01)
|
||||
{
|
||||
id = GetPhyDriveByLogicalDrive(Letter);
|
||||
id = GetPhyDriveByLogicalDrive(Letter, NULL);
|
||||
Log("%C --> %d", Letter, id);
|
||||
if (id >= 0)
|
||||
{
|
||||
@@ -842,7 +875,7 @@ static int FormatPart2Fat(HANDLE hDrive, UINT64 StartSectorId)
|
||||
LARGE_INTEGER liNewPosition;
|
||||
BYTE *CheckBuf = NULL;
|
||||
|
||||
Log("FormatPart2Fat %llu...", StartSectorId);
|
||||
Log("FormatPart2Fat %llu...", (ULONGLONG)StartSectorId);
|
||||
|
||||
CheckBuf = malloc(SIZE_1MB);
|
||||
if (!CheckBuf)
|
||||
@@ -1830,6 +1863,269 @@ End:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int PartitionResizeForVentoy(PHY_DRIVE_INFO *pPhyDrive)
|
||||
{
|
||||
int i, j;
|
||||
int rc = 1;
|
||||
int PhyDrive;
|
||||
int PartStyle;
|
||||
INT64 ReservedValue;
|
||||
UINT64 RecudeBytes;
|
||||
GUID Guid;
|
||||
MBR_HEAD MBR;
|
||||
VTOY_GPT_INFO *pGPT;
|
||||
MBR_HEAD *pMBR;
|
||||
DWORD dwSize = 0;
|
||||
VTOY_GPT_HDR BackupHead;
|
||||
HANDLE hDrive = INVALID_HANDLE_VALUE;
|
||||
GUID ZeroGuid = { 0 };
|
||||
static GUID WindowsDataPartType = { 0xebd0a0a2, 0xb9e5, 0x4433, { 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7 } };
|
||||
static GUID EspPartType = { 0xc12a7328, 0xf81f, 0x11d2, { 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } };
|
||||
static GUID BiosGrubPartType = { 0x21686148, 0x6449, 0x6e6f, { 0x74, 0x4e, 0x65, 0x65, 0x64, 0x45, 0x46, 0x49 } };
|
||||
|
||||
Log("#####################################################");
|
||||
Log("PartitionResizeForVentoy PhyDrive%d <<%s %s %dGB>>",
|
||||
pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
|
||||
GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
|
||||
Log("#####################################################");
|
||||
|
||||
pGPT = &(pPhyDrive->Gpt);
|
||||
pMBR = &(pPhyDrive->Gpt.MBR);
|
||||
Log("Disksize:%llu Part2Start:%llu", pPhyDrive->SizeInBytes, pPhyDrive->ResizePart2StartSector * 512);
|
||||
|
||||
if (pMBR->PartTbl[0].FsFlag == 0xEE && memcmp(pGPT->Head.Signature, "EFI PART", 8) == 0)
|
||||
{
|
||||
PartStyle = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
PartStyle = 0;
|
||||
}
|
||||
|
||||
PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
|
||||
|
||||
RecudeBytes = VENTOY_EFI_PART_SIZE;
|
||||
ReservedValue = GetReservedSpaceInMB();
|
||||
if (ReservedValue > 0)
|
||||
{
|
||||
Log("Reduce add reserved space %lldMB", (LONGLONG)ReservedValue);
|
||||
RecudeBytes += (UINT64)(ReservedValue * SIZE_1MB);
|
||||
}
|
||||
|
||||
|
||||
if (pPhyDrive->ResizeNoShrink == FALSE)
|
||||
{
|
||||
Log("Need to shrink the volume");
|
||||
if (VDS_ShrinkVolume(pPhyDrive->ResizeVolumeGuid, RecudeBytes))
|
||||
{
|
||||
Log("Shrink volume success, now check again");
|
||||
|
||||
hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
|
||||
if (hDrive == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
Log("Failed to GetPhysicalHandle for update.");
|
||||
goto End;
|
||||
}
|
||||
|
||||
//Refresh Drive Layout
|
||||
DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
|
||||
|
||||
CHECK_CLOSE_HANDLE(hDrive);
|
||||
|
||||
|
||||
if (PartResizePreCheck(NULL) && pPhyDrive->ResizeNoShrink)
|
||||
{
|
||||
Log("Recheck after Shrink volume success");
|
||||
Log("After shrink Disksize:%llu Part2Start:%llu", pPhyDrive->SizeInBytes, pPhyDrive->ResizePart2StartSector * 512);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Recheck after Shrink volume failed %u", pPhyDrive->ResizeNoShrink);
|
||||
goto End;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Shrink volume failed");
|
||||
goto End;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Now try write data
|
||||
hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
|
||||
if (hDrive == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
Log("Failed to GetPhysicalHandle for update.");
|
||||
goto End;
|
||||
}
|
||||
|
||||
|
||||
//Write partition 2 data
|
||||
PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);
|
||||
if (0 != FormatPart2Fat(hDrive, pPhyDrive->ResizePart2StartSector))
|
||||
{
|
||||
Log("FormatPart2Fat failed.");
|
||||
goto End;
|
||||
}
|
||||
|
||||
//Write grub stage2 gap
|
||||
PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG);
|
||||
Log("Writing Boot Image ............................. ");
|
||||
if (WriteGrubStage1ToPhyDrive(hDrive, PartStyle) != 0)
|
||||
{
|
||||
Log("WriteGrubStage1ToPhyDrive failed.");
|
||||
goto End;
|
||||
}
|
||||
|
||||
|
||||
//Write partition table
|
||||
PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE);
|
||||
Log("Writing partition table ............................. ");
|
||||
|
||||
VentoyGetLocalBootImg(&MBR);
|
||||
CoCreateGuid(&Guid);
|
||||
memcpy(MBR.BootCode + 0x180, &Guid, 16);
|
||||
memcpy(pMBR->BootCode, MBR.BootCode, 440);
|
||||
|
||||
if (PartStyle == 0)
|
||||
{
|
||||
for (i = 1; i < 4; i++)
|
||||
{
|
||||
if (pMBR->PartTbl[i].SectorCount == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= 4)
|
||||
{
|
||||
Log("Can not find MBR free partition table");
|
||||
goto End;
|
||||
}
|
||||
|
||||
for (j = i - 1; j > 0; j--)
|
||||
{
|
||||
Log("Move MBR partition table %d --> %d", j + 1, j + 2);
|
||||
memcpy(pMBR->PartTbl + (j + 1), pMBR->PartTbl + j, sizeof(PART_TABLE));
|
||||
}
|
||||
|
||||
VentoyFillMBRLocation(pPhyDrive->SizeInBytes, (UINT32)pPhyDrive->ResizePart2StartSector, VENTOY_EFI_PART_SIZE / 512, pMBR->PartTbl + 1);
|
||||
pMBR->PartTbl[0].Active = 0x80; // bootable
|
||||
pMBR->PartTbl[1].Active = 0x00;
|
||||
pMBR->PartTbl[1].FsFlag = 0xEF; // EFI System Partition
|
||||
|
||||
if (!WriteDataToPhyDisk(hDrive, 0, pMBR, 512))
|
||||
{
|
||||
Log("Legacy BIOS write MBR failed");
|
||||
goto End;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 1; i < 128; i++)
|
||||
{
|
||||
if (memcmp(&(pGPT->PartTbl[i].PartGuid), &ZeroGuid, sizeof(GUID)) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= 128)
|
||||
{
|
||||
Log("Can not find GPT free partition table");
|
||||
goto End;
|
||||
}
|
||||
|
||||
for (j = i - 1; j > 0; j--)
|
||||
{
|
||||
Log("Move GPT partition table %d --> %d", j + 1, j + 2);
|
||||
memcpy(pGPT->PartTbl + (j + 1), pGPT->PartTbl + j, sizeof(VTOY_GPT_PART_TBL));
|
||||
}
|
||||
|
||||
|
||||
pMBR->BootCode[92] = 0x22;
|
||||
|
||||
// to fix windows issue
|
||||
memcpy(&(pGPT->PartTbl[1].PartType), &WindowsDataPartType, sizeof(GUID));
|
||||
CoCreateGuid(&(pGPT->PartTbl[1].PartGuid));
|
||||
|
||||
pGPT->PartTbl[1].StartLBA = pGPT->PartTbl[0].LastLBA + 1;
|
||||
pGPT->PartTbl[1].LastLBA = pGPT->PartTbl[1].StartLBA + VENTOY_EFI_PART_SIZE / 512 - 1;
|
||||
pGPT->PartTbl[1].Attr = 0xC000000000000001ULL;
|
||||
memcpy(pGPT->PartTbl[1].Name, L"VTOYEFI", 7 * 2);
|
||||
|
||||
//Update CRC
|
||||
pGPT->Head.PartTblCrc = VentoyCrc32(pGPT->PartTbl, sizeof(pGPT->PartTbl));
|
||||
pGPT->Head.Crc = VentoyCrc32(&(pGPT->Head), pGPT->Head.Length);
|
||||
|
||||
Log("pGPT->Head.EfiStartLBA=%llu", (ULONGLONG)pGPT->Head.EfiStartLBA);
|
||||
Log("pGPT->Head.EfiBackupLBA=%llu", (ULONGLONG)pGPT->Head.EfiBackupLBA);
|
||||
|
||||
VentoyFillBackupGptHead(pGPT, &BackupHead);
|
||||
if (!WriteDataToPhyDisk(hDrive, pGPT->Head.EfiBackupLBA * 512, &BackupHead, 512))
|
||||
{
|
||||
Log("UEFI write backup head failed");
|
||||
goto End;
|
||||
}
|
||||
|
||||
if (!WriteDataToPhyDisk(hDrive, (pGPT->Head.EfiBackupLBA - 32) * 512, pGPT->PartTbl, 512 * 32))
|
||||
{
|
||||
Log("UEFI write backup partition table failed");
|
||||
goto End;
|
||||
}
|
||||
|
||||
if (!WriteDataToPhyDisk(hDrive, 0, pGPT, 512 * 34))
|
||||
{
|
||||
Log("UEFI write MBR & Main partition table failed");
|
||||
goto End;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Refresh Drive Layout
|
||||
DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
|
||||
|
||||
//We must close handle here, because it will block the refresh bellow
|
||||
CHECK_CLOSE_HANDLE(hDrive);
|
||||
|
||||
Sleep(2000);
|
||||
|
||||
//Refresh disk list
|
||||
PhyDrive = pPhyDrive->PhyDrive;
|
||||
|
||||
Log("#### Now Refresh PhyDrive ####");
|
||||
Ventoy2DiskDestroy();
|
||||
Ventoy2DiskInit();
|
||||
|
||||
pPhyDrive = GetPhyDriveInfoByPhyDrive(PhyDrive);
|
||||
if (pPhyDrive)
|
||||
{
|
||||
if (pPhyDrive->VentoyVersion[0] == 0)
|
||||
{
|
||||
Log("After process the Ventoy version is still invalid");
|
||||
goto End;
|
||||
}
|
||||
|
||||
Log("### Ventoy non-destructive installation successfully finished <%s>", pPhyDrive->VentoyVersion);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("### Ventoy non-destructive installation successfully finished <not found>");
|
||||
}
|
||||
|
||||
InitComboxCtrl(g_DialogHwnd, PhyDrive);
|
||||
|
||||
rc = 0;
|
||||
|
||||
End:
|
||||
CHECK_CLOSE_HANDLE(hDrive);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static BOOL DiskCheckWriteAccess(HANDLE hDrive)
|
||||
{
|
||||
DWORD dwSize;
|
||||
|
Reference in New Issue
Block a user