1 /******************************************************************************
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
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.
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.
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/>.
28 #include "Ventoy2Disk.h"
29 #include "fat_filelib.h"
32 #define VDS_SET_ERROR SetLastError
33 #define IVdsServiceLoader_LoadService(This, pwszMachineName, ppService) (This)->lpVtbl->LoadService(This, pwszMachineName, ppService)
34 #define IVdsServiceLoader_Release(This) (This)->lpVtbl->Release(This)
35 #define IVdsService_QueryProviders(This, masks, ppEnum) (This)->lpVtbl->QueryProviders(This, masks, ppEnum)
36 #define IVdsService_WaitForServiceReady(This) ((This)->lpVtbl->WaitForServiceReady(This))
37 #define IVdsService_CleanupObsoleteMountPoints(This) ((This)->lpVtbl->CleanupObsoleteMountPoints(This))
38 #define IVdsService_Refresh(This) ((This)->lpVtbl->Refresh(This))
39 #define IVdsService_Reenumerate(This) ((This)->lpVtbl->Reenumerate(This))
40 #define IVdsSwProvider_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
41 #define IVdsProvider_Release(This) (This)->lpVtbl->Release(This)
42 #define IVdsSwProvider_QueryPacks(This, ppEnum) (This)->lpVtbl->QueryPacks(This, ppEnum)
43 #define IVdsSwProvider_Release(This) (This)->lpVtbl->Release(This)
44 #define IVdsPack_QueryDisks(This, ppEnum) (This)->lpVtbl->QueryDisks(This, ppEnum)
45 #define IVdsDisk_GetProperties(This, pDiskProperties) (This)->lpVtbl->GetProperties(This, pDiskProperties)
46 #define IVdsDisk_Release(This) (This)->lpVtbl->Release(This)
47 #define IVdsDisk_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
48 #define IVdsAdvancedDisk_QueryPartitions(This, ppPartitionPropArray, plNumberOfPartitions) (This)->lpVtbl->QueryPartitions(This, ppPartitionPropArray, plNumberOfPartitions)
49 #define IVdsAdvancedDisk_DeletePartition(This, ullOffset, bForce, bForceProtected) (This)->lpVtbl->DeletePartition(This, ullOffset, bForce, bForceProtected)
50 #define IVdsAdvancedDisk_Clean(This, bForce, bForceOEM, bFullClean, ppAsync) (This)->lpVtbl->Clean(This, bForce, bForceOEM, bFullClean, ppAsync)
51 #define IVdsAdvancedDisk_Release(This) (This)->lpVtbl->Release(This)
52 #define IEnumVdsObject_Next(This, celt, ppObjectArray, pcFetched) (This)->lpVtbl->Next(This, celt, ppObjectArray, pcFetched)
53 #define IVdsPack_QueryVolumes(This, ppEnum) (This)->lpVtbl->QueryVolumes(This, ppEnum)
54 #define IVdsVolume_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
55 #define IVdsVolume_Release(This) (This)->lpVtbl->Release(This)
56 #define IVdsVolumeMF3_QueryVolumeGuidPathnames(This, pwszPathArray, pulNumberOfPaths) (This)->lpVtbl->QueryVolumeGuidPathnames(This,pwszPathArray,pulNumberOfPaths)
57 #define IVdsVolumeMF3_FormatEx2(This, pwszFileSystemTypeName, usFileSystemRevision, ulDesiredUnitAllocationSize, pwszLabel, Options, ppAsync) (This)->lpVtbl->FormatEx2(This, pwszFileSystemTypeName, usFileSystemRevision, ulDesiredUnitAllocationSize, pwszLabel, Options, ppAsync)
58 #define IVdsVolumeMF3_Release(This) (This)->lpVtbl->Release(This)
59 #define IVdsVolume_GetProperties(This, pVolumeProperties) (This)->lpVtbl->GetProperties(This,pVolumeProperties)
60 #define IVdsAsync_Cancel(This) (This)->lpVtbl->Cancel(This)
61 #define IVdsAsync_QueryStatus(This,pHrResult,pulPercentCompleted) (This)->lpVtbl->QueryStatus(This,pHrResult,pulPercentCompleted)
62 #define IVdsAsync_Wait(This,pHrResult,pAsyncOut) (This)->lpVtbl->Wait(This,pHrResult,pAsyncOut)
63 #define IVdsAsync_Release(This) (This)->lpVtbl->Release(This)
65 #define IUnknown_QueryInterface(This, a, b) (This)->lpVtbl->QueryInterface(This,a,b)
66 #define IUnknown_Release(This) (This)->lpVtbl->Release(This)
69 * Delete all the partitions from a disk, using VDS
70 * Mostly copied from https://social.msdn.microsoft.com/Forums/vstudio/en-US/b90482ae-4e44-4b08-8731-81915030b32a/createpartition-using-vds-interface-throw-error-enointerface-dcom?forum=vcgeneral
72 BOOL
DeletePartitions(DWORD DriveIndex
, BOOL OnlyPart2
)
77 wchar_t wPhysicalName
[48];
78 IVdsServiceLoader
*pLoader
;
79 IVdsService
*pService
;
80 IEnumVdsObject
*pEnum
;
83 swprintf_s(wPhysicalName
, ARRAYSIZE(wPhysicalName
), L
"\\\\?\\PhysicalDrive%lu", DriveIndex
);
86 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
87 CoInitializeSecurity(NULL
, -1, NULL
, NULL
, RPC_C_AUTHN_LEVEL_CONNECT
,
88 RPC_C_IMP_LEVEL_IMPERSONATE
, NULL
, 0, NULL
);
90 // Create a VDS Loader Instance
91 hr
= CoCreateInstance(&CLSID_VdsLoader
, NULL
, CLSCTX_LOCAL_SERVER
| CLSCTX_REMOTE_SERVER
,
92 &IID_IVdsServiceLoader
, (void **)&pLoader
);
95 Log("Could not create VDS Loader Instance: %u", LASTERR
);
99 // Load the VDS Service
100 hr
= IVdsServiceLoader_LoadService(pLoader
, L
"", &pService
);
101 IVdsServiceLoader_Release(pLoader
);
104 Log("Could not load VDS Service: %u", LASTERR
);
108 // Wait for the Service to become ready if needed
109 hr
= IVdsService_WaitForServiceReady(pService
);
112 Log("VDS Service is not ready: %u", LASTERR
);
116 // Query the VDS Service Providers
117 hr
= IVdsService_QueryProviders(pService
, VDS_QUERY_SOFTWARE_PROVIDERS
, &pEnum
);
120 Log("Could not query VDS Service Providers: %u", LASTERR
);
124 while (IEnumVdsObject_Next(pEnum
, 1, &pUnk
, &ulFetched
) == S_OK
) {
125 IVdsProvider
*pProvider
;
126 IVdsSwProvider
*pSwProvider
;
127 IEnumVdsObject
*pEnumPack
;
131 hr
= IUnknown_QueryInterface(pUnk
, &IID_IVdsProvider
, (void **)&pProvider
);
132 IUnknown_Release(pUnk
);
135 Log("Could not get VDS Provider: %u", LASTERR
);
139 // Get VDS Software Provider
140 hr
= IVdsSwProvider_QueryInterface(pProvider
, &IID_IVdsSwProvider
, (void **)&pSwProvider
);
141 IVdsProvider_Release(pProvider
);
144 Log("Could not get VDS Software Provider: %u", LASTERR
);
148 // Get VDS Software Provider Packs
149 hr
= IVdsSwProvider_QueryPacks(pSwProvider
, &pEnumPack
);
150 IVdsSwProvider_Release(pSwProvider
);
153 Log("Could not get VDS Software Provider Packs: %u", LASTERR
);
157 // Enumerate Provider Packs
158 while (IEnumVdsObject_Next(pEnumPack
, 1, &pPackUnk
, &ulFetched
) == S_OK
) {
160 IEnumVdsObject
*pEnumDisk
;
163 hr
= IUnknown_QueryInterface(pPackUnk
, &IID_IVdsPack
, (void **)&pPack
);
164 IUnknown_Release(pPackUnk
);
167 Log("Could not query VDS Software Provider Pack: %u", LASTERR
);
171 // Use the pack interface to access the disks
172 hr
= IVdsPack_QueryDisks(pPack
, &pEnumDisk
);
175 Log("Could not query VDS disks: %u", LASTERR
);
180 while (IEnumVdsObject_Next(pEnumDisk
, 1, &pDiskUnk
, &ulFetched
) == S_OK
) {
181 VDS_DISK_PROP diskprop
;
182 VDS_PARTITION_PROP
* prop_array
;
183 LONG i
, prop_array_size
;
185 IVdsAdvancedDisk
*pAdvancedDisk
;
187 // Get the disk interface.
188 hr
= IUnknown_QueryInterface(pDiskUnk
, &IID_IVdsDisk
, (void **)&pDisk
);
191 Log("Could not query VDS Disk Interface: %u", LASTERR
);
195 // Get the disk properties
196 hr
= IVdsDisk_GetProperties(pDisk
, &diskprop
);
199 Log("Could not query VDS Disk Properties: %u", LASTERR
);
203 // Isolate the disk we want
204 if (_wcsicmp(wPhysicalName
, diskprop
.pwszName
) != 0) {
205 IVdsDisk_Release(pDisk
);
209 // Instantiate the AdvanceDisk interface for our disk.
210 hr
= IVdsDisk_QueryInterface(pDisk
, &IID_IVdsAdvancedDisk
, (void **)&pAdvancedDisk
);
211 IVdsDisk_Release(pDisk
);
214 Log("Could not access VDS Advanced Disk interface: %u", LASTERR
);
218 // Query the partition data, so we can get the start offset, which we need for deletion
219 hr
= IVdsAdvancedDisk_QueryPartitions(pAdvancedDisk
, &prop_array
, &prop_array_size
);
221 Log("Deleting ALL partition(s) from disk '%S':", diskprop
.pwszName
);
222 // Now go through each partition
223 for (i
= 0; i
< prop_array_size
; i
++) {
225 Log("* Partition %d (offset: %lld, size: %llu)", prop_array
[i
].ulPartitionNumber
,
226 prop_array
[i
].ullOffset
, (ULONGLONG
)prop_array
[i
].ullSize
);
228 if (OnlyPart2
&& prop_array
[i
].ullOffset
== 2048*512)
230 Log("Skip this partition...");
235 hr
= IVdsAdvancedDisk_DeletePartition(pAdvancedDisk
, prop_array
[i
].ullOffset
, TRUE
, TRUE
);
239 Log("Could not delete partitions: %u", LASTERR
);
245 Log("No partition to delete on disk '%S'", diskprop
.pwszName
);
248 CoTaskMemFree(prop_array
);
251 // Issue a Clean while we're at it
252 HRESULT hr2
= E_FAIL
;
255 hr
= IVdsAdvancedDisk_Clean(pAdvancedDisk
, TRUE
, FALSE
, FALSE
, &pAsync
);
256 while (SUCCEEDED(hr
)) {
257 if (IS_ERROR(FormatStatus
)) {
258 IVdsAsync_Cancel(pAsync
);
261 hr
= IVdsAsync_QueryStatus(pAsync
, &hr2
, &completed
);
266 if (hr
== VDS_E_OPERATION_PENDING
)
273 Log("Could not clean disk: %s", LASTERR
);
276 IVdsAdvancedDisk_Release(pAdvancedDisk
);
287 static DWORD
GetVentoyVolumeName(int PhyDrive
, UINT32 StartSectorId
, CHAR
*NameBuf
, UINT32 BufLen
, BOOL DelSlash
)
295 DWORD Status
= ERROR_NOT_FOUND
;
296 DISK_EXTENT
*pExtents
= NULL
;
297 CHAR VolumeName
[MAX_PATH
] = { 0 };
298 VOLUME_DISK_EXTENTS DiskExtents
;
300 PartOffset
= 512ULL * StartSectorId
;
302 Log("GetVentoyVolumeName PhyDrive %d PartOffset:%llu", PhyDrive
, (ULONGLONG
)PartOffset
);
304 hVolume
= FindFirstVolumeA(VolumeName
, sizeof(VolumeName
));
305 if (hVolume
== INVALID_HANDLE_VALUE
)
312 len
= strlen(VolumeName
);
313 Log("Find volume:%s", VolumeName
);
315 VolumeName
[len
- 1] = 0;
317 hDrive
= CreateFileA(VolumeName
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
318 if (hDrive
== INVALID_HANDLE_VALUE
)
323 bRet
= DeviceIoControl(hDrive
,
324 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
328 (DWORD
)(sizeof(DiskExtents
)),
332 Log("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS bRet:%u code:%u", bRet
, LASTERR
);
333 Log("NumberOfDiskExtents:%u DiskNumber:%u", DiskExtents
.NumberOfDiskExtents
, DiskExtents
.Extents
[0].DiskNumber
);
335 if (bRet
&& DiskExtents
.NumberOfDiskExtents
== 1)
337 pExtents
= DiskExtents
.Extents
;
339 Log("This volume DiskNumber:%u offset:%llu", pExtents
->DiskNumber
, (ULONGLONG
)pExtents
->StartingOffset
.QuadPart
);
340 if ((int)pExtents
->DiskNumber
== PhyDrive
&& pExtents
->StartingOffset
.QuadPart
== PartOffset
)
342 Log("This volume match");
346 VolumeName
[len
- 1] = '\\';
349 sprintf_s(NameBuf
, BufLen
, "%s", VolumeName
);
350 Status
= ERROR_SUCCESS
;
357 } while (FindNextVolumeA(hVolume
, VolumeName
, sizeof(VolumeName
)));
359 FindVolumeClose(hVolume
);
361 Log("GetVentoyVolumeName return %u", Status
);
365 static int GetLettersBelongPhyDrive(int PhyDrive
, char *DriveLetters
, size_t Length
)
370 CHAR
*StringBuf
= NULL
;
372 DataSize
= GetLogicalDriveStringsA(0, NULL
);
373 StringBuf
= (CHAR
*)malloc(DataSize
+ 1);
374 if (StringBuf
== NULL
)
379 GetLogicalDriveStringsA(DataSize
, StringBuf
);
381 for (Pos
= StringBuf
; *Pos
; Pos
+= strlen(Pos
) + 1)
383 if (n
< (int)Length
&& PhyDrive
== GetPhyDriveByLogicalDrive(Pos
[0]))
385 Log("%C: is belong to phydrive%d", Pos
[0], PhyDrive
);
386 DriveLetters
[n
++] = Pos
[0];
394 static HANDLE
GetPhysicalHandle(int Drive
, BOOLEAN bLockDrive
, BOOLEAN bWriteAccess
, BOOLEAN bWriteShare
)
400 HANDLE hDrive
= INVALID_HANDLE_VALUE
;
402 CHAR DevPath
[MAX_PATH
] = { 0 };
404 safe_sprintf(PhyDrive
, "\\\\.\\PhysicalDrive%d", Drive
);
406 if (0 == QueryDosDeviceA(PhyDrive
+ 4, DevPath
, sizeof(DevPath
)))
408 Log("QueryDosDeviceA failed error:%u", GetLastError());
409 strcpy_s(DevPath
, sizeof(DevPath
), "???");
413 Log("QueryDosDeviceA success %s", DevPath
);
416 for (i
= 0; i
< DRIVE_ACCESS_RETRIES
; i
++)
418 // Try without FILE_SHARE_WRITE (unless specifically requested) so that
419 // we won't be bothered by the OS or other apps when we set up our data.
420 // However this means we might have to wait for an access gap...
421 // We keep FILE_SHARE_READ though, as this shouldn't hurt us any, and is
422 // required for enumeration.
423 hDrive
= CreateFileA(PhyDrive
,
424 GENERIC_READ
| (bWriteAccess
? GENERIC_WRITE
: 0),
425 FILE_SHARE_READ
| (bWriteShare
? FILE_SHARE_WRITE
: 0),
428 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_NO_BUFFERING
| FILE_FLAG_WRITE_THROUGH
,
431 LastError
= GetLastError();
432 Log("[%d] CreateFileA %s code:%u %p", i
, PhyDrive
, LastError
, hDrive
);
434 if (hDrive
!= INVALID_HANDLE_VALUE
)
439 if ((LastError
!= ERROR_SHARING_VIOLATION
) && (LastError
!= ERROR_ACCESS_DENIED
))
446 Log("Waiting for access on %s [%s]...", PhyDrive
, DevPath
);
448 else if (!bWriteShare
&& (i
> DRIVE_ACCESS_RETRIES
/ 3))
450 // If we can't seem to get a hold of the drive for some time, try to enable FILE_SHARE_WRITE...
451 Log("Warning: Could not obtain exclusive rights. Retrying with write sharing enabled...");
454 // Try to report the process that is locking the drive
455 // We also use bit 6 as a flag to indicate that SearchProcess was called.
456 //access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE) | 0x40;
459 Sleep(DRIVE_ACCESS_TIMEOUT
/ DRIVE_ACCESS_RETRIES
);
462 if (hDrive
== INVALID_HANDLE_VALUE
)
464 Log("Could not open %s %u", PhyDrive
, LASTERR
);
470 Log("Opened %s for %s write access", PhyDrive
, bWriteShare
? "shared" : "exclusive");
475 if (DeviceIoControl(hDrive
, FSCTL_ALLOW_EXTENDED_DASD_IO
, NULL
, 0, NULL
, 0, &dwSize
, NULL
))
477 Log("I/O boundary checks disabled");
480 EndTime
= GetTickCount64() + DRIVE_ACCESS_TIMEOUT
;
483 if (DeviceIoControl(hDrive
, FSCTL_LOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
))
485 Log("FSCTL_LOCK_VOLUME success");
488 Sleep(DRIVE_ACCESS_TIMEOUT
/ DRIVE_ACCESS_RETRIES
);
489 } while (GetTickCount64() < EndTime
);
491 // If we reached this section, either we didn't manage to get a lock or the user cancelled
492 Log("Could not lock access to %s %u", PhyDrive
, LASTERR
);
494 // See if we can report the processes are accessing the drive
495 //if (!IS_ERROR(FormatStatus) && (access_mask == 0))
496 // access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE);
497 // Try to continue if the only access rights we saw were for read-only
498 //if ((access_mask & 0x07) != 0x01)
499 // safe_closehandle(hDrive);
501 CHECK_CLOSE_HANDLE(hDrive
);
506 if (hDrive
== INVALID_HANDLE_VALUE
)
508 Log("Can get handle of %s, maybe some process control it.", DevPath
);
514 int GetPhyDriveByLogicalDrive(int DriveLetter
)
519 VOLUME_DISK_EXTENTS DiskExtents
;
522 safe_sprintf(PhyPath
, "\\\\.\\%C:", (CHAR
)DriveLetter
);
524 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
525 if (Handle
== INVALID_HANDLE_VALUE
)
527 Log("Could not open the disk<%s>, error:%u", PhyPath
, LASTERR
);
531 Ret
= DeviceIoControl(Handle
,
532 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
536 (DWORD
)(sizeof(DiskExtents
)),
540 if (!Ret
|| DiskExtents
.NumberOfDiskExtents
== 0)
542 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath
, LASTERR
);
543 CHECK_CLOSE_HANDLE(Handle
);
546 CHECK_CLOSE_HANDLE(Handle
);
548 Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",
550 DiskExtents
.Extents
[0].DiskNumber
,
551 DiskExtents
.Extents
[0].StartingOffset
.QuadPart
,
552 DiskExtents
.Extents
[0].ExtentLength
.QuadPart
555 return (int)DiskExtents
.Extents
[0].DiskNumber
;
558 int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO
*pDriveList
, DWORD
*pDriveCount
)
566 DWORD DriveCount
= 0;
567 HANDLE Handle
= INVALID_HANDLE_VALUE
;
569 PHY_DRIVE_INFO
*CurDrive
= pDriveList
;
570 GET_LENGTH_INFORMATION LengthInfo
;
571 STORAGE_PROPERTY_QUERY Query
;
572 STORAGE_DESCRIPTOR_HEADER DevDescHeader
;
573 STORAGE_DEVICE_DESCRIPTOR
*pDevDesc
;
574 int PhyDriveId
[VENTOY_MAX_PHY_DRIVE
];
576 Count
= GetPhysicalDriveCount();
578 for (i
= 0; i
< Count
&& i
< VENTOY_MAX_PHY_DRIVE
; i
++)
583 dwBytes
= GetLogicalDrives();
584 Log("Logical Drives: 0x%x", dwBytes
);
589 id
= GetPhyDriveByLogicalDrive(Letter
);
590 Log("%C --> %d", Letter
, id
);
593 for (i
= 0; i
< Count
; i
++)
595 if (PhyDriveId
[i
] == id
)
603 Log("Add phy%d to list", i
);
604 PhyDriveId
[Count
] = id
;
614 for (i
= 0; i
< Count
&& DriveCount
< VENTOY_MAX_PHY_DRIVE
; i
++)
616 CHECK_CLOSE_HANDLE(Handle
);
618 safe_sprintf(PhyDrive
, "\\\\.\\PhysicalDrive%d", PhyDriveId
[i
]);
619 Handle
= CreateFileA(PhyDrive
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
620 Log("Create file Handle:%p %s status:%u", Handle
, PhyDrive
, LASTERR
);
622 if (Handle
== INVALID_HANDLE_VALUE
)
627 bRet
= DeviceIoControl(Handle
,
628 IOCTL_DISK_GET_LENGTH_INFO
, NULL
,
636 Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR
);
640 Log("PHYSICALDRIVE%d size %llu bytes", i
, (ULONGLONG
)LengthInfo
.Length
.QuadPart
);
642 Query
.PropertyId
= StorageDeviceProperty
;
643 Query
.QueryType
= PropertyStandardQuery
;
645 bRet
= DeviceIoControl(Handle
,
646 IOCTL_STORAGE_QUERY_PROPERTY
,
650 sizeof(STORAGE_DESCRIPTOR_HEADER
),
655 Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR
, dwBytes
);
659 pDevDesc
= (STORAGE_DEVICE_DESCRIPTOR
*)malloc(DevDescHeader
.Size
);
662 Log("failed to malloc error:%u len:%u", LASTERR
, DevDescHeader
.Size
);
666 bRet
= DeviceIoControl(Handle
,
667 IOCTL_STORAGE_QUERY_PROPERTY
,
676 Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR
, dwBytes
);
681 CurDrive
->PhyDrive
= i
;
682 CurDrive
->SizeInBytes
= LengthInfo
.Length
.QuadPart
;
683 CurDrive
->DeviceType
= pDevDesc
->DeviceType
;
684 CurDrive
->RemovableMedia
= pDevDesc
->RemovableMedia
;
685 CurDrive
->BusType
= pDevDesc
->BusType
;
687 if (pDevDesc
->VendorIdOffset
)
689 safe_strcpy(CurDrive
->VendorId
, (char *)pDevDesc
+ pDevDesc
->VendorIdOffset
);
690 TrimString(CurDrive
->VendorId
);
693 if (pDevDesc
->ProductIdOffset
)
695 safe_strcpy(CurDrive
->ProductId
, (char *)pDevDesc
+ pDevDesc
->ProductIdOffset
);
696 TrimString(CurDrive
->ProductId
);
699 if (pDevDesc
->ProductRevisionOffset
)
701 safe_strcpy(CurDrive
->ProductRev
, (char *)pDevDesc
+ pDevDesc
->ProductRevisionOffset
);
702 TrimString(CurDrive
->ProductRev
);
705 if (pDevDesc
->SerialNumberOffset
)
707 safe_strcpy(CurDrive
->SerialNumber
, (char *)pDevDesc
+ pDevDesc
->SerialNumberOffset
);
708 TrimString(CurDrive
->SerialNumber
);
716 CHECK_CLOSE_HANDLE(Handle
);
719 for (i
= 0, CurDrive
= pDriveList
; i
< (int)DriveCount
; i
++, CurDrive
++)
721 Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s",
722 CurDrive
->PhyDrive
, GetBusTypeString(CurDrive
->BusType
), CurDrive
->RemovableMedia
,
723 GetHumanReadableGBSize(CurDrive
->SizeInBytes
), CurDrive
->SizeInBytes
,
724 CurDrive
->VendorId
, CurDrive
->ProductId
);
727 *pDriveCount
= DriveCount
;
733 static HANDLE g_FatPhyDrive
;
734 static UINT64 g_Part2StartSec
;
735 static int GetVentoyVersionFromFatFile(CHAR
*VerBuf
, size_t BufLen
)
742 flfile
= fl_fopen("/grub/grub.cfg", "rb");
745 fl_fseek(flfile
, 0, SEEK_END
);
746 size
= (int)fl_ftell(flfile
);
748 fl_fseek(flfile
, 0, SEEK_SET
);
750 buf
= (char *)malloc(size
+ 1);
753 fl_fread(buf
, 1, size
, flfile
);
757 sprintf_s(VerBuf
, BufLen
, "%s", ParseVentoyVersionFromString(buf
));
767 static int VentoyFatDiskRead(uint32 Sector
, uint8
*Buffer
, uint32 SectorCount
)
772 LARGE_INTEGER liCurrentPosition
;
774 liCurrentPosition
.QuadPart
= Sector
+ g_Part2StartSec
;
775 liCurrentPosition
.QuadPart
*= 512;
776 SetFilePointerEx(g_FatPhyDrive
, liCurrentPosition
, &liCurrentPosition
, FILE_BEGIN
);
778 ReadSize
= (DWORD
)(SectorCount
* 512);
780 bRet
= ReadFile(g_FatPhyDrive
, Buffer
, ReadSize
, &dwSize
, NULL
);
781 if (bRet
== FALSE
|| dwSize
!= ReadSize
)
783 Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet
, ReadSize
, dwSize
, LASTERR
);
790 int GetVentoyVerInPhyDrive(const PHY_DRIVE_INFO
*pDriveInfo
, CHAR
*VerBuf
, size_t BufLen
)
795 hDrive
= GetPhysicalHandle(pDriveInfo
->PhyDrive
, FALSE
, FALSE
, FALSE
);
796 if (hDrive
== INVALID_HANDLE_VALUE
)
801 g_FatPhyDrive
= hDrive
;
802 g_Part2StartSec
= (pDriveInfo
->SizeInBytes
- VENTOY_EFI_PART_SIZE
) / 512;
804 Log("Parse FAT fs...");
808 if (0 == fl_attach_media(VentoyFatDiskRead
, NULL
))
810 rc
= GetVentoyVersionFromFatFile(VerBuf
, BufLen
);
819 CHECK_CLOSE_HANDLE(hDrive
);
828 static unsigned int g_disk_unxz_len
= 0;
829 static BYTE
*g_part_img_pos
= NULL
;
830 static BYTE
*g_part_img_buf
[VENTOY_EFI_PART_SIZE
/ SIZE_1MB
];
833 static int VentoyFatMemRead(uint32 Sector
, uint8
*Buffer
, uint32 SectorCount
)
839 for (i
= 0; i
< SectorCount
; i
++)
841 offset
= (Sector
+ i
) * 512;
843 if (g_part_img_buf
[1] == NULL
)
845 MbBuf
= g_part_img_buf
[0] + offset
;
846 memcpy(Buffer
+ i
* 512, MbBuf
, 512);
850 MbBuf
= g_part_img_buf
[offset
/ SIZE_1MB
];
851 memcpy(Buffer
+ i
* 512, MbBuf
+ (offset
% SIZE_1MB
), 512);
859 static int VentoyFatMemWrite(uint32 Sector
, uint8
*Buffer
, uint32 SectorCount
)
865 for (i
= 0; i
< SectorCount
; i
++)
867 offset
= (Sector
+ i
) * 512;
869 if (g_part_img_buf
[1] == NULL
)
871 MbBuf
= g_part_img_buf
[0] + offset
;
872 memcpy(MbBuf
, Buffer
+ i
* 512, 512);
876 MbBuf
= g_part_img_buf
[offset
/ SIZE_1MB
];
877 memcpy(MbBuf
+ (offset
% SIZE_1MB
), Buffer
+ i
* 512, 512);
884 int VentoyProcSecureBoot(BOOL SecureBoot
)
888 char *filebuf
= NULL
;
891 Log("VentoyProcSecureBoot %d ...", SecureBoot
);
895 Log("Secure boot is enabled ...");
901 if (0 == fl_attach_media(VentoyFatMemRead
, VentoyFatMemWrite
))
903 file
= fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
904 Log("Open ventoy efi file %p ", file
);
907 fl_fseek(file
, 0, SEEK_END
);
908 size
= (int)fl_ftell(file
);
909 fl_fseek(file
, 0, SEEK_SET
);
911 Log("ventoy efi file size %d ...", size
);
913 filebuf
= (char *)malloc(size
);
916 fl_fread(filebuf
, 1, size
, file
);
921 Log("Now delete all efi files ...");
922 fl_remove("/EFI/BOOT/BOOTX64.EFI");
923 fl_remove("/EFI/BOOT/grubx64.efi");
924 fl_remove("/EFI/BOOT/grubx64_real.efi");
925 fl_remove("/EFI/BOOT/MokManager.efi");
927 file
= fl_fopen("/EFI/BOOT/BOOTX64.EFI", "wb");
928 Log("Open bootx64 efi file %p ", file
);
933 fl_fwrite(filebuf
, 1, size
, file
);
958 static int disk_xz_flush(void *src
, unsigned int size
)
961 BYTE
*buf
= (BYTE
*)src
;
963 for (i
= 0; i
< size
; i
++)
965 *g_part_img_pos
= *buf
++;
968 if ((g_disk_unxz_len
% SIZE_1MB
) == 0)
970 g_part_img_pos
= g_part_img_buf
[g_disk_unxz_len
/ SIZE_1MB
];
981 static void unxz_error(char *x
)
986 static BOOL
TryWritePart2(HANDLE hDrive
, UINT64 StartSectorId
)
989 DWORD TrySize
= 16 * 1024;
992 unsigned char *data
= NULL
;
993 LARGE_INTEGER liCurrentPosition
;
995 liCurrentPosition
.QuadPart
= StartSectorId
* 512;
996 SetFilePointerEx(hDrive
, liCurrentPosition
, &liCurrentPosition
, FILE_BEGIN
);
998 Buffer
= malloc(TrySize
);
1000 bRet
= WriteFile(hDrive
, Buffer
, TrySize
, &dwSize
, NULL
);
1004 Log("Try write part2 bRet:%u dwSize:%u code:%u", bRet
, dwSize
, LASTERR
);
1006 if (bRet
&& dwSize
== TrySize
)
1014 static int FormatPart2Fat(HANDLE hDrive
, UINT64 StartSectorId
)
1023 unsigned char *data
= NULL
;
1024 LARGE_INTEGER liCurrentPosition
;
1026 Log("FormatPart2Fat ...");
1028 rc
= ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG
, 0, (void **)&data
, &len
);
1031 Log("Failed to read img file %p %u", data
, len
);
1035 liCurrentPosition
.QuadPart
= StartSectorId
* 512;
1036 SetFilePointerEx(hDrive
, liCurrentPosition
, &liCurrentPosition
, FILE_BEGIN
);
1038 memset(g_part_img_buf
, 0, sizeof(g_part_img_buf
));
1040 g_part_img_buf
[0] = (BYTE
*)malloc(VENTOY_EFI_PART_SIZE
);
1041 if (g_part_img_buf
[0])
1043 Log("Malloc whole img buffer success, now decompress ...");
1044 unxz(data
, len
, NULL
, NULL
, g_part_img_buf
[0], &writelen
, unxz_error
);
1046 if (len
== writelen
)
1048 Log("decompress finished success");
1050 VentoyProcSecureBoot(g_SecureBoot
);
1052 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
1055 bRet
= WriteFile(hDrive
, g_part_img_buf
[0] + i
* SIZE_1MB
, SIZE_1MB
, &dwSize
, NULL
);
1056 Log("Write part data bRet:%u dwSize:%u code:%u", bRet
, dwSize
, LASTERR
);
1064 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START
+ i
);
1070 Log("decompress finished failed");
1076 Log("Failed to malloc whole img size %u, now split it", VENTOY_EFI_PART_SIZE
);
1079 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
1081 g_part_img_buf
[i
] = (BYTE
*)malloc(SIZE_1MB
);
1082 if (g_part_img_buf
[i
] == NULL
)
1089 Log("Malloc part img buffer success, now decompress ...");
1091 g_part_img_pos
= g_part_img_buf
[0];
1093 unxz(data
, len
, NULL
, disk_xz_flush
, NULL
, NULL
, unxz_error
);
1095 if (g_disk_unxz_len
== VENTOY_EFI_PART_SIZE
)
1097 Log("decompress finished success");
1099 VentoyProcSecureBoot(g_SecureBoot
);
1101 for (int i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
1104 bRet
= WriteFile(hDrive
, g_part_img_buf
[i
], SIZE_1MB
, &dwSize
, NULL
);
1105 Log("Write part data bRet:%u dwSize:%u code:%u", bRet
, dwSize
, LASTERR
);
1113 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START
+ i
);
1119 Log("decompress finished failed");
1126 if (data
) free(data
);
1130 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
1132 if (g_part_img_buf
[i
]) free(g_part_img_buf
[i
]);
1137 if (g_part_img_buf
[0]) free(g_part_img_buf
[0]);
1143 static int WriteGrubStage1ToPhyDrive(HANDLE hDrive
)
1149 BYTE
*ImgBuf
= NULL
;
1150 BYTE
*RawBuf
= NULL
;
1152 Log("WriteGrubStage1ToPhyDrive ...");
1154 RawBuf
= (BYTE
*)malloc(SIZE_1MB
);
1160 if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG
, 0, (void **)&ImgBuf
, &Len
))
1162 Log("Failed to read stage1 img");
1167 unxz(ImgBuf
, Len
, NULL
, NULL
, RawBuf
, &readLen
, unxz_error
);
1169 SetFilePointer(hDrive
, 512, NULL
, FILE_BEGIN
);
1171 bRet
= WriteFile(hDrive
, RawBuf
, SIZE_1MB
- 512, &dwSize
, NULL
);
1172 Log("WriteFile Ret:%u dwSize:%u ErrCode:%u", bRet
, dwSize
, GetLastError());
1181 static int FormatPart1exFAT(UINT64 DiskSizeBytes
)
1187 Option
.fmt
= FM_EXFAT
;
1192 // < 32GB select 32KB as cluster size
1193 // > 32GB select 128KB as cluster size
1194 if (DiskSizeBytes
/ 1024 / 1024 / 1024 <= 32)
1196 Option
.au_size
= 32768;
1200 Option
.au_size
= 131072;
1203 Log("Formatting Part1 exFAT ...");
1205 Ret
= f_mkfs(TEXT("0:"), &Option
, 0, 8 * 1024 * 1024);
1209 Log("Formatting Part1 exFAT success");
1211 Ret
= f_mount(&fs
, TEXT("0:"), 1);
1212 Log("mount part %d", Ret
);
1216 Ret
= f_setlabel(TEXT("Ventoy"));
1217 Log("f_setlabel %d", Ret
);
1219 Ret
= f_mount(0, TEXT("0:"), 1);
1220 Log("umount part %d", Ret
);
1227 Log("Formatting Part1 exFAT failed");
1233 int InstallVentoy2PhyDrive(PHY_DRIVE_INFO
*pPhyDrive
)
1242 CHAR DriveName
[] = "?:\\";
1243 CHAR DriveLetters
[MAX_PATH
] = { 0 };
1246 Log("InstallVentoy2PhyDrive PhyDrive%d <<%s %s %dGB>>",
1247 pPhyDrive
->PhyDrive
, pPhyDrive
->VendorId
, pPhyDrive
->ProductId
,
1248 GetHumanReadableGBSize(pPhyDrive
->SizeInBytes
));
1250 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
1252 VentoyFillMBR(pPhyDrive
->SizeInBytes
, &MBR
);
1254 Log("Lock disk for clean ............................. ");
1256 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, FALSE
, FALSE
);
1257 if (hDrive
== INVALID_HANDLE_VALUE
)
1259 Log("Failed to open physical disk");
1263 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
1265 if (DriveLetters
[0] == 0)
1267 Log("No drive letter was assigned...");
1268 DriveName
[0] = GetFirstUnusedDriveLetter();
1269 Log("GetFirstUnusedDriveLetter %C: ...", DriveName
[0]);
1273 // Unmount all mounted volumes that belong to this drive
1274 // Do it in reverse so that we always end on the first volume letter
1275 for (i
= (int)strlen(DriveLetters
); i
> 0; i
--)
1277 DriveName
[0] = DriveLetters
[i
- 1];
1278 bRet
= DeleteVolumeMountPointA(DriveName
);
1279 Log("Delete mountpoint %s ret:%u code:%u", DriveName
, bRet
, GetLastError());
1283 MountDrive
= DriveName
[0];
1284 Log("Will use '%C:' as volume mountpoint", DriveName
[0]);
1286 // It kind of blows, but we have to relinquish access to the physical drive
1287 // for VDS to be able to delete the partitions that reside on it...
1288 DeviceIoControl(hDrive
, FSCTL_UNLOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1289 CHECK_CLOSE_HANDLE(hDrive
);
1291 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART
);
1293 if (!DeletePartitions(pPhyDrive
->PhyDrive
, FALSE
))
1295 Log("Notice: Could not delete partitions: %u", GetLastError());
1298 Log("Deleting all partitions ......................... OK");
1300 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE
);
1302 Log("Lock disk for write ............................. ");
1303 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
1304 if (hDrive
== INVALID_HANDLE_VALUE
)
1306 Log("Failed to GetPhysicalHandle for write.");
1311 //Refresh Drive Layout
1312 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1314 disk_io_set_param(hDrive
, MBR
.PartTbl
[0].StartSectorId
+ MBR
.PartTbl
[0].SectorCount
);
1316 PROGRESS_BAR_SET_POS(PT_FORMAT_PART1
);
1318 Log("Formatting part1 exFAT ...");
1319 if (0 != FormatPart1exFAT(pPhyDrive
->SizeInBytes
))
1325 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2
);
1326 Log("Writing part2 FAT img ...");
1327 if (0 != FormatPart2Fat(hDrive
, MBR
.PartTbl
[1].StartSectorId
))
1333 PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG
);
1334 Log("Writting Boot Image ............................. ");
1335 if (WriteGrubStage1ToPhyDrive(hDrive
) != 0)
1342 PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE
);
1343 Log("Writting Partition Table ........................ ");
1344 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
1345 if (!WriteFile(hDrive
, &MBR
, sizeof(MBR
), &dwSize
, NULL
))
1348 Log("Write MBR Failed, dwSize:%u ErrCode:%u", dwSize
, GetLastError());
1352 Log("Write MBR OK ...");
1354 //Refresh Drive Layout
1355 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1358 CHECK_CLOSE_HANDLE(hDrive
);
1360 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME
);
1361 Log("Mounting Ventoy Partition ....................... ");
1365 memset(DriveLetters
, 0, sizeof(DriveLetters
));
1366 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
1367 Log("Logical drive letter after write ventoy: <%s>", DriveLetters
);
1369 for (i
= 0; i
< sizeof(DriveLetters
) && DriveLetters
[i
]; i
++)
1371 DriveName
[0] = DriveLetters
[i
];
1372 if (IsVentoyLogicalDrive(DriveName
[0]))
1374 Log("%s is ventoy part2, delete mountpoint", DriveName
);
1375 DeleteVolumeMountPointA(DriveName
);
1379 Log("%s is ventoy part1, already mounted", DriveName
);
1386 Log("need to mount ventoy part1...");
1387 if (0 == GetVentoyVolumeName(pPhyDrive
->PhyDrive
, MBR
.PartTbl
[0].StartSectorId
, DriveLetters
, sizeof(DriveLetters
), FALSE
))
1389 DriveName
[0] = MountDrive
;
1390 bRet
= SetVolumeMountPointA(DriveName
, DriveLetters
);
1391 Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName
, DriveLetters
, bRet
, GetLastError());
1395 Log("Failed to find ventoy volume");
1404 int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO
*pPhyDrive
)
1408 BOOL ForceMBR
= FALSE
;
1414 CHAR DriveName
[] = "?:\\";
1415 CHAR DriveLetters
[MAX_PATH
] = { 0 };
1420 StartSector
= (UINT32
)(pPhyDrive
->SizeInBytes
/ 512 - VENTOY_EFI_PART_SIZE
/ 512);
1422 Log("UpdateVentoy2PhyDrive PhyDrive%d <<%s %s %dGB>>",
1423 pPhyDrive
->PhyDrive
, pPhyDrive
->VendorId
, pPhyDrive
->ProductId
,
1424 GetHumanReadableGBSize(pPhyDrive
->SizeInBytes
));
1426 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
1428 Log("Lock disk for umount ............................ ");
1430 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, FALSE
, FALSE
);
1431 if (hDrive
== INVALID_HANDLE_VALUE
)
1433 Log("Failed to open physical disk");
1438 ReadFile(hDrive
, &MBR
, sizeof(MBR
), &dwSize
, NULL
);
1440 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
1442 if (DriveLetters
[0] == 0)
1444 Log("No drive letter was assigned...");
1448 // Unmount all mounted volumes that belong to this drive
1449 // Do it in reverse so that we always end on the first volume letter
1450 for (i
= (int)strlen(DriveLetters
); i
> 0; i
--)
1452 DriveName
[0] = DriveLetters
[i
- 1];
1453 if (IsVentoyLogicalDrive(DriveName
[0]))
1455 Log("%s is ventoy logical drive", DriveName
);
1456 bRet
= DeleteVolumeMountPointA(DriveName
);
1457 Log("Delete mountpoint %s ret:%u code:%u", DriveName
, bRet
, LASTERR
);
1463 // It kind of blows, but we have to relinquish access to the physical drive
1464 // for VDS to be able to delete the partitions that reside on it...
1465 DeviceIoControl(hDrive
, FSCTL_UNLOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1466 CHECK_CLOSE_HANDLE(hDrive
);
1468 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE
);
1470 Log("Lock disk for update ............................ ");
1471 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
1472 if (hDrive
== INVALID_HANDLE_VALUE
)
1474 Log("Failed to GetPhysicalHandle for write.");
1479 PROGRESS_BAR_SET_POS(PT_LOCK_VOLUME
);
1481 Log("Lock volume for update .......................... ");
1482 hVolume
= INVALID_HANDLE_VALUE
;
1483 Status
= GetVentoyVolumeName(pPhyDrive
->PhyDrive
, MBR
.PartTbl
[1].StartSectorId
, DriveLetters
, sizeof(DriveLetters
), TRUE
);
1484 if (ERROR_SUCCESS
== Status
)
1486 Log("Now lock and dismount volume <%s>", DriveLetters
);
1487 hVolume
= CreateFileA(DriveLetters
,
1488 GENERIC_READ
| GENERIC_WRITE
,
1492 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_NO_BUFFERING
| FILE_FLAG_WRITE_THROUGH
,
1495 if (hVolume
== INVALID_HANDLE_VALUE
)
1497 Log("Failed to create file volume, errcode:%u", LASTERR
);
1502 bRet
= DeviceIoControl(hVolume
, FSCTL_LOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1503 Log("FSCTL_LOCK_VOLUME bRet:%u code:%u", bRet
, LASTERR
);
1505 bRet
= DeviceIoControl(hVolume
, FSCTL_DISMOUNT_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1506 Log("FSCTL_DISMOUNT_VOLUME bRet:%u code:%u", bRet
, LASTERR
);
1508 else if (ERROR_NOT_FOUND
== Status
)
1510 Log("Volume not found, maybe not supported");
1519 if (!TryWritePart2(hDrive
, StartSector
))
1522 Log("Try write failed, now delete partition 2...");
1524 CHECK_CLOSE_HANDLE(hDrive
);
1526 Log("Now delete partition 2...");
1527 DeletePartitions(pPhyDrive
->PhyDrive
, TRUE
);
1529 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
1530 if (hDrive
== INVALID_HANDLE_VALUE
)
1532 Log("Failed to GetPhysicalHandle for write.");
1539 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2
);
1541 Log("Write Ventoy to disk ............................ ");
1542 if (0 != FormatPart2Fat(hDrive
, StartSector
))
1548 if (hVolume
!= INVALID_HANDLE_VALUE
)
1550 bRet
= DeviceIoControl(hVolume
, FSCTL_UNLOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1551 Log("FSCTL_UNLOCK_VOLUME bRet:%u code:%u", bRet
, LASTERR
);
1552 CHECK_CLOSE_HANDLE(hVolume
);
1555 Log("Updating Boot Image ............................. ");
1556 if (WriteGrubStage1ToPhyDrive(hDrive
) != 0)
1563 VentoyGetLocalBootImg(&BootImg
);
1566 memcpy(BootImg
.BootCode
+ 0x180, MBR
.BootCode
+ 0x180, 16);
1568 if (ForceMBR
== FALSE
&& memcmp(BootImg
.BootCode
, MBR
.BootCode
, 440) == 0)
1570 Log("Boot image has no difference, no need to write.");
1574 Log("Boot image need to write %u.", ForceMBR
);
1576 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
1578 memcpy(MBR
.BootCode
, BootImg
.BootCode
, 440);
1579 bRet
= WriteFile(hDrive
, &MBR
, 512, &dwSize
, NULL
);
1580 Log("Write Boot Image ret:%u dwSize:%u Error:%u", bRet
, dwSize
, LASTERR
);
1583 //Refresh Drive Layout
1584 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1587 CHECK_CLOSE_HANDLE(hDrive
);