1 /******************************************************************************
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
5 * Copyright (c) 2011-2020, Pete Batard <pete@akeo.ie>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 3 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
29 #include "Ventoy2Disk.h"
30 #include "fat_filelib.h"
34 * Some code and functions in the file are copied from rufus.
35 * https://github.com/pbatard/rufus
37 #define VDS_SET_ERROR SetLastError
38 #define IVdsServiceLoader_LoadService(This, pwszMachineName, ppService) (This)->lpVtbl->LoadService(This, pwszMachineName, ppService)
39 #define IVdsServiceLoader_Release(This) (This)->lpVtbl->Release(This)
40 #define IVdsService_QueryProviders(This, masks, ppEnum) (This)->lpVtbl->QueryProviders(This, masks, ppEnum)
41 #define IVdsService_WaitForServiceReady(This) ((This)->lpVtbl->WaitForServiceReady(This))
42 #define IVdsService_CleanupObsoleteMountPoints(This) ((This)->lpVtbl->CleanupObsoleteMountPoints(This))
43 #define IVdsService_Refresh(This) ((This)->lpVtbl->Refresh(This))
44 #define IVdsService_Reenumerate(This) ((This)->lpVtbl->Reenumerate(This))
45 #define IVdsSwProvider_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
46 #define IVdsProvider_Release(This) (This)->lpVtbl->Release(This)
47 #define IVdsSwProvider_QueryPacks(This, ppEnum) (This)->lpVtbl->QueryPacks(This, ppEnum)
48 #define IVdsSwProvider_Release(This) (This)->lpVtbl->Release(This)
49 #define IVdsPack_QueryDisks(This, ppEnum) (This)->lpVtbl->QueryDisks(This, ppEnum)
50 #define IVdsDisk_GetProperties(This, pDiskProperties) (This)->lpVtbl->GetProperties(This, pDiskProperties)
51 #define IVdsDisk_Release(This) (This)->lpVtbl->Release(This)
52 #define IVdsDisk_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
53 #define IVdsAdvancedDisk_QueryPartitions(This, ppPartitionPropArray, plNumberOfPartitions) (This)->lpVtbl->QueryPartitions(This, ppPartitionPropArray, plNumberOfPartitions)
54 #define IVdsAdvancedDisk_DeletePartition(This, ullOffset, bForce, bForceProtected) (This)->lpVtbl->DeletePartition(This, ullOffset, bForce, bForceProtected)
55 #define IVdsAdvancedDisk_Clean(This, bForce, bForceOEM, bFullClean, ppAsync) (This)->lpVtbl->Clean(This, bForce, bForceOEM, bFullClean, ppAsync)
56 #define IVdsAdvancedDisk_Release(This) (This)->lpVtbl->Release(This)
57 #define IEnumVdsObject_Next(This, celt, ppObjectArray, pcFetched) (This)->lpVtbl->Next(This, celt, ppObjectArray, pcFetched)
58 #define IVdsPack_QueryVolumes(This, ppEnum) (This)->lpVtbl->QueryVolumes(This, ppEnum)
59 #define IVdsVolume_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
60 #define IVdsVolume_Release(This) (This)->lpVtbl->Release(This)
61 #define IVdsVolumeMF3_QueryVolumeGuidPathnames(This, pwszPathArray, pulNumberOfPaths) (This)->lpVtbl->QueryVolumeGuidPathnames(This,pwszPathArray,pulNumberOfPaths)
62 #define IVdsVolumeMF3_FormatEx2(This, pwszFileSystemTypeName, usFileSystemRevision, ulDesiredUnitAllocationSize, pwszLabel, Options, ppAsync) (This)->lpVtbl->FormatEx2(This, pwszFileSystemTypeName, usFileSystemRevision, ulDesiredUnitAllocationSize, pwszLabel, Options, ppAsync)
63 #define IVdsVolumeMF3_Release(This) (This)->lpVtbl->Release(This)
64 #define IVdsVolume_GetProperties(This, pVolumeProperties) (This)->lpVtbl->GetProperties(This,pVolumeProperties)
65 #define IVdsAsync_Cancel(This) (This)->lpVtbl->Cancel(This)
66 #define IVdsAsync_QueryStatus(This,pHrResult,pulPercentCompleted) (This)->lpVtbl->QueryStatus(This,pHrResult,pulPercentCompleted)
67 #define IVdsAsync_Wait(This,pHrResult,pAsyncOut) (This)->lpVtbl->Wait(This,pHrResult,pAsyncOut)
68 #define IVdsAsync_Release(This) (This)->lpVtbl->Release(This)
70 #define IUnknown_QueryInterface(This, a, b) (This)->lpVtbl->QueryInterface(This,a,b)
71 #define IUnknown_Release(This) (This)->lpVtbl->Release(This)
74 * Delete all the partitions from a disk, using VDS
75 * 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
77 BOOL
DeletePartitions(DWORD DriveIndex
, BOOL OnlyPart2
)
82 wchar_t wPhysicalName
[48];
83 IVdsServiceLoader
*pLoader
;
84 IVdsService
*pService
;
85 IEnumVdsObject
*pEnum
;
88 swprintf_s(wPhysicalName
, ARRAYSIZE(wPhysicalName
), L
"\\\\?\\PhysicalDrive%lu", DriveIndex
);
91 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
92 CoInitializeSecurity(NULL
, -1, NULL
, NULL
, RPC_C_AUTHN_LEVEL_CONNECT
,
93 RPC_C_IMP_LEVEL_IMPERSONATE
, NULL
, 0, NULL
);
95 // Create a VDS Loader Instance
96 hr
= CoCreateInstance(&CLSID_VdsLoader
, NULL
, CLSCTX_LOCAL_SERVER
| CLSCTX_REMOTE_SERVER
,
97 &IID_IVdsServiceLoader
, (void **)&pLoader
);
100 Log("Could not create VDS Loader Instance: %u", LASTERR
);
104 // Load the VDS Service
105 hr
= IVdsServiceLoader_LoadService(pLoader
, L
"", &pService
);
106 IVdsServiceLoader_Release(pLoader
);
109 Log("Could not load VDS Service: %u", LASTERR
);
113 // Wait for the Service to become ready if needed
114 hr
= IVdsService_WaitForServiceReady(pService
);
117 Log("VDS Service is not ready: %u", LASTERR
);
121 // Query the VDS Service Providers
122 hr
= IVdsService_QueryProviders(pService
, VDS_QUERY_SOFTWARE_PROVIDERS
, &pEnum
);
125 Log("Could not query VDS Service Providers: %u", LASTERR
);
129 while (IEnumVdsObject_Next(pEnum
, 1, &pUnk
, &ulFetched
) == S_OK
) {
130 IVdsProvider
*pProvider
;
131 IVdsSwProvider
*pSwProvider
;
132 IEnumVdsObject
*pEnumPack
;
136 hr
= IUnknown_QueryInterface(pUnk
, &IID_IVdsProvider
, (void **)&pProvider
);
137 IUnknown_Release(pUnk
);
140 Log("Could not get VDS Provider: %u", LASTERR
);
144 // Get VDS Software Provider
145 hr
= IVdsSwProvider_QueryInterface(pProvider
, &IID_IVdsSwProvider
, (void **)&pSwProvider
);
146 IVdsProvider_Release(pProvider
);
149 Log("Could not get VDS Software Provider: %u", LASTERR
);
153 // Get VDS Software Provider Packs
154 hr
= IVdsSwProvider_QueryPacks(pSwProvider
, &pEnumPack
);
155 IVdsSwProvider_Release(pSwProvider
);
158 Log("Could not get VDS Software Provider Packs: %u", LASTERR
);
162 // Enumerate Provider Packs
163 while (IEnumVdsObject_Next(pEnumPack
, 1, &pPackUnk
, &ulFetched
) == S_OK
) {
165 IEnumVdsObject
*pEnumDisk
;
168 hr
= IUnknown_QueryInterface(pPackUnk
, &IID_IVdsPack
, (void **)&pPack
);
169 IUnknown_Release(pPackUnk
);
172 Log("Could not query VDS Software Provider Pack: %u", LASTERR
);
176 // Use the pack interface to access the disks
177 hr
= IVdsPack_QueryDisks(pPack
, &pEnumDisk
);
180 Log("Could not query VDS disks: %u", LASTERR
);
185 while (IEnumVdsObject_Next(pEnumDisk
, 1, &pDiskUnk
, &ulFetched
) == S_OK
) {
186 VDS_DISK_PROP diskprop
;
187 VDS_PARTITION_PROP
* prop_array
;
188 LONG i
, prop_array_size
;
190 IVdsAdvancedDisk
*pAdvancedDisk
;
192 // Get the disk interface.
193 hr
= IUnknown_QueryInterface(pDiskUnk
, &IID_IVdsDisk
, (void **)&pDisk
);
196 Log("Could not query VDS Disk Interface: %u", LASTERR
);
200 // Get the disk properties
201 hr
= IVdsDisk_GetProperties(pDisk
, &diskprop
);
204 Log("Could not query VDS Disk Properties: %u", LASTERR
);
208 // Isolate the disk we want
209 if (_wcsicmp(wPhysicalName
, diskprop
.pwszName
) != 0) {
210 IVdsDisk_Release(pDisk
);
214 // Instantiate the AdvanceDisk interface for our disk.
215 hr
= IVdsDisk_QueryInterface(pDisk
, &IID_IVdsAdvancedDisk
, (void **)&pAdvancedDisk
);
216 IVdsDisk_Release(pDisk
);
219 Log("Could not access VDS Advanced Disk interface: %u", LASTERR
);
223 // Query the partition data, so we can get the start offset, which we need for deletion
224 hr
= IVdsAdvancedDisk_QueryPartitions(pAdvancedDisk
, &prop_array
, &prop_array_size
);
226 Log("Deleting ALL partition(s) from disk '%S':", diskprop
.pwszName
);
227 // Now go through each partition
228 for (i
= 0; i
< prop_array_size
; i
++) {
230 Log("* Partition %d (offset: %lld, size: %llu)", prop_array
[i
].ulPartitionNumber
,
231 prop_array
[i
].ullOffset
, (ULONGLONG
)prop_array
[i
].ullSize
);
235 if (prop_array
[i
].ullOffset
== 2048 * 512 || prop_array
[i
].ullSize
!= 32 * 1024 * 1024)
237 Log("Skip this partition...");
242 hr
= IVdsAdvancedDisk_DeletePartition(pAdvancedDisk
, prop_array
[i
].ullOffset
, TRUE
, TRUE
);
246 Log("Could not delete partitions: %u", LASTERR
);
249 Log("Delete this partitions success");
255 Log("No partition to delete on disk '%S'", diskprop
.pwszName
);
258 CoTaskMemFree(prop_array
);
261 // Issue a Clean while we're at it
262 HRESULT hr2
= E_FAIL
;
265 hr
= IVdsAdvancedDisk_Clean(pAdvancedDisk
, TRUE
, FALSE
, FALSE
, &pAsync
);
266 while (SUCCEEDED(hr
)) {
267 if (IS_ERROR(FormatStatus
)) {
268 IVdsAsync_Cancel(pAsync
);
271 hr
= IVdsAsync_QueryStatus(pAsync
, &hr2
, &completed
);
276 if (hr
== VDS_E_OPERATION_PENDING
)
283 Log("Could not clean disk: %s", LASTERR
);
286 IVdsAdvancedDisk_Release(pAdvancedDisk
);
297 static DWORD
GetVentoyVolumeName(int PhyDrive
, UINT64 StartSectorId
, CHAR
*NameBuf
, UINT32 BufLen
, BOOL DelSlash
)
305 DWORD Status
= ERROR_NOT_FOUND
;
306 DISK_EXTENT
*pExtents
= NULL
;
307 CHAR VolumeName
[MAX_PATH
] = { 0 };
308 VOLUME_DISK_EXTENTS DiskExtents
;
310 PartOffset
= 512ULL * StartSectorId
;
312 Log("GetVentoyVolumeName PhyDrive %d SectorStart:%llu PartOffset:%llu", PhyDrive
, (ULONGLONG
)StartSectorId
, (ULONGLONG
)PartOffset
);
314 hVolume
= FindFirstVolumeA(VolumeName
, sizeof(VolumeName
));
315 if (hVolume
== INVALID_HANDLE_VALUE
)
322 len
= strlen(VolumeName
);
323 Log("Find volume:%s", VolumeName
);
325 VolumeName
[len
- 1] = 0;
327 hDrive
= CreateFileA(VolumeName
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
328 if (hDrive
== INVALID_HANDLE_VALUE
)
333 bRet
= DeviceIoControl(hDrive
,
334 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
338 (DWORD
)(sizeof(DiskExtents
)),
342 Log("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS bRet:%u code:%u", bRet
, LASTERR
);
343 Log("NumberOfDiskExtents:%u DiskNumber:%u", DiskExtents
.NumberOfDiskExtents
, DiskExtents
.Extents
[0].DiskNumber
);
345 if (bRet
&& DiskExtents
.NumberOfDiskExtents
== 1)
347 pExtents
= DiskExtents
.Extents
;
349 Log("This volume DiskNumber:%u offset:%llu", pExtents
->DiskNumber
, (ULONGLONG
)pExtents
->StartingOffset
.QuadPart
);
350 if ((int)pExtents
->DiskNumber
== PhyDrive
&& pExtents
->StartingOffset
.QuadPart
== PartOffset
)
352 Log("This volume match");
356 VolumeName
[len
- 1] = '\\';
359 sprintf_s(NameBuf
, BufLen
, "%s", VolumeName
);
360 Status
= ERROR_SUCCESS
;
367 } while (FindNextVolumeA(hVolume
, VolumeName
, sizeof(VolumeName
)));
369 FindVolumeClose(hVolume
);
371 Log("GetVentoyVolumeName return %u", Status
);
375 static int GetLettersBelongPhyDrive(int PhyDrive
, char *DriveLetters
, size_t Length
)
380 CHAR
*StringBuf
= NULL
;
382 DataSize
= GetLogicalDriveStringsA(0, NULL
);
383 StringBuf
= (CHAR
*)malloc(DataSize
+ 1);
384 if (StringBuf
== NULL
)
389 GetLogicalDriveStringsA(DataSize
, StringBuf
);
391 for (Pos
= StringBuf
; *Pos
; Pos
+= strlen(Pos
) + 1)
393 if (n
< (int)Length
&& PhyDrive
== GetPhyDriveByLogicalDrive(Pos
[0]))
395 Log("%C: is belong to phydrive%d", Pos
[0], PhyDrive
);
396 DriveLetters
[n
++] = Pos
[0];
404 static HANDLE
GetPhysicalHandle(int Drive
, BOOLEAN bLockDrive
, BOOLEAN bWriteAccess
, BOOLEAN bWriteShare
)
410 HANDLE hDrive
= INVALID_HANDLE_VALUE
;
412 CHAR DevPath
[MAX_PATH
] = { 0 };
414 safe_sprintf(PhyDrive
, "\\\\.\\PhysicalDrive%d", Drive
);
416 if (0 == QueryDosDeviceA(PhyDrive
+ 4, DevPath
, sizeof(DevPath
)))
418 Log("QueryDosDeviceA failed error:%u", GetLastError());
419 strcpy_s(DevPath
, sizeof(DevPath
), "???");
423 Log("QueryDosDeviceA success %s", DevPath
);
426 for (i
= 0; i
< DRIVE_ACCESS_RETRIES
; i
++)
428 // Try without FILE_SHARE_WRITE (unless specifically requested) so that
429 // we won't be bothered by the OS or other apps when we set up our data.
430 // However this means we might have to wait for an access gap...
431 // We keep FILE_SHARE_READ though, as this shouldn't hurt us any, and is
432 // required for enumeration.
433 hDrive
= CreateFileA(PhyDrive
,
434 GENERIC_READ
| (bWriteAccess
? GENERIC_WRITE
: 0),
435 FILE_SHARE_READ
| (bWriteShare
? FILE_SHARE_WRITE
: 0),
438 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_NO_BUFFERING
| FILE_FLAG_WRITE_THROUGH
,
441 LastError
= GetLastError();
442 Log("[%d] CreateFileA %s code:%u %p", i
, PhyDrive
, LastError
, hDrive
);
444 if (hDrive
!= INVALID_HANDLE_VALUE
)
449 if ((LastError
!= ERROR_SHARING_VIOLATION
) && (LastError
!= ERROR_ACCESS_DENIED
))
456 Log("Waiting for access on %s [%s]...", PhyDrive
, DevPath
);
458 else if (!bWriteShare
&& (i
> DRIVE_ACCESS_RETRIES
/ 3))
460 // If we can't seem to get a hold of the drive for some time, try to enable FILE_SHARE_WRITE...
461 Log("Warning: Could not obtain exclusive rights. Retrying with write sharing enabled...");
464 // Try to report the process that is locking the drive
465 // We also use bit 6 as a flag to indicate that SearchProcess was called.
466 //access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE) | 0x40;
469 Sleep(DRIVE_ACCESS_TIMEOUT
/ DRIVE_ACCESS_RETRIES
);
472 if (hDrive
== INVALID_HANDLE_VALUE
)
474 Log("Could not open %s %u", PhyDrive
, LASTERR
);
480 Log("Opened %s for %s write access", PhyDrive
, bWriteShare
? "shared" : "exclusive");
485 if (DeviceIoControl(hDrive
, FSCTL_ALLOW_EXTENDED_DASD_IO
, NULL
, 0, NULL
, 0, &dwSize
, NULL
))
487 Log("I/O boundary checks disabled");
490 EndTime
= GetTickCount64() + DRIVE_ACCESS_TIMEOUT
;
493 if (DeviceIoControl(hDrive
, FSCTL_LOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
))
495 Log("FSCTL_LOCK_VOLUME success");
498 Sleep(DRIVE_ACCESS_TIMEOUT
/ DRIVE_ACCESS_RETRIES
);
499 } while (GetTickCount64() < EndTime
);
501 // If we reached this section, either we didn't manage to get a lock or the user cancelled
502 Log("Could not lock access to %s %u", PhyDrive
, LASTERR
);
504 // See if we can report the processes are accessing the drive
505 //if (!IS_ERROR(FormatStatus) && (access_mask == 0))
506 // access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE);
507 // Try to continue if the only access rights we saw were for read-only
508 //if ((access_mask & 0x07) != 0x01)
509 // safe_closehandle(hDrive);
511 CHECK_CLOSE_HANDLE(hDrive
);
516 if (hDrive
== INVALID_HANDLE_VALUE
)
518 Log("Can get handle of %s, maybe some process control it.", DevPath
);
524 int GetPhyDriveByLogicalDrive(int DriveLetter
)
529 VOLUME_DISK_EXTENTS DiskExtents
;
532 safe_sprintf(PhyPath
, "\\\\.\\%C:", (CHAR
)DriveLetter
);
534 Handle
= CreateFileA(PhyPath
, GENERIC_READ
, FILE_SHARE_READ
| FILE_SHARE_WRITE
, 0, OPEN_EXISTING
, 0, 0);
535 if (Handle
== INVALID_HANDLE_VALUE
)
537 Log("Could not open the disk<%s>, error:%u", PhyPath
, LASTERR
);
541 Ret
= DeviceIoControl(Handle
,
542 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
,
546 (DWORD
)(sizeof(DiskExtents
)),
550 if (!Ret
|| DiskExtents
.NumberOfDiskExtents
== 0)
552 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath
, LASTERR
);
553 CHECK_CLOSE_HANDLE(Handle
);
556 CHECK_CLOSE_HANDLE(Handle
);
558 Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",
560 DiskExtents
.Extents
[0].DiskNumber
,
561 DiskExtents
.Extents
[0].StartingOffset
.QuadPart
,
562 DiskExtents
.Extents
[0].ExtentLength
.QuadPart
565 return (int)DiskExtents
.Extents
[0].DiskNumber
;
568 int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO
*pDriveList
, DWORD
*pDriveCount
)
576 DWORD DriveCount
= 0;
577 HANDLE Handle
= INVALID_HANDLE_VALUE
;
579 PHY_DRIVE_INFO
*CurDrive
= pDriveList
;
580 GET_LENGTH_INFORMATION LengthInfo
;
581 STORAGE_PROPERTY_QUERY Query
;
582 STORAGE_DESCRIPTOR_HEADER DevDescHeader
;
583 STORAGE_DEVICE_DESCRIPTOR
*pDevDesc
;
584 int PhyDriveId
[VENTOY_MAX_PHY_DRIVE
];
586 Count
= GetPhysicalDriveCount();
588 for (i
= 0; i
< Count
&& i
< VENTOY_MAX_PHY_DRIVE
; i
++)
593 dwBytes
= GetLogicalDrives();
594 Log("Logical Drives: 0x%x", dwBytes
);
599 id
= GetPhyDriveByLogicalDrive(Letter
);
600 Log("%C --> %d", Letter
, id
);
603 for (i
= 0; i
< Count
; i
++)
605 if (PhyDriveId
[i
] == id
)
613 Log("Add phy%d to list", i
);
614 PhyDriveId
[Count
] = id
;
624 for (i
= 0; i
< Count
&& DriveCount
< VENTOY_MAX_PHY_DRIVE
; i
++)
626 CHECK_CLOSE_HANDLE(Handle
);
628 safe_sprintf(PhyDrive
, "\\\\.\\PhysicalDrive%d", PhyDriveId
[i
]);
629 Handle
= CreateFileA(PhyDrive
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
630 Log("Create file Handle:%p %s status:%u", Handle
, PhyDrive
, LASTERR
);
632 if (Handle
== INVALID_HANDLE_VALUE
)
637 bRet
= DeviceIoControl(Handle
,
638 IOCTL_DISK_GET_LENGTH_INFO
, NULL
,
646 Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR
);
650 Log("PHYSICALDRIVE%d size %llu bytes", i
, (ULONGLONG
)LengthInfo
.Length
.QuadPart
);
652 Query
.PropertyId
= StorageDeviceProperty
;
653 Query
.QueryType
= PropertyStandardQuery
;
655 bRet
= DeviceIoControl(Handle
,
656 IOCTL_STORAGE_QUERY_PROPERTY
,
660 sizeof(STORAGE_DESCRIPTOR_HEADER
),
665 Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR
, dwBytes
);
669 if (DevDescHeader
.Size
< sizeof(STORAGE_DEVICE_DESCRIPTOR
))
671 Log("Invalid DevDescHeader.Size:%u", DevDescHeader
.Size
);
675 pDevDesc
= (STORAGE_DEVICE_DESCRIPTOR
*)malloc(DevDescHeader
.Size
);
678 Log("failed to malloc error:%u len:%u", LASTERR
, DevDescHeader
.Size
);
682 bRet
= DeviceIoControl(Handle
,
683 IOCTL_STORAGE_QUERY_PROPERTY
,
692 Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR
, dwBytes
);
697 CurDrive
->PhyDrive
= i
;
698 CurDrive
->SizeInBytes
= LengthInfo
.Length
.QuadPart
;
699 CurDrive
->DeviceType
= pDevDesc
->DeviceType
;
700 CurDrive
->RemovableMedia
= pDevDesc
->RemovableMedia
;
701 CurDrive
->BusType
= pDevDesc
->BusType
;
703 if (pDevDesc
->VendorIdOffset
)
705 safe_strcpy(CurDrive
->VendorId
, (char *)pDevDesc
+ pDevDesc
->VendorIdOffset
);
706 TrimString(CurDrive
->VendorId
);
709 if (pDevDesc
->ProductIdOffset
)
711 safe_strcpy(CurDrive
->ProductId
, (char *)pDevDesc
+ pDevDesc
->ProductIdOffset
);
712 TrimString(CurDrive
->ProductId
);
715 if (pDevDesc
->ProductRevisionOffset
)
717 safe_strcpy(CurDrive
->ProductRev
, (char *)pDevDesc
+ pDevDesc
->ProductRevisionOffset
);
718 TrimString(CurDrive
->ProductRev
);
721 if (pDevDesc
->SerialNumberOffset
)
723 safe_strcpy(CurDrive
->SerialNumber
, (char *)pDevDesc
+ pDevDesc
->SerialNumberOffset
);
724 TrimString(CurDrive
->SerialNumber
);
732 CHECK_CLOSE_HANDLE(Handle
);
735 for (i
= 0, CurDrive
= pDriveList
; i
< (int)DriveCount
; i
++, CurDrive
++)
737 Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s",
738 CurDrive
->PhyDrive
, GetBusTypeString(CurDrive
->BusType
), CurDrive
->RemovableMedia
,
739 GetHumanReadableGBSize(CurDrive
->SizeInBytes
), CurDrive
->SizeInBytes
,
740 CurDrive
->VendorId
, CurDrive
->ProductId
);
743 *pDriveCount
= DriveCount
;
749 static HANDLE g_FatPhyDrive
;
750 static UINT64 g_Part2StartSec
;
751 static int GetVentoyVersionFromFatFile(CHAR
*VerBuf
, size_t BufLen
)
758 flfile
= fl_fopen("/grub/grub.cfg", "rb");
761 fl_fseek(flfile
, 0, SEEK_END
);
762 size
= (int)fl_ftell(flfile
);
764 fl_fseek(flfile
, 0, SEEK_SET
);
766 buf
= (char *)malloc(size
+ 1);
769 fl_fread(buf
, 1, size
, flfile
);
773 sprintf_s(VerBuf
, BufLen
, "%s", ParseVentoyVersionFromString(buf
));
783 static int VentoyFatDiskRead(uint32 Sector
, uint8
*Buffer
, uint32 SectorCount
)
788 LARGE_INTEGER liCurrentPosition
;
790 liCurrentPosition
.QuadPart
= Sector
+ g_Part2StartSec
;
791 liCurrentPosition
.QuadPart
*= 512;
792 SetFilePointerEx(g_FatPhyDrive
, liCurrentPosition
, &liCurrentPosition
, FILE_BEGIN
);
794 ReadSize
= (DWORD
)(SectorCount
* 512);
796 bRet
= ReadFile(g_FatPhyDrive
, Buffer
, ReadSize
, &dwSize
, NULL
);
797 if (bRet
== FALSE
|| dwSize
!= ReadSize
)
799 Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet
, ReadSize
, dwSize
, LASTERR
);
806 int GetVentoyVerInPhyDrive(const PHY_DRIVE_INFO
*pDriveInfo
, UINT64 Part2StartSector
, CHAR
*VerBuf
, size_t BufLen
, BOOL
*pSecureBoot
)
812 hDrive
= GetPhysicalHandle(pDriveInfo
->PhyDrive
, FALSE
, FALSE
, FALSE
);
813 if (hDrive
== INVALID_HANDLE_VALUE
)
818 g_FatPhyDrive
= hDrive
;
819 g_Part2StartSec
= Part2StartSector
;
821 Log("Parse FAT fs...");
825 if (0 == fl_attach_media(VentoyFatDiskRead
, NULL
))
827 Log("attach media success...");
828 rc
= GetVentoyVersionFromFatFile(VerBuf
, BufLen
);
832 Log("attach media failed...");
836 Log("GetVentoyVerInPhyDrive rc=%d...", rc
);
839 Log("VentoyVerInPhyDrive %d is <%s>...", pDriveInfo
->PhyDrive
, VerBuf
);
841 flfile
= fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
851 CHECK_CLOSE_HANDLE(hDrive
);
860 static unsigned int g_disk_unxz_len
= 0;
861 static BYTE
*g_part_img_pos
= NULL
;
862 static BYTE
*g_part_img_buf
[VENTOY_EFI_PART_SIZE
/ SIZE_1MB
];
865 static int VentoyFatMemRead(uint32 Sector
, uint8
*Buffer
, uint32 SectorCount
)
871 for (i
= 0; i
< SectorCount
; i
++)
873 offset
= (Sector
+ i
) * 512;
875 if (g_part_img_buf
[1] == NULL
)
877 MbBuf
= g_part_img_buf
[0] + offset
;
878 memcpy(Buffer
+ i
* 512, MbBuf
, 512);
882 MbBuf
= g_part_img_buf
[offset
/ SIZE_1MB
];
883 memcpy(Buffer
+ i
* 512, MbBuf
+ (offset
% SIZE_1MB
), 512);
891 static int VentoyFatMemWrite(uint32 Sector
, uint8
*Buffer
, uint32 SectorCount
)
897 for (i
= 0; i
< SectorCount
; i
++)
899 offset
= (Sector
+ i
) * 512;
901 if (g_part_img_buf
[1] == NULL
)
903 MbBuf
= g_part_img_buf
[0] + offset
;
904 memcpy(MbBuf
, Buffer
+ i
* 512, 512);
908 MbBuf
= g_part_img_buf
[offset
/ SIZE_1MB
];
909 memcpy(MbBuf
+ (offset
% SIZE_1MB
), Buffer
+ i
* 512, 512);
916 int VentoyProcSecureBoot(BOOL SecureBoot
)
920 char *filebuf
= NULL
;
923 Log("VentoyProcSecureBoot %d ...", SecureBoot
);
927 Log("Secure boot is enabled ...");
933 if (0 == fl_attach_media(VentoyFatMemRead
, VentoyFatMemWrite
))
935 file
= fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
936 Log("Open ventoy efi file %p ", file
);
939 fl_fseek(file
, 0, SEEK_END
);
940 size
= (int)fl_ftell(file
);
941 fl_fseek(file
, 0, SEEK_SET
);
943 Log("ventoy efi file size %d ...", size
);
945 filebuf
= (char *)malloc(size
);
948 fl_fread(filebuf
, 1, size
, file
);
953 Log("Now delete all efi files ...");
954 fl_remove("/EFI/BOOT/BOOTX64.EFI");
955 fl_remove("/EFI/BOOT/grubx64.efi");
956 fl_remove("/EFI/BOOT/grubx64_real.efi");
957 fl_remove("/EFI/BOOT/MokManager.efi");
958 fl_remove("/ENROLL_THIS_KEY_IN_MOKMANAGER.cer");
960 file
= fl_fopen("/EFI/BOOT/BOOTX64.EFI", "wb");
961 Log("Open bootx64 efi file %p ", file
);
966 fl_fwrite(filebuf
, 1, size
, file
);
979 file
= fl_fopen("/EFI/BOOT/grubia32_real.efi", "rb");
980 Log("Open ventoy efi file %p ", file
);
983 fl_fseek(file
, 0, SEEK_END
);
984 size
= (int)fl_ftell(file
);
985 fl_fseek(file
, 0, SEEK_SET
);
987 Log("ventoy efi file size %d ...", size
);
989 filebuf
= (char *)malloc(size
);
992 fl_fread(filebuf
, 1, size
, file
);
997 Log("Now delete all efi files ...");
998 fl_remove("/EFI/BOOT/BOOTIA32.EFI");
999 fl_remove("/EFI/BOOT/grubia32.efi");
1000 fl_remove("/EFI/BOOT/grubia32_real.efi");
1001 fl_remove("/EFI/BOOT/mmia32.efi");
1003 file
= fl_fopen("/EFI/BOOT/BOOTIA32.EFI", "wb");
1004 Log("Open bootia32 efi file %p ", file
);
1009 fl_fwrite(filebuf
, 1, size
, file
);
1035 static int disk_xz_flush(void *src
, unsigned int size
)
1038 BYTE
*buf
= (BYTE
*)src
;
1040 for (i
= 0; i
< size
; i
++)
1042 *g_part_img_pos
= *buf
++;
1045 if ((g_disk_unxz_len
% SIZE_1MB
) == 0)
1047 g_part_img_pos
= g_part_img_buf
[g_disk_unxz_len
/ SIZE_1MB
];
1058 static void unxz_error(char *x
)
1063 static BOOL
TryWritePart2(HANDLE hDrive
, UINT64 StartSectorId
)
1066 DWORD TrySize
= 16 * 1024;
1068 BYTE
*Buffer
= NULL
;
1069 unsigned char *data
= NULL
;
1070 LARGE_INTEGER liCurrentPosition
;
1072 liCurrentPosition
.QuadPart
= StartSectorId
* 512;
1073 SetFilePointerEx(hDrive
, liCurrentPosition
, &liCurrentPosition
, FILE_BEGIN
);
1075 Buffer
= malloc(TrySize
);
1077 bRet
= WriteFile(hDrive
, Buffer
, TrySize
, &dwSize
, NULL
);
1081 Log("Try write part2 bRet:%u dwSize:%u code:%u", bRet
, dwSize
, LASTERR
);
1083 if (bRet
&& dwSize
== TrySize
)
1091 static int FormatPart2Fat(HANDLE hDrive
, UINT64 StartSectorId
)
1100 unsigned char *data
= NULL
;
1101 LARGE_INTEGER liCurrentPosition
;
1102 LARGE_INTEGER liNewPosition
;
1104 Log("FormatPart2Fat %llu...", StartSectorId
);
1106 rc
= ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG
, 0, (void **)&data
, &len
);
1109 Log("Failed to read img file %p %u", data
, len
);
1113 liCurrentPosition
.QuadPart
= StartSectorId
* 512;
1114 SetFilePointerEx(hDrive
, liCurrentPosition
, &liNewPosition
, FILE_BEGIN
);
1116 Log("Set file pointer: %llu New pointer:%llu", liCurrentPosition
.QuadPart
, liNewPosition
.QuadPart
);
1118 memset(g_part_img_buf
, 0, sizeof(g_part_img_buf
));
1120 g_part_img_buf
[0] = (BYTE
*)malloc(VENTOY_EFI_PART_SIZE
);
1121 if (g_part_img_buf
[0])
1123 Log("Malloc whole img buffer success, now decompress ...");
1124 unxz(data
, len
, NULL
, NULL
, g_part_img_buf
[0], &writelen
, unxz_error
);
1126 if (len
== writelen
)
1128 Log("decompress finished success");
1130 VentoyProcSecureBoot(g_SecureBoot
);
1132 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
1135 bRet
= WriteFile(hDrive
, g_part_img_buf
[0] + i
* SIZE_1MB
, SIZE_1MB
, &dwSize
, NULL
);
1136 Log("Write part data bRet:%u dwSize:%u code:%u", bRet
, dwSize
, LASTERR
);
1144 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START
+ i
);
1150 Log("decompress finished failed");
1156 Log("Failed to malloc whole img size %u, now split it", VENTOY_EFI_PART_SIZE
);
1159 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
1161 g_part_img_buf
[i
] = (BYTE
*)malloc(SIZE_1MB
);
1162 if (g_part_img_buf
[i
] == NULL
)
1169 Log("Malloc part img buffer success, now decompress ...");
1171 g_part_img_pos
= g_part_img_buf
[0];
1173 unxz(data
, len
, NULL
, disk_xz_flush
, NULL
, NULL
, unxz_error
);
1175 if (g_disk_unxz_len
== VENTOY_EFI_PART_SIZE
)
1177 Log("decompress finished success");
1179 VentoyProcSecureBoot(g_SecureBoot
);
1181 for (int i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
1184 bRet
= WriteFile(hDrive
, g_part_img_buf
[i
], SIZE_1MB
, &dwSize
, NULL
);
1185 Log("Write part data bRet:%u dwSize:%u code:%u", bRet
, dwSize
, LASTERR
);
1193 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START
+ i
);
1199 Log("decompress finished failed");
1206 if (data
) free(data
);
1210 for (i
= 0; i
< VENTOY_EFI_PART_SIZE
/ SIZE_1MB
; i
++)
1212 if (g_part_img_buf
[i
]) free(g_part_img_buf
[i
]);
1217 if (g_part_img_buf
[0]) free(g_part_img_buf
[0]);
1223 static int WriteGrubStage1ToPhyDrive(HANDLE hDrive
, int PartStyle
)
1229 BYTE
*ImgBuf
= NULL
;
1230 BYTE
*RawBuf
= NULL
;
1232 Log("WriteGrubStage1ToPhyDrive ...");
1234 RawBuf
= (BYTE
*)malloc(SIZE_1MB
);
1240 if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG
, 0, (void **)&ImgBuf
, &Len
))
1242 Log("Failed to read stage1 img");
1247 unxz(ImgBuf
, Len
, NULL
, NULL
, RawBuf
, &readLen
, unxz_error
);
1251 Log("Write GPT stage1 ...");
1252 RawBuf
[500] = 35;//update blocklist
1253 SetFilePointer(hDrive
, 512 * 34, NULL
, FILE_BEGIN
);
1254 bRet
= WriteFile(hDrive
, RawBuf
, SIZE_1MB
- 512 * 34, &dwSize
, NULL
);
1258 Log("Write MBR stage1 ...");
1259 SetFilePointer(hDrive
, 512, NULL
, FILE_BEGIN
);
1260 bRet
= WriteFile(hDrive
, RawBuf
, SIZE_1MB
- 512, &dwSize
, NULL
);
1263 Log("WriteFile Ret:%u dwSize:%u ErrCode:%u", bRet
, dwSize
, GetLastError());
1272 static int FormatPart1exFAT(UINT64 DiskSizeBytes
)
1277 Option
.fmt
= FM_EXFAT
;
1282 // < 32GB select 32KB as cluster size
1283 // > 32GB select 128KB as cluster size
1284 if (DiskSizeBytes
/ 1024 / 1024 / 1024 <= 32)
1286 Option
.au_size
= 32768;
1290 Option
.au_size
= 131072;
1293 Log("Formatting Part1 exFAT ...");
1295 Ret
= f_mkfs(TEXT("0:"), &Option
, 0, 8 * 1024 * 1024);
1298 Log("Formatting Part1 exFAT success");
1303 Log("Formatting Part1 exFAT failed");
1310 int ClearVentoyFromPhyDrive(HWND hWnd
, PHY_DRIVE_INFO
*pPhyDrive
, char *pDrvLetter
)
1319 CHAR DriveName
[] = "?:\\";
1320 CHAR DriveLetters
[MAX_PATH
] = { 0 };
1321 LARGE_INTEGER liCurrentPosition
;
1322 char *pTmpBuf
= NULL
;
1327 Log("ClearVentoyFromPhyDrive PhyDrive%d <<%s %s %dGB>>",
1328 pPhyDrive
->PhyDrive
, pPhyDrive
->VendorId
, pPhyDrive
->ProductId
,
1329 GetHumanReadableGBSize(pPhyDrive
->SizeInBytes
));
1331 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
1333 Log("Lock disk for clean ............................. ");
1335 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, FALSE
, FALSE
);
1336 if (hDrive
== INVALID_HANDLE_VALUE
)
1338 Log("Failed to open physical disk");
1342 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
1344 if (DriveLetters
[0] == 0)
1346 Log("No drive letter was assigned...");
1347 DriveName
[0] = GetFirstUnusedDriveLetter();
1348 Log("GetFirstUnusedDriveLetter %C: ...", DriveName
[0]);
1352 // Unmount all mounted volumes that belong to this drive
1353 // Do it in reverse so that we always end on the first volume letter
1354 for (i
= (int)strlen(DriveLetters
); i
> 0; i
--)
1356 DriveName
[0] = DriveLetters
[i
- 1];
1357 bRet
= DeleteVolumeMountPointA(DriveName
);
1358 Log("Delete mountpoint %s ret:%u code:%u", DriveName
, bRet
, GetLastError());
1362 MountDrive
= DriveName
[0];
1363 Log("Will use '%C:' as volume mountpoint", DriveName
[0]);
1365 // It kind of blows, but we have to relinquish access to the physical drive
1366 // for VDS to be able to delete the partitions that reside on it...
1367 DeviceIoControl(hDrive
, FSCTL_UNLOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1368 CHECK_CLOSE_HANDLE(hDrive
);
1370 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART
);
1372 if (!DeletePartitions(pPhyDrive
->PhyDrive
, FALSE
))
1374 Log("Notice: Could not delete partitions: %u", GetLastError());
1377 Log("Deleting all partitions ......................... OK");
1379 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE
);
1381 Log("Lock disk for write ............................. ");
1382 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
1383 if (hDrive
== INVALID_HANDLE_VALUE
)
1385 Log("Failed to GetPhysicalHandle for write.");
1390 // clear first and last 2MB space
1391 pTmpBuf
= malloc(SIZE_2MB
);
1394 Log("Failed to alloc memory.");
1398 memset(pTmpBuf
, 0, SIZE_2MB
);
1401 bRet
= WriteFile(hDrive
, pTmpBuf
, SIZE_2MB
- 512, &dwSize
, NULL
);
1402 Log("Write fisrt 1MB ret:%d size:%u err:%d", bRet
, dwSize
, LASTERR
);
1409 SET_FILE_POS(pPhyDrive
->SizeInBytes
- SIZE_2MB
);
1410 bRet
= WriteFile(hDrive
, pTmpBuf
, SIZE_2MB
, &dwSize
, NULL
);
1411 Log("Write 2nd 1MB ret:%d size:%u err:%d", bRet
, dwSize
, LASTERR
);
1420 if (pPhyDrive
->SizeInBytes
> 2199023255552ULL)
1422 VTOY_GPT_INFO
*pGptInfo
;
1423 VTOY_GPT_HDR BackupHead
;
1424 LARGE_INTEGER liCurrentPosition
;
1426 pGptInfo
= (VTOY_GPT_INFO
*)pTmpBuf
;
1428 VentoyFillWholeGpt(pPhyDrive
->SizeInBytes
, pGptInfo
);
1430 SET_FILE_POS(pPhyDrive
->SizeInBytes
- 512);
1431 VentoyFillBackupGptHead(pGptInfo
, &BackupHead
);
1432 if (!WriteFile(hDrive
, &BackupHead
, sizeof(VTOY_GPT_HDR
), &dwSize
, NULL
))
1435 Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1439 SET_FILE_POS(pPhyDrive
->SizeInBytes
- 512 * 33);
1440 if (!WriteFile(hDrive
, pGptInfo
->PartTbl
, sizeof(pGptInfo
->PartTbl
), &dwSize
, NULL
))
1443 Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1448 if (!WriteFile(hDrive
, pGptInfo
, sizeof(VTOY_GPT_INFO
), &dwSize
, NULL
))
1451 Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1455 Log("Write GPT Info OK ...");
1459 bRet
= ReadFile(hDrive
, &MBR
, sizeof(MBR
), &dwSize
, NULL
);
1460 Log("Read MBR ret:%d size:%u err:%d", bRet
, dwSize
, LASTERR
);
1467 //clear boot code and partition table (reserved disk signature)
1468 memset(MBR
.BootCode
, 0, 440);
1469 memset(MBR
.PartTbl
, 0, sizeof(MBR
.PartTbl
));
1471 VentoyFillMBRLocation(pPhyDrive
->SizeInBytes
, 2048, (UINT32
)(pPhyDrive
->SizeInBytes
/ 512 - 2048), MBR
.PartTbl
);
1473 MBR
.PartTbl
[0].Active
= 0x00; // bootable
1474 MBR
.PartTbl
[0].FsFlag
= 0x07; // exFAT/NTFS/HPFS
1477 bRet
= WriteFile(hDrive
, &MBR
, 512, &dwSize
, NULL
);
1478 Log("Write MBR ret:%d size:%u err:%d", bRet
, dwSize
, LASTERR
);
1486 Log("Clear Ventoy successfully finished");
1488 //Refresh Drive Layout
1489 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1493 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME
);
1502 Log("Mounting Ventoy Partition ....................... ");
1506 memset(DriveLetters
, 0, sizeof(DriveLetters
));
1507 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
1508 Log("Logical drive letter after write ventoy: <%s>", DriveLetters
);
1510 for (i
= 0; i
< sizeof(DriveLetters
) && DriveLetters
[i
]; i
++)
1512 DriveName
[0] = DriveLetters
[i
];
1513 Log("%s is ventoy part1, already mounted", DriveName
);
1519 Log("need to mount ventoy part1...");
1520 if (0 == GetVentoyVolumeName(pPhyDrive
->PhyDrive
, 2048, DriveLetters
, sizeof(DriveLetters
), FALSE
))
1522 DriveName
[0] = MountDrive
;
1523 bRet
= SetVolumeMountPointA(DriveName
, DriveLetters
);
1524 Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName
, DriveLetters
, bRet
, GetLastError());
1526 *pDrvLetter
= MountDrive
;
1530 Log("Failed to find ventoy volume");
1538 FindProcessOccupyDisk(hDrive
, pPhyDrive
);
1541 CHECK_CLOSE_HANDLE(hDrive
);
1545 int InstallVentoy2FileImage(PHY_DRIVE_INFO
*pPhyDrive
, int PartStyle
)
1554 UINT64 data_offset
= 0;
1555 UINT64 Part2StartSector
= 0;
1556 UINT64 Part1StartSector
= 0;
1557 UINT64 Part1SectorCount
= 0;
1558 UINT8
*pData
= NULL
;
1559 UINT8
*pBkGptPartTbl
= NULL
;
1560 BYTE
*ImgBuf
= NULL
;
1561 MBR_HEAD
*pMBR
= NULL
;
1562 VTSI_FOOTER
*pImgFooter
= NULL
;
1563 VTSI_SEGMENT
*pSegment
= NULL
;
1564 VTOY_GPT_INFO
*pGptInfo
= NULL
;
1565 VTOY_GPT_HDR
*pBkGptHdr
= NULL
;
1568 Log("InstallVentoy2FileImage %s PhyDrive%d <<%s %s %dGB>>",
1569 PartStyle
? "GPT" : "MBR", pPhyDrive
->PhyDrive
, pPhyDrive
->VendorId
, pPhyDrive
->ProductId
,
1570 GetHumanReadableGBSize(pPhyDrive
->SizeInBytes
));
1572 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
1574 size
= SIZE_1MB
+ VENTOY_EFI_PART_SIZE
+ 33 * 512 + VTSI_IMG_MAX_SEG
* sizeof(VTSI_SEGMENT
) + sizeof(VTSI_FOOTER
);
1576 pData
= (UINT8
*)malloc(size
);
1579 Log("malloc image buffer failed %d.", size
);
1583 pImgFooter
= (VTSI_FOOTER
*)(pData
+ size
- sizeof(VTSI_FOOTER
));
1584 pSegment
= (VTSI_SEGMENT
*)((UINT8
*)pImgFooter
- VTSI_IMG_MAX_SEG
* sizeof(VTSI_SEGMENT
));
1585 memset(pImgFooter
, 0, sizeof(VTSI_FOOTER
));
1586 memset(pSegment
, 0, VTSI_IMG_MAX_SEG
* sizeof(VTSI_SEGMENT
));
1588 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START
);
1590 Log("Writing Boot Image ............................. ");
1591 if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG
, 0, (void **)&ImgBuf
, &Len
))
1593 Log("Failed to read stage1 img");
1597 unxz(ImgBuf
, Len
, NULL
, NULL
, pData
, &dataLen
, unxz_error
);
1600 Log("decompress %s len:%d", VENTOY_FILE_STG1_IMG
, dataLen
);
1604 pData
[500] = 35;//update blocklist
1605 memmove(pData
+ 34 * 512, pData
, SIZE_1MB
- 512 * 34);
1606 memset(pData
, 0, 34 * 512);
1608 pGptInfo
= (VTOY_GPT_INFO
*)pData
;
1609 memset(pGptInfo
, 0, sizeof(VTOY_GPT_INFO
));
1610 VentoyFillGpt(pPhyDrive
->SizeInBytes
, pGptInfo
);
1612 pBkGptPartTbl
= pData
+ SIZE_1MB
+ VENTOY_EFI_PART_SIZE
;
1613 memset(pBkGptPartTbl
, 0, 33 * 512);
1615 memcpy(pBkGptPartTbl
, pGptInfo
->PartTbl
, 32 * 512);
1616 pBkGptHdr
= (VTOY_GPT_HDR
*)(pBkGptPartTbl
+ 32 * 512);
1617 VentoyFillBackupGptHead(pGptInfo
, pBkGptHdr
);
1619 Part1StartSector
= pGptInfo
->PartTbl
[0].StartLBA
;
1620 Part1SectorCount
= pGptInfo
->PartTbl
[0].LastLBA
- Part1StartSector
+ 1;
1621 Part2StartSector
= pGptInfo
->PartTbl
[1].StartLBA
;
1623 Log("Write GPT Info OK ...");
1627 memmove(pData
+ 512, pData
, SIZE_1MB
- 512);
1628 memset(pData
, 0, 512);
1630 pMBR
= (MBR_HEAD
*)pData
;
1631 VentoyFillMBR(pPhyDrive
->SizeInBytes
, pMBR
, PartStyle
);
1632 Part1StartSector
= pMBR
->PartTbl
[0].StartSectorId
;
1633 Part1SectorCount
= pMBR
->PartTbl
[0].SectorCount
;
1634 Part2StartSector
= pMBR
->PartTbl
[1].StartSectorId
;
1636 Log("Write MBR OK ...");
1639 Log("Writing EFI part Image ............................. ");
1640 rc
= ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG
, 0, (void **)&ImgBuf
, &Len
);
1643 Log("Failed to read img file %p %u", ImgBuf
, Len
);
1647 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START
+ 28);
1648 memset(g_part_img_buf
, 0, sizeof(g_part_img_buf
));
1649 unxz(ImgBuf
, Len
, NULL
, NULL
, pData
+ SIZE_1MB
, &dataLen
, unxz_error
);
1652 Log("decompress finished success");
1653 g_part_img_buf
[0] = pData
+ SIZE_1MB
;
1655 VentoyProcSecureBoot(g_SecureBoot
);
1659 Log("decompress finished failed");
1663 fopen_s(&fp
, "VentoySparseImg.vtsi", "wb+");
1666 Log("Failed to create Ventoy img file");
1670 Log("Writing stage1 data ............................. ");
1672 fwrite(pData
, 1, SIZE_1MB
, fp
);
1674 pSegment
[0].disk_start_sector
= 0;
1675 pSegment
[0].sector_num
= SIZE_1MB
/ 512;
1676 pSegment
[0].data_offset
= data_offset
;
1677 data_offset
+= pSegment
[0].sector_num
* 512;
1679 disk_io_set_param(INVALID_HANDLE_VALUE
, Part1StartSector
+ Part1SectorCount
);// include the 2048 sector gap
1680 disk_io_set_imghook(fp
, pSegment
+ 1, VTSI_IMG_MAX_SEG
- 1, data_offset
);
1682 Log("Formatting part1 exFAT ...");
1683 if (0 != FormatPart1exFAT(pPhyDrive
->SizeInBytes
))
1685 Log("FormatPart1exFAT failed.");
1686 disk_io_reset_imghook(&segnum
, &data_offset
);
1690 disk_io_reset_imghook(&segnum
, &data_offset
);
1693 Log("current segment number:%d dataoff:%ld", segnum
, (long)data_offset
);
1696 Log("Writing part2 data ............................. ");
1697 fwrite(pData
+ SIZE_1MB
, 1, VENTOY_EFI_PART_SIZE
, fp
);
1698 pSegment
[segnum
].disk_start_sector
= Part2StartSector
;
1699 pSegment
[segnum
].sector_num
= VENTOY_EFI_PART_SIZE
/ 512;
1700 pSegment
[segnum
].data_offset
= data_offset
;
1701 data_offset
+= pSegment
[segnum
].sector_num
* 512;
1706 Log("Writing backup gpt table ............................. ");
1707 fwrite(pBkGptPartTbl
, 1, 33 * 512, fp
);
1708 pSegment
[segnum
].disk_start_sector
= pPhyDrive
->SizeInBytes
/ 512 - 33;
1709 pSegment
[segnum
].sector_num
= 33;
1710 pSegment
[segnum
].data_offset
= data_offset
;
1711 data_offset
+= pSegment
[segnum
].sector_num
* 512;
1715 Log("Writing segment metadata ............................. ");
1717 for (i
= 0; i
< (int)segnum
; i
++)
1719 Log("SEG[%d]: PhySector:%llu SectorNum:%llu DataOffset:%llu(sector:%llu)", i
, pSegment
[i
].disk_start_sector
, pSegment
[i
].sector_num
,
1720 pSegment
[i
].data_offset
, pSegment
[i
].data_offset
/ 512);
1723 dataLen
= segnum
* sizeof(VTSI_SEGMENT
);
1724 fwrite(pSegment
, 1, dataLen
, fp
);
1728 //pData + SIZE_1MB - 8192 is a temp data buffer with zero
1729 fwrite(pData
+ SIZE_1MB
- 8192, 1, 512 - (dataLen
% 512), fp
);
1733 pImgFooter
->magic
= VTSI_IMG_MAGIC
;
1734 pImgFooter
->version
= 1;
1735 pImgFooter
->disk_size
= pPhyDrive
->SizeInBytes
;
1736 memcpy(&pImgFooter
->disk_signature
, pPhyDrive
->MBR
.BootCode
+ 0x1b8, 4);
1737 pImgFooter
->segment_num
= segnum
;
1738 pImgFooter
->segment_offset
= data_offset
;
1740 for (i
= 0, chksum
= 0; i
< (int)(segnum
* sizeof(VTSI_SEGMENT
)); i
++)
1742 chksum
+= *((UINT8
*)pSegment
+ i
);
1744 pImgFooter
->segment_chksum
= ~chksum
;
1746 for (i
= 0, chksum
= 0; i
< sizeof(VTSI_FOOTER
); i
++)
1748 chksum
+= *((UINT8
*)pImgFooter
+ i
);
1750 pImgFooter
->foot_chksum
= ~chksum
;
1752 Log("Writing footer segnum(%u) segoffset(%llu) ......................", segnum
, data_offset
);
1753 Log("disk_size=%llu disk_signature=%lx segment_offset=%llu", pImgFooter
->disk_size
, pImgFooter
->disk_signature
, pImgFooter
->segment_offset
);
1755 fwrite(pImgFooter
, 1, sizeof(VTSI_FOOTER
), fp
);
1758 Log("Writing Ventoy image file finished, the file size should be %llu .", data_offset
+ 512 + ((dataLen
+ 511) / 512 * 512));
1764 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME
);
1766 Log("retcode:%d\n", rc
);
1775 int InstallVentoy2PhyDrive(PHY_DRIVE_INFO
*pPhyDrive
, int PartStyle
)
1784 CHAR DriveName
[] = "?:\\";
1785 CHAR DriveLetters
[MAX_PATH
] = { 0 };
1787 VTOY_GPT_INFO
*pGptInfo
= NULL
;
1788 UINT64 Part1StartSector
= 0;
1789 UINT64 Part1SectorCount
= 0;
1790 UINT64 Part2StartSector
= 0;
1792 Log("InstallVentoy2PhyDrive %s PhyDrive%d <<%s %s %dGB>>",
1793 PartStyle
? "GPT" : "MBR", pPhyDrive
->PhyDrive
, pPhyDrive
->VendorId
, pPhyDrive
->ProductId
,
1794 GetHumanReadableGBSize(pPhyDrive
->SizeInBytes
));
1798 pGptInfo
= malloc(sizeof(VTOY_GPT_INFO
));
1799 memset(pGptInfo
, 0, sizeof(VTOY_GPT_INFO
));
1802 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
1806 VentoyFillGpt(pPhyDrive
->SizeInBytes
, pGptInfo
);
1807 Part1StartSector
= pGptInfo
->PartTbl
[0].StartLBA
;
1808 Part1SectorCount
= pGptInfo
->PartTbl
[0].LastLBA
- Part1StartSector
+ 1;
1809 Part2StartSector
= pGptInfo
->PartTbl
[1].StartLBA
;
1813 VentoyFillMBR(pPhyDrive
->SizeInBytes
, &MBR
, PartStyle
);
1814 Part1StartSector
= MBR
.PartTbl
[0].StartSectorId
;
1815 Part1SectorCount
= MBR
.PartTbl
[0].SectorCount
;
1816 Part2StartSector
= MBR
.PartTbl
[1].StartSectorId
;
1819 Log("Lock disk for clean ............................. ");
1821 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, FALSE
, FALSE
);
1822 if (hDrive
== INVALID_HANDLE_VALUE
)
1824 Log("Failed to open physical disk");
1829 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
1831 if (DriveLetters
[0] == 0)
1833 Log("No drive letter was assigned...");
1834 DriveName
[0] = GetFirstUnusedDriveLetter();
1835 Log("GetFirstUnusedDriveLetter %C: ...", DriveName
[0]);
1839 // Unmount all mounted volumes that belong to this drive
1840 // Do it in reverse so that we always end on the first volume letter
1841 for (i
= (int)strlen(DriveLetters
); i
> 0; i
--)
1843 DriveName
[0] = DriveLetters
[i
- 1];
1844 bRet
= DeleteVolumeMountPointA(DriveName
);
1845 Log("Delete mountpoint %s ret:%u code:%u", DriveName
, bRet
, GetLastError());
1849 MountDrive
= DriveName
[0];
1850 Log("Will use '%C:' as volume mountpoint", DriveName
[0]);
1852 // It kind of blows, but we have to relinquish access to the physical drive
1853 // for VDS to be able to delete the partitions that reside on it...
1854 DeviceIoControl(hDrive
, FSCTL_UNLOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1855 CHECK_CLOSE_HANDLE(hDrive
);
1857 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART
);
1859 if (!DeletePartitions(pPhyDrive
->PhyDrive
, FALSE
))
1861 Log("Notice: Could not delete partitions: %u", GetLastError());
1864 Log("Deleting all partitions ......................... OK");
1866 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE
);
1868 Log("Lock disk for write ............................. ");
1869 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
1870 if (hDrive
== INVALID_HANDLE_VALUE
)
1872 Log("Failed to GetPhysicalHandle for write.");
1877 //Refresh Drive Layout
1878 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1880 disk_io_set_param(hDrive
, Part1StartSector
+ Part1SectorCount
);// include the 2048 sector gap
1882 PROGRESS_BAR_SET_POS(PT_FORMAT_PART1
);
1884 if (PartStyle
== 1 && pPhyDrive
->PartStyle
== 0)
1886 Log("Wait for format part1 ...");
1890 Log("Formatting part1 exFAT ...");
1891 if (0 != FormatPart1exFAT(pPhyDrive
->SizeInBytes
))
1893 Log("FormatPart1exFAT failed.");
1898 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2
);
1899 Log("Writing part2 FAT img ...");
1901 if (0 != FormatPart2Fat(hDrive
, Part2StartSector
))
1903 Log("FormatPart2Fat failed.");
1908 PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG
);
1909 Log("Writing Boot Image ............................. ");
1910 if (WriteGrubStage1ToPhyDrive(hDrive
, PartStyle
) != 0)
1912 Log("WriteGrubStage1ToPhyDrive failed.");
1917 PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE
);
1918 Log("Writing Partition Table ........................ ");
1919 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
1923 VTOY_GPT_HDR BackupHead
;
1924 LARGE_INTEGER liCurrentPosition
;
1926 SET_FILE_POS(pPhyDrive
->SizeInBytes
- 512);
1927 VentoyFillBackupGptHead(pGptInfo
, &BackupHead
);
1928 if (!WriteFile(hDrive
, &BackupHead
, sizeof(VTOY_GPT_HDR
), &dwSize
, NULL
))
1931 Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1935 SET_FILE_POS(pPhyDrive
->SizeInBytes
- 512 * 33);
1936 if (!WriteFile(hDrive
, pGptInfo
->PartTbl
, sizeof(pGptInfo
->PartTbl
), &dwSize
, NULL
))
1939 Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1944 if (!WriteFile(hDrive
, pGptInfo
, sizeof(VTOY_GPT_INFO
), &dwSize
, NULL
))
1947 Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize
, sizeof(VTOY_GPT_INFO
), GetLastError());
1951 Log("Write GPT Info OK ...");
1952 memcpy(&(pPhyDrive
->MBR
), &(pGptInfo
->MBR
), 512);
1956 if (!WriteFile(hDrive
, &MBR
, sizeof(MBR
), &dwSize
, NULL
))
1959 Log("Write MBR Failed, dwSize:%u ErrCode:%u", dwSize
, GetLastError());
1962 Log("Write MBR OK ...");
1963 memcpy(&(pPhyDrive
->MBR
), &MBR
, 512);
1966 //Refresh Drive Layout
1967 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
1971 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME
);
1975 Log("Mounting Ventoy Partition ....................... ");
1979 memset(DriveLetters
, 0, sizeof(DriveLetters
));
1980 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
1981 Log("Logical drive letter after write ventoy: <%s>", DriveLetters
);
1983 for (i
= 0; i
< sizeof(DriveLetters
) && DriveLetters
[i
]; i
++)
1985 DriveName
[0] = DriveLetters
[i
];
1986 if (IsVentoyLogicalDrive(DriveName
[0]))
1988 Log("%s is ventoy part2, delete mountpoint", DriveName
);
1989 DeleteVolumeMountPointA(DriveName
);
1993 Log("%s is ventoy part1, already mounted", DriveName
);
2000 Log("need to mount ventoy part1...");
2002 if (0 == GetVentoyVolumeName(pPhyDrive
->PhyDrive
, Part1StartSector
, DriveLetters
, sizeof(DriveLetters
), FALSE
))
2004 DriveName
[0] = MountDrive
;
2005 bRet
= SetVolumeMountPointA(DriveName
, DriveLetters
);
2006 Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName
, DriveLetters
, bRet
, GetLastError());
2010 Log("Failed to find ventoy volume");
2017 FindProcessOccupyDisk(hDrive
, pPhyDrive
);
2025 CHECK_CLOSE_HANDLE(hDrive
);
2029 int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO
*pPhyDrive
)
2033 BOOL ForceMBR
= FALSE
;
2039 CHAR DriveName
[] = "?:\\";
2040 CHAR DriveLetters
[MAX_PATH
] = { 0 };
2042 UINT64 ReservedMB
= 0;
2045 VTOY_GPT_INFO
*pGptInfo
= NULL
;
2046 UINT8 ReservedData
[4096];
2048 Log("UpdateVentoy2PhyDrive %s PhyDrive%d <<%s %s %dGB>>",
2049 pPhyDrive
->PartStyle
? "GPT" : "MBR", pPhyDrive
->PhyDrive
, pPhyDrive
->VendorId
, pPhyDrive
->ProductId
,
2050 GetHumanReadableGBSize(pPhyDrive
->SizeInBytes
));
2052 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN
);
2054 Log("Lock disk for umount ............................ ");
2056 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, FALSE
, FALSE
);
2057 if (hDrive
== INVALID_HANDLE_VALUE
)
2059 Log("Failed to open physical disk");
2063 if (pPhyDrive
->PartStyle
)
2065 pGptInfo
= malloc(sizeof(VTOY_GPT_INFO
));
2071 memset(pGptInfo
, 0, sizeof(VTOY_GPT_INFO
));
2074 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
2075 ReadFile(hDrive
, pGptInfo
, sizeof(VTOY_GPT_INFO
), &dwSize
, NULL
);
2077 //MBR will be used to compare with local boot image
2078 memcpy(&MBR
, &pGptInfo
->MBR
, sizeof(MBR_HEAD
));
2080 StartSector
= pGptInfo
->PartTbl
[1].StartLBA
;
2081 Log("GPT StartSector in PartTbl:%llu", (ULONGLONG
)StartSector
);
2083 ReservedMB
= (pPhyDrive
->SizeInBytes
/ 512 - (StartSector
+ VENTOY_EFI_PART_SIZE
/ 512) - 33) / 2048;
2084 Log("GPT Reserved Disk Space:%llu MB", (ULONGLONG
)ReservedMB
);
2089 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
2090 ReadFile(hDrive
, &MBR
, sizeof(MBR
), &dwSize
, NULL
);
2092 StartSector
= MBR
.PartTbl
[1].StartSectorId
;
2093 Log("MBR StartSector in PartTbl:%llu", (ULONGLONG
)StartSector
);
2095 ReservedMB
= (pPhyDrive
->SizeInBytes
/ 512 - (StartSector
+ VENTOY_EFI_PART_SIZE
/ 512)) / 2048;
2096 Log("MBR Reserved Disk Space:%llu MB", (ULONGLONG
)ReservedMB
);
2099 //Read Reserved Data
2100 SetFilePointer(hDrive
, 512 * 2040, NULL
, FILE_BEGIN
);
2101 ReadFile(hDrive
, ReservedData
, sizeof(ReservedData
), &dwSize
, NULL
);
2103 GetLettersBelongPhyDrive(pPhyDrive
->PhyDrive
, DriveLetters
, sizeof(DriveLetters
));
2105 if (DriveLetters
[0] == 0)
2107 Log("No drive letter was assigned...");
2111 // Unmount all mounted volumes that belong to this drive
2112 // Do it in reverse so that we always end on the first volume letter
2113 for (i
= (int)strlen(DriveLetters
); i
> 0; i
--)
2115 DriveName
[0] = DriveLetters
[i
- 1];
2116 if (IsVentoyLogicalDrive(DriveName
[0]))
2118 Log("%s is ventoy logical drive", DriveName
);
2119 bRet
= DeleteVolumeMountPointA(DriveName
);
2120 Log("Delete mountpoint %s ret:%u code:%u", DriveName
, bRet
, LASTERR
);
2126 // It kind of blows, but we have to relinquish access to the physical drive
2127 // for VDS to be able to delete the partitions that reside on it...
2128 DeviceIoControl(hDrive
, FSCTL_UNLOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
2129 CHECK_CLOSE_HANDLE(hDrive
);
2131 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE
);
2133 Log("Lock disk for update ............................ ");
2134 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
2135 if (hDrive
== INVALID_HANDLE_VALUE
)
2137 Log("Failed to GetPhysicalHandle for write.");
2142 PROGRESS_BAR_SET_POS(PT_LOCK_VOLUME
);
2144 Log("Lock volume for update .......................... ");
2145 hVolume
= INVALID_HANDLE_VALUE
;
2146 Status
= GetVentoyVolumeName(pPhyDrive
->PhyDrive
, StartSector
, DriveLetters
, sizeof(DriveLetters
), TRUE
);
2147 if (ERROR_SUCCESS
== Status
)
2149 Log("Now lock and dismount volume <%s>", DriveLetters
);
2150 hVolume
= CreateFileA(DriveLetters
,
2151 GENERIC_READ
| GENERIC_WRITE
,
2155 FILE_ATTRIBUTE_NORMAL
| FILE_FLAG_NO_BUFFERING
| FILE_FLAG_WRITE_THROUGH
,
2158 if (hVolume
== INVALID_HANDLE_VALUE
)
2160 Log("Failed to create file volume, errcode:%u", LASTERR
);
2165 bRet
= DeviceIoControl(hVolume
, FSCTL_LOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
2166 Log("FSCTL_LOCK_VOLUME bRet:%u code:%u", bRet
, LASTERR
);
2168 bRet
= DeviceIoControl(hVolume
, FSCTL_DISMOUNT_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
2169 Log("FSCTL_DISMOUNT_VOLUME bRet:%u code:%u", bRet
, LASTERR
);
2171 else if (ERROR_NOT_FOUND
== Status
)
2173 Log("Volume not found, maybe not supported");
2182 if (!TryWritePart2(hDrive
, StartSector
))
2184 if (pPhyDrive
->PartStyle
== 0)
2187 Log("Try write failed, now delete partition 2...");
2189 CHECK_CLOSE_HANDLE(hDrive
);
2191 Log("Now delete partition 2...");
2192 DeletePartitions(pPhyDrive
->PhyDrive
, TRUE
);
2194 hDrive
= GetPhysicalHandle(pPhyDrive
->PhyDrive
, TRUE
, TRUE
, FALSE
);
2195 if (hDrive
== INVALID_HANDLE_VALUE
)
2197 Log("Failed to GetPhysicalHandle for write.");
2204 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2
);
2206 Log("Write Ventoy to disk ............................ ");
2207 if (0 != FormatPart2Fat(hDrive
, StartSector
))
2213 if (hVolume
!= INVALID_HANDLE_VALUE
)
2215 bRet
= DeviceIoControl(hVolume
, FSCTL_UNLOCK_VOLUME
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
2216 Log("FSCTL_UNLOCK_VOLUME bRet:%u code:%u", bRet
, LASTERR
);
2217 CHECK_CLOSE_HANDLE(hVolume
);
2220 Log("Updating Boot Image ............................. ");
2221 if (WriteGrubStage1ToPhyDrive(hDrive
, pPhyDrive
->PartStyle
) != 0)
2227 //write reserved data
2228 SetFilePointer(hDrive
, 512 * 2040, NULL
, FILE_BEGIN
);
2229 bRet
= WriteFile(hDrive
, ReservedData
, sizeof(ReservedData
), &dwSize
, NULL
);
2230 Log("Write resv data ret:%u dwSize:%u Error:%u", bRet
, dwSize
, LASTERR
);
2233 VentoyGetLocalBootImg(&BootImg
);
2236 memcpy(BootImg
.BootCode
+ 0x180, MBR
.BootCode
+ 0x180, 16);
2237 if (pPhyDrive
->PartStyle
)
2239 BootImg
.BootCode
[92] = 0x22;
2242 if (ForceMBR
== FALSE
&& memcmp(BootImg
.BootCode
, MBR
.BootCode
, 440) == 0)
2244 Log("Boot image has no difference, no need to write.");
2248 Log("Boot image need to write %u.", ForceMBR
);
2250 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
2252 memcpy(MBR
.BootCode
, BootImg
.BootCode
, 440);
2253 bRet
= WriteFile(hDrive
, &MBR
, 512, &dwSize
, NULL
);
2254 Log("Write Boot Image ret:%u dwSize:%u Error:%u", bRet
, dwSize
, LASTERR
);
2257 if (pPhyDrive
->PartStyle
== 0)
2259 if (0x00 == MBR
.PartTbl
[0].Active
&& 0x80 == MBR
.PartTbl
[1].Active
)
2261 Log("Need to chage 1st partition active and 2nd partition inactive.");
2263 MBR
.PartTbl
[0].Active
= 0x80;
2264 MBR
.PartTbl
[1].Active
= 0x00;
2266 SetFilePointer(hDrive
, 0, NULL
, FILE_BEGIN
);
2267 bRet
= WriteFile(hDrive
, &MBR
, 512, &dwSize
, NULL
);
2268 Log("Write NEW MBR ret:%u dwSize:%u Error:%u", bRet
, dwSize
, LASTERR
);
2272 //Refresh Drive Layout
2273 DeviceIoControl(hDrive
, IOCTL_DISK_UPDATE_PROPERTIES
, NULL
, 0, NULL
, 0, &dwSize
, NULL
);
2283 FindProcessOccupyDisk(hDrive
, pPhyDrive
);
2286 CHECK_CLOSE_HANDLE(hDrive
);