]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - Ventoy2Disk/Ventoy2Disk/PhyDrive.c
d888b583a0449ab2354cdaf025de6fb18511df4d
[Ventoy.git] / Ventoy2Disk / Ventoy2Disk / PhyDrive.c
1 /******************************************************************************
2 * PhyDrive.c
3 *
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
5 * Copyright (c) 2011-2020, Pete Batard <pete@akeo.ie>
6 *
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.
11 *
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.
16 *
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/>.
19 *
20 */
21
22 #include <Windows.h>
23 #include <winternl.h>
24 #include <commctrl.h>
25 #include <initguid.h>
26 #include <vds.h>
27 #include "resource.h"
28 #include "Language.h"
29 #include "Ventoy2Disk.h"
30 #include "fat_filelib.h"
31 #include "ff.h"
32
33 /*
34 * Some code and functions in the file are copied from rufus.
35 * https://github.com/pbatard/rufus
36 */
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)
69
70 #define IUnknown_QueryInterface(This, a, b) (This)->lpVtbl->QueryInterface(This,a,b)
71 #define IUnknown_Release(This) (This)->lpVtbl->Release(This)
72
73 /*
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
76 */
77 BOOL DeletePartitions(DWORD DriveIndex, BOOL OnlyPart2)
78 {
79 BOOL r = FALSE;
80 HRESULT hr;
81 ULONG ulFetched;
82 wchar_t wPhysicalName[48];
83 IVdsServiceLoader *pLoader;
84 IVdsService *pService;
85 IEnumVdsObject *pEnum;
86 IUnknown *pUnk;
87
88 swprintf_s(wPhysicalName, ARRAYSIZE(wPhysicalName), L"\\\\?\\PhysicalDrive%lu", DriveIndex);
89
90 // Initialize COM
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);
94
95 // Create a VDS Loader Instance
96 hr = CoCreateInstance(&CLSID_VdsLoader, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,
97 &IID_IVdsServiceLoader, (void **)&pLoader);
98 if (hr != S_OK) {
99 VDS_SET_ERROR(hr);
100 Log("Could not create VDS Loader Instance: %u", LASTERR);
101 goto out;
102 }
103
104 // Load the VDS Service
105 hr = IVdsServiceLoader_LoadService(pLoader, L"", &pService);
106 IVdsServiceLoader_Release(pLoader);
107 if (hr != S_OK) {
108 VDS_SET_ERROR(hr);
109 Log("Could not load VDS Service: %u", LASTERR);
110 goto out;
111 }
112
113 // Wait for the Service to become ready if needed
114 hr = IVdsService_WaitForServiceReady(pService);
115 if (hr != S_OK) {
116 VDS_SET_ERROR(hr);
117 Log("VDS Service is not ready: %u", LASTERR);
118 goto out;
119 }
120
121 // Query the VDS Service Providers
122 hr = IVdsService_QueryProviders(pService, VDS_QUERY_SOFTWARE_PROVIDERS, &pEnum);
123 if (hr != S_OK) {
124 VDS_SET_ERROR(hr);
125 Log("Could not query VDS Service Providers: %u", LASTERR);
126 goto out;
127 }
128
129 while (IEnumVdsObject_Next(pEnum, 1, &pUnk, &ulFetched) == S_OK) {
130 IVdsProvider *pProvider;
131 IVdsSwProvider *pSwProvider;
132 IEnumVdsObject *pEnumPack;
133 IUnknown *pPackUnk;
134
135 // Get VDS Provider
136 hr = IUnknown_QueryInterface(pUnk, &IID_IVdsProvider, (void **)&pProvider);
137 IUnknown_Release(pUnk);
138 if (hr != S_OK) {
139 VDS_SET_ERROR(hr);
140 Log("Could not get VDS Provider: %u", LASTERR);
141 goto out;
142 }
143
144 // Get VDS Software Provider
145 hr = IVdsSwProvider_QueryInterface(pProvider, &IID_IVdsSwProvider, (void **)&pSwProvider);
146 IVdsProvider_Release(pProvider);
147 if (hr != S_OK) {
148 VDS_SET_ERROR(hr);
149 Log("Could not get VDS Software Provider: %u", LASTERR);
150 goto out;
151 }
152
153 // Get VDS Software Provider Packs
154 hr = IVdsSwProvider_QueryPacks(pSwProvider, &pEnumPack);
155 IVdsSwProvider_Release(pSwProvider);
156 if (hr != S_OK) {
157 VDS_SET_ERROR(hr);
158 Log("Could not get VDS Software Provider Packs: %u", LASTERR);
159 goto out;
160 }
161
162 // Enumerate Provider Packs
163 while (IEnumVdsObject_Next(pEnumPack, 1, &pPackUnk, &ulFetched) == S_OK) {
164 IVdsPack *pPack;
165 IEnumVdsObject *pEnumDisk;
166 IUnknown *pDiskUnk;
167
168 hr = IUnknown_QueryInterface(pPackUnk, &IID_IVdsPack, (void **)&pPack);
169 IUnknown_Release(pPackUnk);
170 if (hr != S_OK) {
171 VDS_SET_ERROR(hr);
172 Log("Could not query VDS Software Provider Pack: %u", LASTERR);
173 goto out;
174 }
175
176 // Use the pack interface to access the disks
177 hr = IVdsPack_QueryDisks(pPack, &pEnumDisk);
178 if (hr != S_OK) {
179 VDS_SET_ERROR(hr);
180 Log("Could not query VDS disks: %u", LASTERR);
181 goto out;
182 }
183
184 // List disks
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;
189 IVdsDisk *pDisk;
190 IVdsAdvancedDisk *pAdvancedDisk;
191
192 // Get the disk interface.
193 hr = IUnknown_QueryInterface(pDiskUnk, &IID_IVdsDisk, (void **)&pDisk);
194 if (hr != S_OK) {
195 VDS_SET_ERROR(hr);
196 Log("Could not query VDS Disk Interface: %u", LASTERR);
197 goto out;
198 }
199
200 // Get the disk properties
201 hr = IVdsDisk_GetProperties(pDisk, &diskprop);
202 if (hr != S_OK) {
203 VDS_SET_ERROR(hr);
204 Log("Could not query VDS Disk Properties: %u", LASTERR);
205 goto out;
206 }
207
208 // Isolate the disk we want
209 if (_wcsicmp(wPhysicalName, diskprop.pwszName) != 0) {
210 IVdsDisk_Release(pDisk);
211 continue;
212 }
213
214 // Instantiate the AdvanceDisk interface for our disk.
215 hr = IVdsDisk_QueryInterface(pDisk, &IID_IVdsAdvancedDisk, (void **)&pAdvancedDisk);
216 IVdsDisk_Release(pDisk);
217 if (hr != S_OK) {
218 VDS_SET_ERROR(hr);
219 Log("Could not access VDS Advanced Disk interface: %u", LASTERR);
220 goto out;
221 }
222
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);
225 if (hr == S_OK) {
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++) {
229
230 Log("* Partition %d (offset: %lld, size: %llu)", prop_array[i].ulPartitionNumber,
231 prop_array[i].ullOffset, (ULONGLONG)prop_array[i].ullSize);
232
233 if (OnlyPart2 && prop_array[i].ullOffset == 2048*512)
234 {
235 Log("Skip this partition...");
236 continue;
237 }
238
239
240 hr = IVdsAdvancedDisk_DeletePartition(pAdvancedDisk, prop_array[i].ullOffset, TRUE, TRUE);
241 if (hr != S_OK) {
242 r = FALSE;
243 VDS_SET_ERROR(hr);
244 Log("Could not delete partitions: %u", LASTERR);
245 }
246 }
247 r = TRUE;
248 }
249 else {
250 Log("No partition to delete on disk '%S'", diskprop.pwszName);
251 r = TRUE;
252 }
253 CoTaskMemFree(prop_array);
254
255 #if 0
256 // Issue a Clean while we're at it
257 HRESULT hr2 = E_FAIL;
258 ULONG completed;
259 IVdsAsync* pAsync;
260 hr = IVdsAdvancedDisk_Clean(pAdvancedDisk, TRUE, FALSE, FALSE, &pAsync);
261 while (SUCCEEDED(hr)) {
262 if (IS_ERROR(FormatStatus)) {
263 IVdsAsync_Cancel(pAsync);
264 break;
265 }
266 hr = IVdsAsync_QueryStatus(pAsync, &hr2, &completed);
267 if (SUCCEEDED(hr)) {
268 hr = hr2;
269 if (hr == S_OK)
270 break;
271 if (hr == VDS_E_OPERATION_PENDING)
272 hr = S_OK;
273 }
274 Sleep(500);
275 }
276 if (hr != S_OK) {
277 VDS_SET_ERROR(hr);
278 Log("Could not clean disk: %s", LASTERR);
279 }
280 #endif
281 IVdsAdvancedDisk_Release(pAdvancedDisk);
282 goto out;
283 }
284 }
285 }
286
287 out:
288 return r;
289 }
290
291
292 static DWORD GetVentoyVolumeName(int PhyDrive, UINT64 StartSectorId, CHAR *NameBuf, UINT32 BufLen, BOOL DelSlash)
293 {
294 size_t len;
295 BOOL bRet;
296 DWORD dwSize;
297 HANDLE hDrive;
298 HANDLE hVolume;
299 UINT64 PartOffset;
300 DWORD Status = ERROR_NOT_FOUND;
301 DISK_EXTENT *pExtents = NULL;
302 CHAR VolumeName[MAX_PATH] = { 0 };
303 VOLUME_DISK_EXTENTS DiskExtents;
304
305 PartOffset = 512ULL * StartSectorId;
306
307 Log("GetVentoyVolumeName PhyDrive %d SectorStart:%llu PartOffset:%llu", PhyDrive, (ULONGLONG)StartSectorId, (ULONGLONG)PartOffset);
308
309 hVolume = FindFirstVolumeA(VolumeName, sizeof(VolumeName));
310 if (hVolume == INVALID_HANDLE_VALUE)
311 {
312 return 1;
313 }
314
315 do {
316
317 len = strlen(VolumeName);
318 Log("Find volume:%s", VolumeName);
319
320 VolumeName[len - 1] = 0;
321
322 hDrive = CreateFileA(VolumeName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
323 if (hDrive == INVALID_HANDLE_VALUE)
324 {
325 continue;
326 }
327
328 bRet = DeviceIoControl(hDrive,
329 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
330 NULL,
331 0,
332 &DiskExtents,
333 (DWORD)(sizeof(DiskExtents)),
334 (LPDWORD)&dwSize,
335 NULL);
336
337 Log("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS bRet:%u code:%u", bRet, LASTERR);
338 Log("NumberOfDiskExtents:%u DiskNumber:%u", DiskExtents.NumberOfDiskExtents, DiskExtents.Extents[0].DiskNumber);
339
340 if (bRet && DiskExtents.NumberOfDiskExtents == 1)
341 {
342 pExtents = DiskExtents.Extents;
343
344 Log("This volume DiskNumber:%u offset:%llu", pExtents->DiskNumber, (ULONGLONG)pExtents->StartingOffset.QuadPart);
345 if ((int)pExtents->DiskNumber == PhyDrive && pExtents->StartingOffset.QuadPart == PartOffset)
346 {
347 Log("This volume match");
348
349 if (!DelSlash)
350 {
351 VolumeName[len - 1] = '\\';
352 }
353
354 sprintf_s(NameBuf, BufLen, "%s", VolumeName);
355 Status = ERROR_SUCCESS;
356 CloseHandle(hDrive);
357 break;
358 }
359 }
360
361 CloseHandle(hDrive);
362 } while (FindNextVolumeA(hVolume, VolumeName, sizeof(VolumeName)));
363
364 FindVolumeClose(hVolume);
365
366 Log("GetVentoyVolumeName return %u", Status);
367 return Status;
368 }
369
370 static int GetLettersBelongPhyDrive(int PhyDrive, char *DriveLetters, size_t Length)
371 {
372 int n = 0;
373 DWORD DataSize = 0;
374 CHAR *Pos = NULL;
375 CHAR *StringBuf = NULL;
376
377 DataSize = GetLogicalDriveStringsA(0, NULL);
378 StringBuf = (CHAR *)malloc(DataSize + 1);
379 if (StringBuf == NULL)
380 {
381 return 1;
382 }
383
384 GetLogicalDriveStringsA(DataSize, StringBuf);
385
386 for (Pos = StringBuf; *Pos; Pos += strlen(Pos) + 1)
387 {
388 if (n < (int)Length && PhyDrive == GetPhyDriveByLogicalDrive(Pos[0]))
389 {
390 Log("%C: is belong to phydrive%d", Pos[0], PhyDrive);
391 DriveLetters[n++] = Pos[0];
392 }
393 }
394
395 free(StringBuf);
396 return 0;
397 }
398
399 static HANDLE GetPhysicalHandle(int Drive, BOOLEAN bLockDrive, BOOLEAN bWriteAccess, BOOLEAN bWriteShare)
400 {
401 int i;
402 DWORD dwSize;
403 DWORD LastError;
404 UINT64 EndTime;
405 HANDLE hDrive = INVALID_HANDLE_VALUE;
406 CHAR PhyDrive[128];
407 CHAR DevPath[MAX_PATH] = { 0 };
408
409 safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", Drive);
410
411 if (0 == QueryDosDeviceA(PhyDrive + 4, DevPath, sizeof(DevPath)))
412 {
413 Log("QueryDosDeviceA failed error:%u", GetLastError());
414 strcpy_s(DevPath, sizeof(DevPath), "???");
415 }
416 else
417 {
418 Log("QueryDosDeviceA success %s", DevPath);
419 }
420
421 for (i = 0; i < DRIVE_ACCESS_RETRIES; i++)
422 {
423 // Try without FILE_SHARE_WRITE (unless specifically requested) so that
424 // we won't be bothered by the OS or other apps when we set up our data.
425 // However this means we might have to wait for an access gap...
426 // We keep FILE_SHARE_READ though, as this shouldn't hurt us any, and is
427 // required for enumeration.
428 hDrive = CreateFileA(PhyDrive,
429 GENERIC_READ | (bWriteAccess ? GENERIC_WRITE : 0),
430 FILE_SHARE_READ | (bWriteShare ? FILE_SHARE_WRITE : 0),
431 NULL,
432 OPEN_EXISTING,
433 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
434 NULL);
435
436 LastError = GetLastError();
437 Log("[%d] CreateFileA %s code:%u %p", i, PhyDrive, LastError, hDrive);
438
439 if (hDrive != INVALID_HANDLE_VALUE)
440 {
441 break;
442 }
443
444 if ((LastError != ERROR_SHARING_VIOLATION) && (LastError != ERROR_ACCESS_DENIED))
445 {
446 break;
447 }
448
449 if (i == 0)
450 {
451 Log("Waiting for access on %s [%s]...", PhyDrive, DevPath);
452 }
453 else if (!bWriteShare && (i > DRIVE_ACCESS_RETRIES / 3))
454 {
455 // If we can't seem to get a hold of the drive for some time, try to enable FILE_SHARE_WRITE...
456 Log("Warning: Could not obtain exclusive rights. Retrying with write sharing enabled...");
457 bWriteShare = TRUE;
458
459 // Try to report the process that is locking the drive
460 // We also use bit 6 as a flag to indicate that SearchProcess was called.
461 //access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE) | 0x40;
462
463 }
464 Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES);
465 }
466
467 if (hDrive == INVALID_HANDLE_VALUE)
468 {
469 Log("Could not open %s %u", PhyDrive, LASTERR);
470 goto End;
471 }
472
473 if (bWriteAccess)
474 {
475 Log("Opened %s for %s write access", PhyDrive, bWriteShare ? "shared" : "exclusive");
476 }
477
478 if (bLockDrive)
479 {
480 if (DeviceIoControl(hDrive, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &dwSize, NULL))
481 {
482 Log("I/O boundary checks disabled");
483 }
484
485 EndTime = GetTickCount64() + DRIVE_ACCESS_TIMEOUT;
486
487 do {
488 if (DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL))
489 {
490 Log("FSCTL_LOCK_VOLUME success");
491 goto End;
492 }
493 Sleep(DRIVE_ACCESS_TIMEOUT / DRIVE_ACCESS_RETRIES);
494 } while (GetTickCount64() < EndTime);
495
496 // If we reached this section, either we didn't manage to get a lock or the user cancelled
497 Log("Could not lock access to %s %u", PhyDrive, LASTERR);
498
499 // See if we can report the processes are accessing the drive
500 //if (!IS_ERROR(FormatStatus) && (access_mask == 0))
501 // access_mask = SearchProcess(DevPath, SEARCH_PROCESS_TIMEOUT, TRUE, TRUE, FALSE);
502 // Try to continue if the only access rights we saw were for read-only
503 //if ((access_mask & 0x07) != 0x01)
504 // safe_closehandle(hDrive);
505
506 CHECK_CLOSE_HANDLE(hDrive);
507 }
508
509 End:
510
511 if (hDrive == INVALID_HANDLE_VALUE)
512 {
513 Log("Can get handle of %s, maybe some process control it.", DevPath);
514 }
515
516 return hDrive;
517 }
518
519 int GetPhyDriveByLogicalDrive(int DriveLetter)
520 {
521 BOOL Ret;
522 DWORD dwSize;
523 HANDLE Handle;
524 VOLUME_DISK_EXTENTS DiskExtents;
525 CHAR PhyPath[128];
526
527 safe_sprintf(PhyPath, "\\\\.\\%C:", (CHAR)DriveLetter);
528
529 Handle = CreateFileA(PhyPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
530 if (Handle == INVALID_HANDLE_VALUE)
531 {
532 Log("Could not open the disk<%s>, error:%u", PhyPath, LASTERR);
533 return -1;
534 }
535
536 Ret = DeviceIoControl(Handle,
537 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
538 NULL,
539 0,
540 &DiskExtents,
541 (DWORD)(sizeof(DiskExtents)),
542 (LPDWORD)&dwSize,
543 NULL);
544
545 if (!Ret || DiskExtents.NumberOfDiskExtents == 0)
546 {
547 Log("DeviceIoControl IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS failed %s, error:%u", PhyPath, LASTERR);
548 CHECK_CLOSE_HANDLE(Handle);
549 return -1;
550 }
551 CHECK_CLOSE_HANDLE(Handle);
552
553 Log("LogicalDrive:%s PhyDrive:%d Offset:%llu ExtentLength:%llu",
554 PhyPath,
555 DiskExtents.Extents[0].DiskNumber,
556 DiskExtents.Extents[0].StartingOffset.QuadPart,
557 DiskExtents.Extents[0].ExtentLength.QuadPart
558 );
559
560 return (int)DiskExtents.Extents[0].DiskNumber;
561 }
562
563 int GetAllPhysicalDriveInfo(PHY_DRIVE_INFO *pDriveList, DWORD *pDriveCount)
564 {
565 int i;
566 int Count;
567 int id;
568 int Letter = 'A';
569 BOOL bRet;
570 DWORD dwBytes;
571 DWORD DriveCount = 0;
572 HANDLE Handle = INVALID_HANDLE_VALUE;
573 CHAR PhyDrive[128];
574 PHY_DRIVE_INFO *CurDrive = pDriveList;
575 GET_LENGTH_INFORMATION LengthInfo;
576 STORAGE_PROPERTY_QUERY Query;
577 STORAGE_DESCRIPTOR_HEADER DevDescHeader;
578 STORAGE_DEVICE_DESCRIPTOR *pDevDesc;
579 int PhyDriveId[VENTOY_MAX_PHY_DRIVE];
580
581 Count = GetPhysicalDriveCount();
582
583 for (i = 0; i < Count && i < VENTOY_MAX_PHY_DRIVE; i++)
584 {
585 PhyDriveId[i] = i;
586 }
587
588 dwBytes = GetLogicalDrives();
589 Log("Logical Drives: 0x%x", dwBytes);
590 while (dwBytes)
591 {
592 if (dwBytes & 0x01)
593 {
594 id = GetPhyDriveByLogicalDrive(Letter);
595 Log("%C --> %d", Letter, id);
596 if (id >= 0)
597 {
598 for (i = 0; i < Count; i++)
599 {
600 if (PhyDriveId[i] == id)
601 {
602 break;
603 }
604 }
605
606 if (i >= Count)
607 {
608 Log("Add phy%d to list", i);
609 PhyDriveId[Count] = id;
610 Count++;
611 }
612 }
613 }
614
615 Letter++;
616 dwBytes >>= 1;
617 }
618
619 for (i = 0; i < Count && DriveCount < VENTOY_MAX_PHY_DRIVE; i++)
620 {
621 CHECK_CLOSE_HANDLE(Handle);
622
623 safe_sprintf(PhyDrive, "\\\\.\\PhysicalDrive%d", PhyDriveId[i]);
624 Handle = CreateFileA(PhyDrive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
625 Log("Create file Handle:%p %s status:%u", Handle, PhyDrive, LASTERR);
626
627 if (Handle == INVALID_HANDLE_VALUE)
628 {
629 continue;
630 }
631
632 bRet = DeviceIoControl(Handle,
633 IOCTL_DISK_GET_LENGTH_INFO, NULL,
634 0,
635 &LengthInfo,
636 sizeof(LengthInfo),
637 &dwBytes,
638 NULL);
639 if (!bRet)
640 {
641 Log("DeviceIoControl IOCTL_DISK_GET_LENGTH_INFO failed error:%u", LASTERR);
642 continue;
643 }
644
645 Log("PHYSICALDRIVE%d size %llu bytes", i, (ULONGLONG)LengthInfo.Length.QuadPart);
646
647 Query.PropertyId = StorageDeviceProperty;
648 Query.QueryType = PropertyStandardQuery;
649
650 bRet = DeviceIoControl(Handle,
651 IOCTL_STORAGE_QUERY_PROPERTY,
652 &Query,
653 sizeof(Query),
654 &DevDescHeader,
655 sizeof(STORAGE_DESCRIPTOR_HEADER),
656 &dwBytes,
657 NULL);
658 if (!bRet)
659 {
660 Log("DeviceIoControl1 error:%u dwBytes:%u", LASTERR, dwBytes);
661 continue;
662 }
663
664 if (DevDescHeader.Size < sizeof(STORAGE_DEVICE_DESCRIPTOR))
665 {
666 Log("Invalid DevDescHeader.Size:%u", DevDescHeader.Size);
667 continue;
668 }
669
670 pDevDesc = (STORAGE_DEVICE_DESCRIPTOR *)malloc(DevDescHeader.Size);
671 if (!pDevDesc)
672 {
673 Log("failed to malloc error:%u len:%u", LASTERR, DevDescHeader.Size);
674 continue;
675 }
676
677 bRet = DeviceIoControl(Handle,
678 IOCTL_STORAGE_QUERY_PROPERTY,
679 &Query,
680 sizeof(Query),
681 pDevDesc,
682 DevDescHeader.Size,
683 &dwBytes,
684 NULL);
685 if (!bRet)
686 {
687 Log("DeviceIoControl2 error:%u dwBytes:%u", LASTERR, dwBytes);
688 free(pDevDesc);
689 continue;
690 }
691
692 CurDrive->PhyDrive = i;
693 CurDrive->SizeInBytes = LengthInfo.Length.QuadPart;
694 CurDrive->DeviceType = pDevDesc->DeviceType;
695 CurDrive->RemovableMedia = pDevDesc->RemovableMedia;
696 CurDrive->BusType = pDevDesc->BusType;
697
698 if (pDevDesc->VendorIdOffset)
699 {
700 safe_strcpy(CurDrive->VendorId, (char *)pDevDesc + pDevDesc->VendorIdOffset);
701 TrimString(CurDrive->VendorId);
702 }
703
704 if (pDevDesc->ProductIdOffset)
705 {
706 safe_strcpy(CurDrive->ProductId, (char *)pDevDesc + pDevDesc->ProductIdOffset);
707 TrimString(CurDrive->ProductId);
708 }
709
710 if (pDevDesc->ProductRevisionOffset)
711 {
712 safe_strcpy(CurDrive->ProductRev, (char *)pDevDesc + pDevDesc->ProductRevisionOffset);
713 TrimString(CurDrive->ProductRev);
714 }
715
716 if (pDevDesc->SerialNumberOffset)
717 {
718 safe_strcpy(CurDrive->SerialNumber, (char *)pDevDesc + pDevDesc->SerialNumberOffset);
719 TrimString(CurDrive->SerialNumber);
720 }
721
722 CurDrive++;
723 DriveCount++;
724
725 free(pDevDesc);
726
727 CHECK_CLOSE_HANDLE(Handle);
728 }
729
730 for (i = 0, CurDrive = pDriveList; i < (int)DriveCount; i++, CurDrive++)
731 {
732 Log("PhyDrv:%d BusType:%-4s Removable:%u Size:%dGB(%llu) Name:%s %s",
733 CurDrive->PhyDrive, GetBusTypeString(CurDrive->BusType), CurDrive->RemovableMedia,
734 GetHumanReadableGBSize(CurDrive->SizeInBytes), CurDrive->SizeInBytes,
735 CurDrive->VendorId, CurDrive->ProductId);
736 }
737
738 *pDriveCount = DriveCount;
739
740 return 0;
741 }
742
743
744 static HANDLE g_FatPhyDrive;
745 static UINT64 g_Part2StartSec;
746 static int GetVentoyVersionFromFatFile(CHAR *VerBuf, size_t BufLen)
747 {
748 int rc = 1;
749 int size = 0;
750 char *buf = NULL;
751 void *flfile = NULL;
752
753 flfile = fl_fopen("/grub/grub.cfg", "rb");
754 if (flfile)
755 {
756 fl_fseek(flfile, 0, SEEK_END);
757 size = (int)fl_ftell(flfile);
758
759 fl_fseek(flfile, 0, SEEK_SET);
760
761 buf = (char *)malloc(size + 1);
762 if (buf)
763 {
764 fl_fread(buf, 1, size, flfile);
765 buf[size] = 0;
766
767 rc = 0;
768 sprintf_s(VerBuf, BufLen, "%s", ParseVentoyVersionFromString(buf));
769 free(buf);
770 }
771
772 fl_fclose(flfile);
773 }
774
775 return rc;
776 }
777
778 static int VentoyFatDiskRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
779 {
780 DWORD dwSize;
781 BOOL bRet;
782 DWORD ReadSize;
783 LARGE_INTEGER liCurrentPosition;
784
785 liCurrentPosition.QuadPart = Sector + g_Part2StartSec;
786 liCurrentPosition.QuadPart *= 512;
787 SetFilePointerEx(g_FatPhyDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
788
789 ReadSize = (DWORD)(SectorCount * 512);
790
791 bRet = ReadFile(g_FatPhyDrive, Buffer, ReadSize, &dwSize, NULL);
792 if (bRet == FALSE || dwSize != ReadSize)
793 {
794 Log("ReadFile error bRet:%u WriteSize:%u dwSize:%u ErrCode:%u\n", bRet, ReadSize, dwSize, LASTERR);
795 }
796
797 return 1;
798 }
799
800
801 int GetVentoyVerInPhyDrive(const PHY_DRIVE_INFO *pDriveInfo, UINT64 Part2StartSector, CHAR *VerBuf, size_t BufLen, BOOL *pSecureBoot)
802 {
803 int rc = 0;
804 HANDLE hDrive;
805 void *flfile;
806
807 hDrive = GetPhysicalHandle(pDriveInfo->PhyDrive, FALSE, FALSE, FALSE);
808 if (hDrive == INVALID_HANDLE_VALUE)
809 {
810 return 1;
811 }
812
813 g_FatPhyDrive = hDrive;
814 g_Part2StartSec = Part2StartSector;
815
816 Log("Parse FAT fs...");
817
818 fl_init();
819
820 if (0 == fl_attach_media(VentoyFatDiskRead, NULL))
821 {
822 Log("attach media success...");
823 rc = GetVentoyVersionFromFatFile(VerBuf, BufLen);
824 }
825 else
826 {
827 Log("attach media failed...");
828 rc = 1;
829 }
830
831 Log("GetVentoyVerInPhyDrive rc=%d...", rc);
832 if (rc == 0)
833 {
834 Log("VentoyVerInPhyDrive %d is <%s>...", pDriveInfo->PhyDrive, VerBuf);
835
836 flfile = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
837 if (flfile)
838 {
839 *pSecureBoot = TRUE;
840 fl_fclose(flfile);
841 }
842 }
843
844 fl_shutdown();
845
846 CHECK_CLOSE_HANDLE(hDrive);
847
848 return rc;
849 }
850
851
852
853
854
855 static unsigned int g_disk_unxz_len = 0;
856 static BYTE *g_part_img_pos = NULL;
857 static BYTE *g_part_img_buf[VENTOY_EFI_PART_SIZE / SIZE_1MB];
858
859
860 static int VentoyFatMemRead(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
861 {
862 uint32 i;
863 uint32 offset;
864 BYTE *MbBuf = NULL;
865
866 for (i = 0; i < SectorCount; i++)
867 {
868 offset = (Sector + i) * 512;
869
870 if (g_part_img_buf[1] == NULL)
871 {
872 MbBuf = g_part_img_buf[0] + offset;
873 memcpy(Buffer + i * 512, MbBuf, 512);
874 }
875 else
876 {
877 MbBuf = g_part_img_buf[offset / SIZE_1MB];
878 memcpy(Buffer + i * 512, MbBuf + (offset % SIZE_1MB), 512);
879 }
880 }
881
882 return 1;
883 }
884
885
886 static int VentoyFatMemWrite(uint32 Sector, uint8 *Buffer, uint32 SectorCount)
887 {
888 uint32 i;
889 uint32 offset;
890 BYTE *MbBuf = NULL;
891
892 for (i = 0; i < SectorCount; i++)
893 {
894 offset = (Sector + i) * 512;
895
896 if (g_part_img_buf[1] == NULL)
897 {
898 MbBuf = g_part_img_buf[0] + offset;
899 memcpy(MbBuf, Buffer + i * 512, 512);
900 }
901 else
902 {
903 MbBuf = g_part_img_buf[offset / SIZE_1MB];
904 memcpy(MbBuf + (offset % SIZE_1MB), Buffer + i * 512, 512);
905 }
906 }
907
908 return 1;
909 }
910
911 int VentoyProcSecureBoot(BOOL SecureBoot)
912 {
913 int rc = 0;
914 int size;
915 char *filebuf = NULL;
916 void *file = NULL;
917
918 Log("VentoyProcSecureBoot %d ...", SecureBoot);
919
920 if (SecureBoot)
921 {
922 Log("Secure boot is enabled ...");
923 return 0;
924 }
925
926 fl_init();
927
928 if (0 == fl_attach_media(VentoyFatMemRead, VentoyFatMemWrite))
929 {
930 file = fl_fopen("/EFI/BOOT/grubx64_real.efi", "rb");
931 Log("Open ventoy efi file %p ", file);
932 if (file)
933 {
934 fl_fseek(file, 0, SEEK_END);
935 size = (int)fl_ftell(file);
936 fl_fseek(file, 0, SEEK_SET);
937
938 Log("ventoy efi file size %d ...", size);
939
940 filebuf = (char *)malloc(size);
941 if (filebuf)
942 {
943 fl_fread(filebuf, 1, size, file);
944 }
945
946 fl_fclose(file);
947
948 Log("Now delete all efi files ...");
949 fl_remove("/EFI/BOOT/BOOTX64.EFI");
950 fl_remove("/EFI/BOOT/grubx64.efi");
951 fl_remove("/EFI/BOOT/grubx64_real.efi");
952 fl_remove("/EFI/BOOT/MokManager.efi");
953 fl_remove("/ENROLL_THIS_KEY_IN_MOKMANAGER.cer");
954
955 file = fl_fopen("/EFI/BOOT/BOOTX64.EFI", "wb");
956 Log("Open bootx64 efi file %p ", file);
957 if (file)
958 {
959 if (filebuf)
960 {
961 fl_fwrite(filebuf, 1, size, file);
962 }
963
964 fl_fflush(file);
965 fl_fclose(file);
966 }
967
968 if (filebuf)
969 {
970 free(filebuf);
971 }
972 }
973
974 file = fl_fopen("/EFI/BOOT/grubia32_real.efi", "rb");
975 Log("Open ventoy efi file %p ", file);
976 if (file)
977 {
978 fl_fseek(file, 0, SEEK_END);
979 size = (int)fl_ftell(file);
980 fl_fseek(file, 0, SEEK_SET);
981
982 Log("ventoy efi file size %d ...", size);
983
984 filebuf = (char *)malloc(size);
985 if (filebuf)
986 {
987 fl_fread(filebuf, 1, size, file);
988 }
989
990 fl_fclose(file);
991
992 Log("Now delete all efi files ...");
993 fl_remove("/EFI/BOOT/BOOTIA32.EFI");
994 fl_remove("/EFI/BOOT/grubia32.efi");
995 fl_remove("/EFI/BOOT/grubia32_real.efi");
996 fl_remove("/EFI/BOOT/mmia32.efi");
997
998 file = fl_fopen("/EFI/BOOT/BOOTIA32.EFI", "wb");
999 Log("Open bootia32 efi file %p ", file);
1000 if (file)
1001 {
1002 if (filebuf)
1003 {
1004 fl_fwrite(filebuf, 1, size, file);
1005 }
1006
1007 fl_fflush(file);
1008 fl_fclose(file);
1009 }
1010
1011 if (filebuf)
1012 {
1013 free(filebuf);
1014 }
1015 }
1016
1017 }
1018 else
1019 {
1020 rc = 1;
1021 }
1022
1023 fl_shutdown();
1024
1025 return rc;
1026 }
1027
1028
1029
1030 static int disk_xz_flush(void *src, unsigned int size)
1031 {
1032 unsigned int i;
1033 BYTE *buf = (BYTE *)src;
1034
1035 for (i = 0; i < size; i++)
1036 {
1037 *g_part_img_pos = *buf++;
1038
1039 g_disk_unxz_len++;
1040 if ((g_disk_unxz_len % SIZE_1MB) == 0)
1041 {
1042 g_part_img_pos = g_part_img_buf[g_disk_unxz_len / SIZE_1MB];
1043 }
1044 else
1045 {
1046 g_part_img_pos++;
1047 }
1048 }
1049
1050 return (int)size;
1051 }
1052
1053 static void unxz_error(char *x)
1054 {
1055 Log("%s", x);
1056 }
1057
1058 static BOOL TryWritePart2(HANDLE hDrive, UINT64 StartSectorId)
1059 {
1060 BOOL bRet;
1061 DWORD TrySize = 16 * 1024;
1062 DWORD dwSize;
1063 BYTE *Buffer = NULL;
1064 unsigned char *data = NULL;
1065 LARGE_INTEGER liCurrentPosition;
1066
1067 liCurrentPosition.QuadPart = StartSectorId * 512;
1068 SetFilePointerEx(hDrive, liCurrentPosition, &liCurrentPosition, FILE_BEGIN);
1069
1070 Buffer = malloc(TrySize);
1071
1072 bRet = WriteFile(hDrive, Buffer, TrySize, &dwSize, NULL);
1073
1074 free(Buffer);
1075
1076 Log("Try write part2 bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
1077
1078 if (bRet && dwSize == TrySize)
1079 {
1080 return TRUE;
1081 }
1082
1083 return FALSE;
1084 }
1085
1086 static int FormatPart2Fat(HANDLE hDrive, UINT64 StartSectorId)
1087 {
1088 int i;
1089 int rc = 0;
1090 int len = 0;
1091 int writelen = 0;
1092 int partwrite = 0;
1093 DWORD dwSize = 0;
1094 BOOL bRet;
1095 unsigned char *data = NULL;
1096 LARGE_INTEGER liCurrentPosition;
1097 LARGE_INTEGER liNewPosition;
1098
1099 Log("FormatPart2Fat %llu...", StartSectorId);
1100
1101 rc = ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG, 0, (void **)&data, &len);
1102 if (rc)
1103 {
1104 Log("Failed to read img file %p %u", data, len);
1105 return 1;
1106 }
1107
1108 liCurrentPosition.QuadPart = StartSectorId * 512;
1109 SetFilePointerEx(hDrive, liCurrentPosition, &liNewPosition, FILE_BEGIN);
1110
1111 Log("Set file pointer: %llu New pointer:%llu", liCurrentPosition.QuadPart, liNewPosition.QuadPart);
1112
1113 memset(g_part_img_buf, 0, sizeof(g_part_img_buf));
1114
1115 g_part_img_buf[0] = (BYTE *)malloc(VENTOY_EFI_PART_SIZE);
1116 if (g_part_img_buf[0])
1117 {
1118 Log("Malloc whole img buffer success, now decompress ...");
1119 unxz(data, len, NULL, NULL, g_part_img_buf[0], &writelen, unxz_error);
1120
1121 if (len == writelen)
1122 {
1123 Log("decompress finished success");
1124
1125 VentoyProcSecureBoot(g_SecureBoot);
1126
1127 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
1128 {
1129 dwSize = 0;
1130 bRet = WriteFile(hDrive, g_part_img_buf[0] + i * SIZE_1MB, SIZE_1MB, &dwSize, NULL);
1131 Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
1132
1133 if (!bRet)
1134 {
1135 rc = 1;
1136 goto End;
1137 }
1138
1139 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START + i);
1140 }
1141 }
1142 else
1143 {
1144 rc = 1;
1145 Log("decompress finished failed");
1146 goto End;
1147 }
1148 }
1149 else
1150 {
1151 Log("Failed to malloc whole img size %u, now split it", VENTOY_EFI_PART_SIZE);
1152
1153 partwrite = 1;
1154 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
1155 {
1156 g_part_img_buf[i] = (BYTE *)malloc(SIZE_1MB);
1157 if (g_part_img_buf[i] == NULL)
1158 {
1159 rc = 1;
1160 goto End;
1161 }
1162 }
1163
1164 Log("Malloc part img buffer success, now decompress ...");
1165
1166 g_part_img_pos = g_part_img_buf[0];
1167
1168 unxz(data, len, NULL, disk_xz_flush, NULL, NULL, unxz_error);
1169
1170 if (g_disk_unxz_len == VENTOY_EFI_PART_SIZE)
1171 {
1172 Log("decompress finished success");
1173
1174 VentoyProcSecureBoot(g_SecureBoot);
1175
1176 for (int i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
1177 {
1178 dwSize = 0;
1179 bRet = WriteFile(hDrive, g_part_img_buf[i], SIZE_1MB, &dwSize, NULL);
1180 Log("Write part data bRet:%u dwSize:%u code:%u", bRet, dwSize, LASTERR);
1181
1182 if (!bRet)
1183 {
1184 rc = 1;
1185 goto End;
1186 }
1187
1188 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START + i);
1189 }
1190 }
1191 else
1192 {
1193 rc = 1;
1194 Log("decompress finished failed");
1195 goto End;
1196 }
1197 }
1198
1199 End:
1200
1201 if (data) free(data);
1202
1203 if (partwrite)
1204 {
1205 for (i = 0; i < VENTOY_EFI_PART_SIZE / SIZE_1MB; i++)
1206 {
1207 if (g_part_img_buf[i]) free(g_part_img_buf[i]);
1208 }
1209 }
1210 else
1211 {
1212 if (g_part_img_buf[0]) free(g_part_img_buf[0]);
1213 }
1214
1215 return rc;
1216 }
1217
1218 static int WriteGrubStage1ToPhyDrive(HANDLE hDrive, int PartStyle)
1219 {
1220 int Len = 0;
1221 int readLen = 0;
1222 BOOL bRet;
1223 DWORD dwSize;
1224 BYTE *ImgBuf = NULL;
1225 BYTE *RawBuf = NULL;
1226
1227 Log("WriteGrubStage1ToPhyDrive ...");
1228
1229 RawBuf = (BYTE *)malloc(SIZE_1MB);
1230 if (!RawBuf)
1231 {
1232 return 1;
1233 }
1234
1235 if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG, 0, (void **)&ImgBuf, &Len))
1236 {
1237 Log("Failed to read stage1 img");
1238 free(RawBuf);
1239 return 1;
1240 }
1241
1242 unxz(ImgBuf, Len, NULL, NULL, RawBuf, &readLen, unxz_error);
1243
1244 if (PartStyle)
1245 {
1246 Log("Write GPT stage1 ...");
1247 RawBuf[500] = 35;//update blocklist
1248 SetFilePointer(hDrive, 512 * 34, NULL, FILE_BEGIN);
1249 bRet = WriteFile(hDrive, RawBuf, SIZE_1MB - 512 * 34, &dwSize, NULL);
1250 }
1251 else
1252 {
1253 Log("Write MBR stage1 ...");
1254 SetFilePointer(hDrive, 512, NULL, FILE_BEGIN);
1255 bRet = WriteFile(hDrive, RawBuf, SIZE_1MB - 512, &dwSize, NULL);
1256 }
1257
1258 Log("WriteFile Ret:%u dwSize:%u ErrCode:%u", bRet, dwSize, GetLastError());
1259
1260 free(RawBuf);
1261 free(ImgBuf);
1262 return 0;
1263 }
1264
1265
1266
1267 static int FormatPart1exFAT(UINT64 DiskSizeBytes)
1268 {
1269 MKFS_PARM Option;
1270 FRESULT Ret;
1271
1272 Option.fmt = FM_EXFAT;
1273 Option.n_fat = 1;
1274 Option.align = 8;
1275 Option.n_root = 1;
1276
1277 // < 32GB select 32KB as cluster size
1278 // > 32GB select 128KB as cluster size
1279 if (DiskSizeBytes / 1024 / 1024 / 1024 <= 32)
1280 {
1281 Option.au_size = 32768;
1282 }
1283 else
1284 {
1285 Option.au_size = 131072;
1286 }
1287
1288 Log("Formatting Part1 exFAT ...");
1289
1290 Ret = f_mkfs(TEXT("0:"), &Option, 0, 8 * 1024 * 1024);
1291 if (FR_OK == Ret)
1292 {
1293 Log("Formatting Part1 exFAT success");
1294 return 0;
1295 }
1296 else
1297 {
1298 Log("Formatting Part1 exFAT failed");
1299 return 1;
1300 }
1301 }
1302
1303
1304
1305 int ClearVentoyFromPhyDrive(HWND hWnd, PHY_DRIVE_INFO *pPhyDrive, char *pDrvLetter)
1306 {
1307 int i;
1308 int rc = 0;
1309 int state = 0;
1310 HANDLE hDrive;
1311 DWORD dwSize;
1312 BOOL bRet;
1313 CHAR MountDrive;
1314 CHAR DriveName[] = "?:\\";
1315 CHAR DriveLetters[MAX_PATH] = { 0 };
1316 LARGE_INTEGER liCurrentPosition;
1317 char *pTmpBuf = NULL;
1318 MBR_HEAD MBR;
1319
1320 *pDrvLetter = 0;
1321
1322 Log("ClearVentoyFromPhyDrive PhyDrive%d <<%s %s %dGB>>",
1323 pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
1324 GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
1325
1326 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
1327
1328 Log("Lock disk for clean ............................. ");
1329
1330 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
1331 if (hDrive == INVALID_HANDLE_VALUE)
1332 {
1333 Log("Failed to open physical disk");
1334 return 1;
1335 }
1336
1337 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
1338
1339 if (DriveLetters[0] == 0)
1340 {
1341 Log("No drive letter was assigned...");
1342 DriveName[0] = GetFirstUnusedDriveLetter();
1343 Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]);
1344 }
1345 else
1346 {
1347 // Unmount all mounted volumes that belong to this drive
1348 // Do it in reverse so that we always end on the first volume letter
1349 for (i = (int)strlen(DriveLetters); i > 0; i--)
1350 {
1351 DriveName[0] = DriveLetters[i - 1];
1352 bRet = DeleteVolumeMountPointA(DriveName);
1353 Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError());
1354 }
1355 }
1356
1357 MountDrive = DriveName[0];
1358 Log("Will use '%C:' as volume mountpoint", DriveName[0]);
1359
1360 // It kind of blows, but we have to relinquish access to the physical drive
1361 // for VDS to be able to delete the partitions that reside on it...
1362 DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
1363 CHECK_CLOSE_HANDLE(hDrive);
1364
1365 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);
1366
1367 if (!DeletePartitions(pPhyDrive->PhyDrive, FALSE))
1368 {
1369 Log("Notice: Could not delete partitions: %u", GetLastError());
1370 }
1371
1372 Log("Deleting all partitions ......................... OK");
1373
1374 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
1375
1376 Log("Lock disk for write ............................. ");
1377 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
1378 if (hDrive == INVALID_HANDLE_VALUE)
1379 {
1380 Log("Failed to GetPhysicalHandle for write.");
1381 rc = 1;
1382 goto End;
1383 }
1384
1385 // clear first and last 2MB space
1386 pTmpBuf = malloc(SIZE_2MB);
1387 if (!pTmpBuf)
1388 {
1389 Log("Failed to alloc memory.");
1390 rc = 1;
1391 goto End;
1392 }
1393 memset(pTmpBuf, 0, SIZE_2MB);
1394
1395 SET_FILE_POS(512);
1396 bRet = WriteFile(hDrive, pTmpBuf, SIZE_2MB - 512, &dwSize, NULL);
1397 Log("Write fisrt 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
1398 if (!bRet)
1399 {
1400 rc = 1;
1401 goto End;
1402 }
1403
1404 SET_FILE_POS(pPhyDrive->SizeInBytes - SIZE_2MB);
1405 bRet = WriteFile(hDrive, pTmpBuf, SIZE_2MB, &dwSize, NULL);
1406 Log("Write 2nd 1MB ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
1407 if (!bRet)
1408 {
1409 rc = 1;
1410 goto End;
1411 }
1412
1413 SET_FILE_POS(0);
1414
1415 if (pPhyDrive->SizeInBytes > 2199023255552ULL)
1416 {
1417 VTOY_GPT_INFO *pGptInfo;
1418 VTOY_GPT_HDR BackupHead;
1419 LARGE_INTEGER liCurrentPosition;
1420
1421 pGptInfo = (VTOY_GPT_INFO *)pTmpBuf;
1422
1423 VentoyFillWholeGpt(pPhyDrive->SizeInBytes, pGptInfo);
1424
1425 SET_FILE_POS(pPhyDrive->SizeInBytes - 512);
1426 VentoyFillBackupGptHead(pGptInfo, &BackupHead);
1427 if (!WriteFile(hDrive, &BackupHead, sizeof(VTOY_GPT_HDR), &dwSize, NULL))
1428 {
1429 rc = 1;
1430 Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1431 goto End;
1432 }
1433
1434 SET_FILE_POS(pPhyDrive->SizeInBytes - 512 * 33);
1435 if (!WriteFile(hDrive, pGptInfo->PartTbl, sizeof(pGptInfo->PartTbl), &dwSize, NULL))
1436 {
1437 rc = 1;
1438 Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1439 goto End;
1440 }
1441
1442 SET_FILE_POS(0);
1443 if (!WriteFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL))
1444 {
1445 rc = 1;
1446 Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1447 goto End;
1448 }
1449
1450 Log("Write GPT Info OK ...");
1451 }
1452 else
1453 {
1454 bRet = ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);
1455 Log("Read MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
1456 if (!bRet)
1457 {
1458 rc = 1;
1459 goto End;
1460 }
1461
1462 //clear boot code and partition table (reserved disk signature)
1463 memset(MBR.BootCode, 0, 440);
1464 memset(MBR.PartTbl, 0, sizeof(MBR.PartTbl));
1465
1466 VentoyFillMBRLocation(pPhyDrive->SizeInBytes, 2048, (UINT32)(pPhyDrive->SizeInBytes / 512 - 2048), MBR.PartTbl);
1467
1468 MBR.PartTbl[0].Active = 0x00; // bootable
1469 MBR.PartTbl[0].FsFlag = 0x07; // exFAT/NTFS/HPFS
1470
1471 SET_FILE_POS(0);
1472 bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);
1473 Log("Write MBR ret:%d size:%u err:%d", bRet, dwSize, LASTERR);
1474 if (!bRet)
1475 {
1476 rc = 1;
1477 goto End;
1478 }
1479 }
1480
1481 Log("Clear Ventoy successfully finished");
1482
1483 //Refresh Drive Layout
1484 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
1485
1486 End:
1487
1488 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
1489
1490 if (pTmpBuf)
1491 {
1492 free(pTmpBuf);
1493 }
1494
1495 if (rc == 0)
1496 {
1497 Log("Mounting Ventoy Partition ....................... ");
1498 Sleep(1000);
1499
1500 state = 0;
1501 memset(DriveLetters, 0, sizeof(DriveLetters));
1502 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
1503 Log("Logical drive letter after write ventoy: <%s>", DriveLetters);
1504
1505 for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++)
1506 {
1507 DriveName[0] = DriveLetters[i];
1508 Log("%s is ventoy part1, already mounted", DriveName);
1509 state = 1;
1510 }
1511
1512 if (state != 1)
1513 {
1514 Log("need to mount ventoy part1...");
1515 if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, 2048, DriveLetters, sizeof(DriveLetters), FALSE))
1516 {
1517 DriveName[0] = MountDrive;
1518 bRet = SetVolumeMountPointA(DriveName, DriveLetters);
1519 Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError());
1520
1521 *pDrvLetter = MountDrive;
1522 }
1523 else
1524 {
1525 Log("Failed to find ventoy volume");
1526 }
1527 }
1528
1529 Log("OK\n");
1530 }
1531 else
1532 {
1533 FindProcessOccupyDisk(hDrive, pPhyDrive);
1534 }
1535
1536 CHECK_CLOSE_HANDLE(hDrive);
1537 return rc;
1538 }
1539
1540 int InstallVentoy2FileImage(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
1541 {
1542 int i;
1543 int rc = 1;
1544 int Len = 0;
1545 int dataLen = 0;
1546 UINT size = 0;
1547 UINT segnum = 0;
1548 UINT32 chksum = 0;
1549 UINT64 data_offset = 0;
1550 UINT64 Part2StartSector = 0;
1551 UINT64 Part1StartSector = 0;
1552 UINT64 Part1SectorCount = 0;
1553 UINT8 *pData = NULL;
1554 UINT8 *pBkGptPartTbl = NULL;
1555 BYTE *ImgBuf = NULL;
1556 MBR_HEAD *pMBR = NULL;
1557 VTSI_FOOTER *pImgFooter = NULL;
1558 VTSI_SEGMENT *pSegment = NULL;
1559 VTOY_GPT_INFO *pGptInfo = NULL;
1560 VTOY_GPT_HDR *pBkGptHdr = NULL;
1561 FILE *fp = NULL;
1562
1563 Log("InstallVentoy2FileImage %s PhyDrive%d <<%s %s %dGB>>",
1564 PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
1565 GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
1566
1567 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
1568
1569 size = SIZE_1MB + VENTOY_EFI_PART_SIZE + 33 * 512 + VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT) + sizeof(VTSI_FOOTER);
1570
1571 pData = (UINT8 *)malloc(size);
1572 if (!pData)
1573 {
1574 Log("malloc image buffer failed %d.", size);
1575 goto End;
1576 }
1577
1578 pImgFooter = (VTSI_FOOTER *)(pData + size - sizeof(VTSI_FOOTER));
1579 pSegment = (VTSI_SEGMENT *)((UINT8 *)pImgFooter - VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT));
1580 memset(pImgFooter, 0, sizeof(VTSI_FOOTER));
1581 memset(pSegment, 0, VTSI_IMG_MAX_SEG * sizeof(VTSI_SEGMENT));
1582
1583 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START);
1584
1585 Log("Writing Boot Image ............................. ");
1586 if (ReadWholeFileToBuf(VENTOY_FILE_STG1_IMG, 0, (void **)&ImgBuf, &Len))
1587 {
1588 Log("Failed to read stage1 img");
1589 goto End;
1590 }
1591
1592 unxz(ImgBuf, Len, NULL, NULL, pData, &dataLen, unxz_error);
1593 SAFE_FREE(ImgBuf);
1594
1595 if (PartStyle)
1596 {
1597 pGptInfo = (VTOY_GPT_INFO *)pData;
1598 memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO));
1599 VentoyFillGpt(pPhyDrive->SizeInBytes, pGptInfo);
1600
1601 pBkGptPartTbl = pData + SIZE_1MB + VENTOY_EFI_PART_SIZE;
1602 memset(pBkGptPartTbl, 0, 33 * 512);
1603
1604 memcpy(pBkGptPartTbl, pGptInfo->PartTbl, 32 * 512);
1605 pBkGptHdr = (VTOY_GPT_HDR *)(pBkGptPartTbl + 32 * 512);
1606 VentoyFillBackupGptHead(pGptInfo, pBkGptHdr);
1607
1608 Part1StartSector = pGptInfo->PartTbl[0].StartLBA;
1609 Part1SectorCount = pGptInfo->PartTbl[0].LastLBA - Part1StartSector + 1;
1610 Part2StartSector = pGptInfo->PartTbl[1].StartLBA;
1611
1612 Log("Write GPT Info OK ...");
1613 }
1614 else
1615 {
1616 pMBR = (MBR_HEAD *)pData;
1617 VentoyFillMBR(pPhyDrive->SizeInBytes, pMBR, PartStyle);
1618 Part1StartSector = pMBR->PartTbl[0].StartSectorId;
1619 Part1SectorCount = pMBR->PartTbl[0].SectorCount;
1620 Part2StartSector = pMBR->PartTbl[1].StartSectorId;
1621
1622 Log("Write MBR OK ...");
1623 }
1624
1625 Log("Writing EFI part Image ............................. ");
1626 rc = ReadWholeFileToBuf(VENTOY_FILE_DISK_IMG, 0, (void **)&ImgBuf, &Len);
1627 if (rc)
1628 {
1629 Log("Failed to read img file %p %u", ImgBuf, Len);
1630 goto End;
1631 }
1632
1633 PROGRESS_BAR_SET_POS(PT_WRITE_VENTOY_START + 28);
1634 memset(g_part_img_buf, 0, sizeof(g_part_img_buf));
1635 unxz(ImgBuf, Len, NULL, NULL, pData + SIZE_1MB, &dataLen, unxz_error);
1636 if (dataLen == Len)
1637 {
1638 Log("decompress finished success");
1639 g_part_img_buf[0] = pData + SIZE_1MB;
1640
1641 VentoyProcSecureBoot(g_SecureBoot);
1642 }
1643 else
1644 {
1645 Log("decompress finished failed");
1646 goto End;
1647 }
1648
1649 fopen_s(&fp, "VentoySparseImg.vtsi", "wb+");
1650 if (!fp)
1651 {
1652 Log("Failed to create Ventoy img file");
1653 goto End;
1654 }
1655
1656 Log("Writing stage1 data ............................. ");
1657 fwrite(pData, 1, SIZE_1MB, fp);
1658 pSegment[0].disk_start_sector = 0;
1659 pSegment[0].sector_num = SIZE_1MB / 512;
1660 pSegment[0].data_offset = data_offset;
1661 data_offset += pSegment[0].sector_num * 512;
1662
1663 disk_io_set_param(INVALID_HANDLE_VALUE, Part1StartSector + Part1SectorCount);// include the 2048 sector gap
1664 disk_io_set_imghook(fp, pSegment + 1, VTSI_IMG_MAX_SEG - 1, data_offset);
1665
1666 Log("Formatting part1 exFAT ...");
1667 if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))
1668 {
1669 Log("FormatPart1exFAT failed.");
1670 disk_io_reset_imghook(&segnum, &data_offset);
1671 goto End;
1672 }
1673
1674 disk_io_reset_imghook(&segnum, &data_offset);
1675 segnum++;
1676
1677 Log("current segment number:%d dataoff:%ld", segnum, (long)data_offset);
1678
1679 //write data
1680 Log("Writing part2 data ............................. ");
1681 fwrite(pData + SIZE_1MB, 1, VENTOY_EFI_PART_SIZE, fp);
1682 pSegment[segnum].disk_start_sector = Part2StartSector;
1683 pSegment[segnum].sector_num = VENTOY_EFI_PART_SIZE / 512;
1684 pSegment[segnum].data_offset = data_offset;
1685 data_offset += pSegment[segnum].sector_num * 512;
1686 segnum++;
1687
1688 if (PartStyle)
1689 {
1690 Log("Writing backup gpt table ............................. ");
1691 fwrite(pBkGptPartTbl, 1, 33 * 512, fp);
1692 pSegment[segnum].disk_start_sector = pPhyDrive->SizeInBytes / 512 - 33;
1693 pSegment[segnum].sector_num = 33;
1694 pSegment[segnum].data_offset = data_offset;
1695 data_offset += pSegment[segnum].sector_num * 512;
1696 segnum++;
1697 }
1698
1699 Log("Writing segment metadata ............................. ");
1700
1701 for (i = 0; i < (int)segnum; i++)
1702 {
1703 Log("SEG[%d]: PhySector:%llu SectorNum:%llu DataOffset:%llu(sector:%llu)", i, pSegment[i].disk_start_sector, pSegment[i].sector_num,
1704 pSegment[i].data_offset, pSegment[i].data_offset / 512);
1705 }
1706
1707 dataLen = segnum * sizeof(VTSI_SEGMENT);
1708 fwrite(pSegment, 1, dataLen, fp);
1709
1710 if (dataLen % 512)
1711 {
1712 //pData + SIZE_1MB - 8192 is a temp data buffer with zero
1713 fwrite(pData + SIZE_1MB - 8192, 1, 512 - (dataLen % 512), fp);
1714 }
1715
1716 //Fill footer
1717 pImgFooter->magic = VTSI_IMG_MAGIC;
1718 pImgFooter->version = 1;
1719 pImgFooter->disk_size = pPhyDrive->SizeInBytes;
1720 memcpy(&pImgFooter->disk_signature, pPhyDrive->MBR.BootCode + 0x1b8, 4);
1721 pImgFooter->segment_num = segnum;
1722 pImgFooter->segment_offset = data_offset;
1723
1724 for (i = 0, chksum = 0; i < (int)(segnum * sizeof(VTSI_SEGMENT)); i++)
1725 {
1726 chksum += *((UINT8 *)pSegment + i);
1727 }
1728 pImgFooter->segment_chksum = ~chksum;
1729
1730 for (i = 0, chksum = 0; i < sizeof(VTSI_FOOTER); i++)
1731 {
1732 chksum += *((UINT8 *)pImgFooter + i);
1733 }
1734 pImgFooter->foot_chksum = ~chksum;
1735
1736 Log("Writing footer segnum(%u) segoffset(%llu) ......................", segnum, data_offset);
1737 Log("disk_size=%llu disk_signature=%lx segment_offset=%llu", pImgFooter->disk_size, pImgFooter->disk_signature, pImgFooter->segment_offset);
1738
1739 fwrite(pImgFooter, 1, sizeof(VTSI_FOOTER), fp);
1740 fclose(fp);
1741
1742 Log("Writing Ventoy image file finished, the file size should be %llu .", data_offset + 512 + ((dataLen + 511) / 512 * 512));
1743
1744 rc = 0;
1745
1746 End:
1747
1748 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
1749
1750 Log("retcode:%d\n", rc);
1751
1752 SAFE_FREE(pData);
1753 SAFE_FREE(ImgBuf);
1754
1755 return rc;
1756 }
1757
1758
1759 int InstallVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive, int PartStyle)
1760 {
1761 int i;
1762 int rc = 0;
1763 int state = 0;
1764 HANDLE hDrive;
1765 DWORD dwSize;
1766 BOOL bRet;
1767 CHAR MountDrive;
1768 CHAR DriveName[] = "?:\\";
1769 CHAR DriveLetters[MAX_PATH] = { 0 };
1770 MBR_HEAD MBR;
1771 VTOY_GPT_INFO *pGptInfo = NULL;
1772 UINT64 Part1StartSector = 0;
1773 UINT64 Part1SectorCount = 0;
1774 UINT64 Part2StartSector = 0;
1775
1776 Log("InstallVentoy2PhyDrive %s PhyDrive%d <<%s %s %dGB>>",
1777 PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
1778 GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
1779
1780 if (PartStyle)
1781 {
1782 pGptInfo = malloc(sizeof(VTOY_GPT_INFO));
1783 memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO));
1784 }
1785
1786 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
1787
1788 if (PartStyle)
1789 {
1790 VentoyFillGpt(pPhyDrive->SizeInBytes, pGptInfo);
1791 Part1StartSector = pGptInfo->PartTbl[0].StartLBA;
1792 Part1SectorCount = pGptInfo->PartTbl[0].LastLBA - Part1StartSector + 1;
1793 Part2StartSector = pGptInfo->PartTbl[1].StartLBA;
1794 }
1795 else
1796 {
1797 VentoyFillMBR(pPhyDrive->SizeInBytes, &MBR, PartStyle);
1798 Part1StartSector = MBR.PartTbl[0].StartSectorId;
1799 Part1SectorCount = MBR.PartTbl[0].SectorCount;
1800 Part2StartSector = MBR.PartTbl[1].StartSectorId;
1801 }
1802
1803 Log("Lock disk for clean ............................. ");
1804
1805 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
1806 if (hDrive == INVALID_HANDLE_VALUE)
1807 {
1808 Log("Failed to open physical disk");
1809 free(pGptInfo);
1810 return 1;
1811 }
1812
1813 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
1814
1815 if (DriveLetters[0] == 0)
1816 {
1817 Log("No drive letter was assigned...");
1818 DriveName[0] = GetFirstUnusedDriveLetter();
1819 Log("GetFirstUnusedDriveLetter %C: ...", DriveName[0]);
1820 }
1821 else
1822 {
1823 // Unmount all mounted volumes that belong to this drive
1824 // Do it in reverse so that we always end on the first volume letter
1825 for (i = (int)strlen(DriveLetters); i > 0; i--)
1826 {
1827 DriveName[0] = DriveLetters[i - 1];
1828 bRet = DeleteVolumeMountPointA(DriveName);
1829 Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, GetLastError());
1830 }
1831 }
1832
1833 MountDrive = DriveName[0];
1834 Log("Will use '%C:' as volume mountpoint", DriveName[0]);
1835
1836 // It kind of blows, but we have to relinquish access to the physical drive
1837 // for VDS to be able to delete the partitions that reside on it...
1838 DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
1839 CHECK_CLOSE_HANDLE(hDrive);
1840
1841 PROGRESS_BAR_SET_POS(PT_DEL_ALL_PART);
1842
1843 if (!DeletePartitions(pPhyDrive->PhyDrive, FALSE))
1844 {
1845 Log("Notice: Could not delete partitions: %u", GetLastError());
1846 }
1847
1848 Log("Deleting all partitions ......................... OK");
1849
1850 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
1851
1852 Log("Lock disk for write ............................. ");
1853 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
1854 if (hDrive == INVALID_HANDLE_VALUE)
1855 {
1856 Log("Failed to GetPhysicalHandle for write.");
1857 rc = 1;
1858 goto End;
1859 }
1860
1861 //Refresh Drive Layout
1862 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
1863
1864 disk_io_set_param(hDrive, Part1StartSector + Part1SectorCount);// include the 2048 sector gap
1865
1866 PROGRESS_BAR_SET_POS(PT_FORMAT_PART1);
1867
1868 if (PartStyle == 1 && pPhyDrive->PartStyle == 0)
1869 {
1870 Log("Wait for format part1 ...");
1871 Sleep(1000 * 5);
1872 }
1873
1874 Log("Formatting part1 exFAT ...");
1875 if (0 != FormatPart1exFAT(pPhyDrive->SizeInBytes))
1876 {
1877 Log("FormatPart1exFAT failed.");
1878 rc = 1;
1879 goto End;
1880 }
1881
1882 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);
1883 Log("Writing part2 FAT img ...");
1884
1885 if (0 != FormatPart2Fat(hDrive, Part2StartSector))
1886 {
1887 Log("FormatPart2Fat failed.");
1888 rc = 1;
1889 goto End;
1890 }
1891
1892 PROGRESS_BAR_SET_POS(PT_WRITE_STG1_IMG);
1893 Log("Writing Boot Image ............................. ");
1894 if (WriteGrubStage1ToPhyDrive(hDrive, PartStyle) != 0)
1895 {
1896 Log("WriteGrubStage1ToPhyDrive failed.");
1897 rc = 1;
1898 goto End;
1899 }
1900
1901 PROGRESS_BAR_SET_POS(PT_WRITE_PART_TABLE);
1902 Log("Writing Partition Table ........................ ");
1903 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
1904
1905 if (PartStyle)
1906 {
1907 VTOY_GPT_HDR BackupHead;
1908 LARGE_INTEGER liCurrentPosition;
1909
1910 SET_FILE_POS(pPhyDrive->SizeInBytes - 512);
1911 VentoyFillBackupGptHead(pGptInfo, &BackupHead);
1912 if (!WriteFile(hDrive, &BackupHead, sizeof(VTOY_GPT_HDR), &dwSize, NULL))
1913 {
1914 rc = 1;
1915 Log("Write GPT Backup Head Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1916 goto End;
1917 }
1918
1919 SET_FILE_POS(pPhyDrive->SizeInBytes - 512 * 33);
1920 if (!WriteFile(hDrive, pGptInfo->PartTbl, sizeof(pGptInfo->PartTbl), &dwSize, NULL))
1921 {
1922 rc = 1;
1923 Log("Write GPT Backup Part Table Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1924 goto End;
1925 }
1926
1927 SET_FILE_POS(0);
1928 if (!WriteFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL))
1929 {
1930 rc = 1;
1931 Log("Write GPT Info Failed, dwSize:%u (%u) ErrCode:%u", dwSize, sizeof(VTOY_GPT_INFO), GetLastError());
1932 goto End;
1933 }
1934
1935 Log("Write GPT Info OK ...");
1936 memcpy(&(pPhyDrive->MBR), &(pGptInfo->MBR), 512);
1937 }
1938 else
1939 {
1940 if (!WriteFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL))
1941 {
1942 rc = 1;
1943 Log("Write MBR Failed, dwSize:%u ErrCode:%u", dwSize, GetLastError());
1944 goto End;
1945 }
1946 Log("Write MBR OK ...");
1947 memcpy(&(pPhyDrive->MBR), &MBR, 512);
1948 }
1949
1950 //Refresh Drive Layout
1951 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
1952
1953 End:
1954
1955 PROGRESS_BAR_SET_POS(PT_MOUNT_VOLUME);
1956
1957 if (rc == 0)
1958 {
1959 Log("Mounting Ventoy Partition ....................... ");
1960 Sleep(1000);
1961
1962 state = 0;
1963 memset(DriveLetters, 0, sizeof(DriveLetters));
1964 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
1965 Log("Logical drive letter after write ventoy: <%s>", DriveLetters);
1966
1967 for (i = 0; i < sizeof(DriveLetters) && DriveLetters[i]; i++)
1968 {
1969 DriveName[0] = DriveLetters[i];
1970 if (IsVentoyLogicalDrive(DriveName[0]))
1971 {
1972 Log("%s is ventoy part2, delete mountpoint", DriveName);
1973 DeleteVolumeMountPointA(DriveName);
1974 }
1975 else
1976 {
1977 Log("%s is ventoy part1, already mounted", DriveName);
1978 state = 1;
1979 }
1980 }
1981
1982 if (state != 1)
1983 {
1984 Log("need to mount ventoy part1...");
1985
1986 if (0 == GetVentoyVolumeName(pPhyDrive->PhyDrive, Part1StartSector, DriveLetters, sizeof(DriveLetters), FALSE))
1987 {
1988 DriveName[0] = MountDrive;
1989 bRet = SetVolumeMountPointA(DriveName, DriveLetters);
1990 Log("SetVolumeMountPoint <%s> <%s> bRet:%u code:%u", DriveName, DriveLetters, bRet, GetLastError());
1991 }
1992 else
1993 {
1994 Log("Failed to find ventoy volume");
1995 }
1996 }
1997 Log("OK\n");
1998 }
1999 else
2000 {
2001 FindProcessOccupyDisk(hDrive, pPhyDrive);
2002 }
2003
2004 if (pGptInfo)
2005 {
2006 free(pGptInfo);
2007 }
2008
2009 CHECK_CLOSE_HANDLE(hDrive);
2010 return rc;
2011 }
2012
2013 int UpdateVentoy2PhyDrive(PHY_DRIVE_INFO *pPhyDrive)
2014 {
2015 int i;
2016 int rc = 0;
2017 BOOL ForceMBR = FALSE;
2018 HANDLE hVolume;
2019 HANDLE hDrive;
2020 DWORD Status;
2021 DWORD dwSize;
2022 BOOL bRet;
2023 CHAR DriveName[] = "?:\\";
2024 CHAR DriveLetters[MAX_PATH] = { 0 };
2025 UINT64 StartSector;
2026 UINT64 ReservedMB = 0;
2027 MBR_HEAD BootImg;
2028 MBR_HEAD MBR;
2029 VTOY_GPT_INFO *pGptInfo = NULL;
2030 UINT8 ReservedData[4096];
2031
2032 Log("UpdateVentoy2PhyDrive %s PhyDrive%d <<%s %s %dGB>>",
2033 pPhyDrive->PartStyle ? "GPT" : "MBR", pPhyDrive->PhyDrive, pPhyDrive->VendorId, pPhyDrive->ProductId,
2034 GetHumanReadableGBSize(pPhyDrive->SizeInBytes));
2035
2036 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_CLEAN);
2037
2038 Log("Lock disk for umount ............................ ");
2039
2040 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, FALSE, FALSE);
2041 if (hDrive == INVALID_HANDLE_VALUE)
2042 {
2043 Log("Failed to open physical disk");
2044 return 1;
2045 }
2046
2047 if (pPhyDrive->PartStyle)
2048 {
2049 pGptInfo = malloc(sizeof(VTOY_GPT_INFO));
2050 if (!pGptInfo)
2051 {
2052 return 1;
2053 }
2054
2055 memset(pGptInfo, 0, sizeof(VTOY_GPT_INFO));
2056
2057 // Read GPT Info
2058 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
2059 ReadFile(hDrive, pGptInfo, sizeof(VTOY_GPT_INFO), &dwSize, NULL);
2060
2061 //MBR will be used to compare with local boot image
2062 memcpy(&MBR, &pGptInfo->MBR, sizeof(MBR_HEAD));
2063
2064 StartSector = pGptInfo->PartTbl[1].StartLBA;
2065 Log("GPT StartSector in PartTbl:%llu", (ULONGLONG)StartSector);
2066
2067 ReservedMB = (pPhyDrive->SizeInBytes / 512 - (StartSector + VENTOY_EFI_PART_SIZE / 512) - 33) / 2048;
2068 Log("GPT Reserved Disk Space:%llu MB", (ULONGLONG)ReservedMB);
2069 }
2070 else
2071 {
2072 // Read MBR
2073 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
2074 ReadFile(hDrive, &MBR, sizeof(MBR), &dwSize, NULL);
2075
2076 StartSector = MBR.PartTbl[1].StartSectorId;
2077 Log("MBR StartSector in PartTbl:%llu", (ULONGLONG)StartSector);
2078
2079 ReservedMB = (pPhyDrive->SizeInBytes / 512 - (StartSector + VENTOY_EFI_PART_SIZE / 512)) / 2048;
2080 Log("MBR Reserved Disk Space:%llu MB", (ULONGLONG)ReservedMB);
2081 }
2082
2083 //Read Reserved Data
2084 SetFilePointer(hDrive, 512 * 2040, NULL, FILE_BEGIN);
2085 ReadFile(hDrive, ReservedData, sizeof(ReservedData), &dwSize, NULL);
2086
2087 GetLettersBelongPhyDrive(pPhyDrive->PhyDrive, DriveLetters, sizeof(DriveLetters));
2088
2089 if (DriveLetters[0] == 0)
2090 {
2091 Log("No drive letter was assigned...");
2092 }
2093 else
2094 {
2095 // Unmount all mounted volumes that belong to this drive
2096 // Do it in reverse so that we always end on the first volume letter
2097 for (i = (int)strlen(DriveLetters); i > 0; i--)
2098 {
2099 DriveName[0] = DriveLetters[i - 1];
2100 if (IsVentoyLogicalDrive(DriveName[0]))
2101 {
2102 Log("%s is ventoy logical drive", DriveName);
2103 bRet = DeleteVolumeMountPointA(DriveName);
2104 Log("Delete mountpoint %s ret:%u code:%u", DriveName, bRet, LASTERR);
2105 break;
2106 }
2107 }
2108 }
2109
2110 // It kind of blows, but we have to relinquish access to the physical drive
2111 // for VDS to be able to delete the partitions that reside on it...
2112 DeviceIoControl(hDrive, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
2113 CHECK_CLOSE_HANDLE(hDrive);
2114
2115 PROGRESS_BAR_SET_POS(PT_LOCK_FOR_WRITE);
2116
2117 Log("Lock disk for update ............................ ");
2118 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
2119 if (hDrive == INVALID_HANDLE_VALUE)
2120 {
2121 Log("Failed to GetPhysicalHandle for write.");
2122 rc = 1;
2123 goto End;
2124 }
2125
2126 PROGRESS_BAR_SET_POS(PT_LOCK_VOLUME);
2127
2128 Log("Lock volume for update .......................... ");
2129 hVolume = INVALID_HANDLE_VALUE;
2130 Status = GetVentoyVolumeName(pPhyDrive->PhyDrive, StartSector, DriveLetters, sizeof(DriveLetters), TRUE);
2131 if (ERROR_SUCCESS == Status)
2132 {
2133 Log("Now lock and dismount volume <%s>", DriveLetters);
2134 hVolume = CreateFileA(DriveLetters,
2135 GENERIC_READ | GENERIC_WRITE,
2136 FILE_SHARE_READ,
2137 NULL,
2138 OPEN_EXISTING,
2139 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
2140 NULL);
2141
2142 if (hVolume == INVALID_HANDLE_VALUE)
2143 {
2144 Log("Failed to create file volume, errcode:%u", LASTERR);
2145 rc = 1;
2146 goto End;
2147 }
2148
2149 bRet = DeviceIoControl(hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
2150 Log("FSCTL_LOCK_VOLUME bRet:%u code:%u", bRet, LASTERR);
2151
2152 bRet = DeviceIoControl(hVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
2153 Log("FSCTL_DISMOUNT_VOLUME bRet:%u code:%u", bRet, LASTERR);
2154 }
2155 else if (ERROR_NOT_FOUND == Status)
2156 {
2157 Log("Volume not found, maybe not supported");
2158 }
2159 else
2160 {
2161 rc = 1;
2162 goto End;
2163 }
2164
2165
2166 if (!TryWritePart2(hDrive, StartSector))
2167 {
2168 if (pPhyDrive->PartStyle == 0)
2169 {
2170 ForceMBR = TRUE;
2171 Log("Try write failed, now delete partition 2...");
2172
2173 CHECK_CLOSE_HANDLE(hDrive);
2174
2175 Log("Now delete partition 2...");
2176 DeletePartitions(pPhyDrive->PhyDrive, TRUE);
2177
2178 hDrive = GetPhysicalHandle(pPhyDrive->PhyDrive, TRUE, TRUE, FALSE);
2179 if (hDrive == INVALID_HANDLE_VALUE)
2180 {
2181 Log("Failed to GetPhysicalHandle for write.");
2182 rc = 1;
2183 goto End;
2184 }
2185 }
2186 }
2187
2188 PROGRESS_BAR_SET_POS(PT_FORMAT_PART2);
2189
2190 Log("Write Ventoy to disk ............................ ");
2191 if (0 != FormatPart2Fat(hDrive, StartSector))
2192 {
2193 rc = 1;
2194 goto End;
2195 }
2196
2197 if (hVolume != INVALID_HANDLE_VALUE)
2198 {
2199 bRet = DeviceIoControl(hVolume, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
2200 Log("FSCTL_UNLOCK_VOLUME bRet:%u code:%u", bRet, LASTERR);
2201 CHECK_CLOSE_HANDLE(hVolume);
2202 }
2203
2204 Log("Updating Boot Image ............................. ");
2205 if (WriteGrubStage1ToPhyDrive(hDrive, pPhyDrive->PartStyle) != 0)
2206 {
2207 rc = 1;
2208 goto End;
2209 }
2210
2211 //write reserved data
2212 SetFilePointer(hDrive, 512 * 2040, NULL, FILE_BEGIN);
2213 bRet = WriteFile(hDrive, ReservedData, sizeof(ReservedData), &dwSize, NULL);
2214 Log("Write resv data ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR);
2215
2216 // Boot Image
2217 VentoyGetLocalBootImg(&BootImg);
2218
2219 // Use Old UUID
2220 memcpy(BootImg.BootCode + 0x180, MBR.BootCode + 0x180, 16);
2221 if (pPhyDrive->PartStyle)
2222 {
2223 BootImg.BootCode[92] = 0x22;
2224 }
2225
2226 if (ForceMBR == FALSE && memcmp(BootImg.BootCode, MBR.BootCode, 440) == 0)
2227 {
2228 Log("Boot image has no difference, no need to write.");
2229 }
2230 else
2231 {
2232 Log("Boot image need to write %u.", ForceMBR);
2233
2234 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
2235
2236 memcpy(MBR.BootCode, BootImg.BootCode, 440);
2237 bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);
2238 Log("Write Boot Image ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR);
2239 }
2240
2241 if (pPhyDrive->PartStyle == 0)
2242 {
2243 if (0x00 == MBR.PartTbl[0].Active && 0x80 == MBR.PartTbl[1].Active)
2244 {
2245 Log("Need to chage 1st partition active and 2nd partition inactive.");
2246
2247 MBR.PartTbl[0].Active = 0x80;
2248 MBR.PartTbl[1].Active = 0x00;
2249
2250 SetFilePointer(hDrive, 0, NULL, FILE_BEGIN);
2251 bRet = WriteFile(hDrive, &MBR, 512, &dwSize, NULL);
2252 Log("Write NEW MBR ret:%u dwSize:%u Error:%u", bRet, dwSize, LASTERR);
2253 }
2254 }
2255
2256 //Refresh Drive Layout
2257 DeviceIoControl(hDrive, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &dwSize, NULL);
2258
2259 End:
2260
2261 if (rc == 0)
2262 {
2263 Log("OK");
2264 }
2265 else
2266 {
2267 FindProcessOccupyDisk(hDrive, pPhyDrive);
2268 }
2269
2270 CHECK_CLOSE_HANDLE(hDrive);
2271
2272 if (pGptInfo)
2273 {
2274 free(pGptInfo);
2275 }
2276
2277 return rc;
2278 }
2279
2280