1 /******************************************************************************
4 * Copyright (c) 2021, 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/>.
27 #include "Ventoy2Disk.h"
28 #include "DiskService.h"
32 // Count on Microsoft to add a new API while not bothering updating the existing error facilities,
33 // so that the new error messages have to be handled manually. Now, since I don't have all day:
34 // 1. Copy text from https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-vds/5102cc53-3143-4268-ba4c-6ea39e999ab4
35 // 2. awk '{l[NR%7]=$0} {if (NR%7==0) printf "\tcase %s:\t// %s\n\t\treturn \"%s\";\n", l[1], l[3], l[6]}' vds.txt
36 // 3. Filter out the crap we don't need.
37 static const char *GetVdsError(DWORD error_code
)
41 sprintf_s(code
, sizeof(code
), "[0x%08x]", error_code
);
44 case 0x80042400: // VDS_E_NOT_SUPPORTED
45 return "The operation is not supported by the object.";
46 case 0x80042401: // VDS_E_INITIALIZED_FAILED
47 return "VDS or the provider failed to initialize.";
48 case 0x80042402: // VDS_E_INITIALIZE_NOT_CALLED
49 return "VDS did not call the hardware provider's initialization method.";
50 case 0x80042403: // VDS_E_ALREADY_REGISTERED
51 return "The provider is already registered.";
52 case 0x80042404: // VDS_E_ANOTHER_CALL_IN_PROGRESS
53 return "A concurrent second call is made on an object before the first call is completed.";
54 case 0x80042405: // VDS_E_OBJECT_NOT_FOUND
55 return "The specified object was not found.";
56 case 0x80042406: // VDS_E_INVALID_SPACE
57 return "The specified space is neither free nor valid.";
58 case 0x80042407: // VDS_E_PARTITION_LIMIT_REACHED
59 return "No more partitions can be created on the specified disk.";
60 case 0x80042408: // VDS_E_PARTITION_NOT_EMPTY
61 return "The extended partition is not empty.";
62 case 0x80042409: // VDS_E_OPERATION_PENDING
63 return "The operation is still in progress.";
64 case 0x8004240A: // VDS_E_OPERATION_DENIED
65 return "The operation is not permitted on the specified disk, partition, or volume.";
66 case 0x8004240B: // VDS_E_OBJECT_DELETED
67 return "The object no longer exists.";
68 case 0x8004240C: // VDS_E_CANCEL_TOO_LATE
69 return "The operation can no longer be canceled.";
70 case 0x8004240D: // VDS_E_OPERATION_CANCELED
71 return "The operation has already been canceled.";
72 case 0x8004240E: // VDS_E_CANNOT_EXTEND
73 return "The file system does not support extending this volume.";
74 case 0x8004240F: // VDS_E_NOT_ENOUGH_SPACE
75 return "There is not enough space to complete the operation.";
76 case 0x80042410: // VDS_E_NOT_ENOUGH_DRIVE
77 return "There are not enough free disk drives in the subsystem to complete the operation.";
78 case 0x80042411: // VDS_E_BAD_COOKIE
79 return "The cookie was not found.";
80 case 0x80042412: // VDS_E_NO_MEDIA
81 return "There is no removable media in the drive.";
82 case 0x80042413: // VDS_E_DEVICE_IN_USE
83 return "The device is currently in use.";
84 case 0x80042414: // VDS_E_DISK_NOT_EMPTY
85 return "The disk contains partitions or volumes.";
86 case 0x80042415: // VDS_E_INVALID_OPERATION
87 return "The specified operation is not valid.";
88 case 0x80042416: // VDS_E_PATH_NOT_FOUND
89 return "The specified path was not found.";
90 case 0x80042417: // VDS_E_DISK_NOT_INITIALIZED
91 return "The specified disk has not been initialized.";
92 case 0x80042418: // VDS_E_NOT_AN_UNALLOCATED_DISK
93 return "The specified disk is not an unallocated disk.";
94 case 0x80042419: // VDS_E_UNRECOVERABLE_ERROR
95 return "An unrecoverable error occurred. The service MUST shut down.";
96 case 0x0004241A: // VDS_S_DISK_PARTIALLY_CLEANED
97 return "The clean operation was not a full clean or was canceled before it could be completed.";
98 case 0x8004241B: // VDS_E_DMADMIN_SERVICE_CONNECTION_FAILED
99 return "The provider failed to connect to the LDMA service.";
100 case 0x8004241C: // VDS_E_PROVIDER_INITIALIZATION_FAILED
101 return "The provider failed to initialize.";
102 case 0x8004241D: // VDS_E_OBJECT_EXISTS
103 return "The object already exists.";
104 case 0x8004241E: // VDS_E_NO_DISKS_FOUND
105 return "No disks were found on the target machine.";
106 case 0x8004241F: // VDS_E_PROVIDER_CACHE_CORRUPT
107 return "The cache for a provider is corrupt.";
108 case 0x80042420: // VDS_E_DMADMIN_METHOD_CALL_FAILED
109 return "A method call to the LDMA service failed.";
110 case 0x00042421: // VDS_S_PROVIDER_ERROR_LOADING_CACHE
111 return "The provider encountered errors while loading the cache.";
112 case 0x80042422: // VDS_E_PROVIDER_VOL_DEVICE_NAME_NOT_FOUND
113 return "The device form of the volume pathname could not be retrieved.";
114 case 0x80042423: // VDS_E_PROVIDER_VOL_OPEN
115 return "Failed to open the volume device";
116 case 0x80042424: // VDS_E_DMADMIN_CORRUPT_NOTIFICATION
117 return "A corrupt notification was sent from the LDMA service.";
118 case 0x80042425: // VDS_E_INCOMPATIBLE_FILE_SYSTEM
119 return "The file system is incompatible with the specified operation.";
120 case 0x80042426: // VDS_E_INCOMPATIBLE_MEDIA
121 return "The media is incompatible with the specified operation.";
122 case 0x80042427: // VDS_E_ACCESS_DENIED
123 return "Access is denied. A VDS operation MUST run elevated.";
124 case 0x80042428: // VDS_E_MEDIA_WRITE_PROTECTED
125 return "The media is write-protected.";
126 case 0x80042429: // VDS_E_BAD_LABEL
127 return "The volume label is not valid.";
128 case 0x8004242A: // VDS_E_CANT_QUICK_FORMAT
129 return "The volume cannot be quick-formatted.";
130 case 0x8004242B: // VDS_E_IO_ERROR
131 return "An I/O error occurred during the operation.";
132 case 0x8004242C: // VDS_E_VOLUME_TOO_SMALL
133 return "The volume size is too small.";
134 case 0x8004242D: // VDS_E_VOLUME_TOO_BIG
135 return "The volume size is too large.";
136 case 0x8004242E: // VDS_E_CLUSTER_SIZE_TOO_SMALL
137 return "The cluster size is too small.";
138 case 0x8004242F: // VDS_E_CLUSTER_SIZE_TOO_BIG
139 return "The cluster size is too large.";
140 case 0x80042430: // VDS_E_CLUSTER_COUNT_BEYOND_32BITS
141 return "The number of clusters is too large to be represented as a 32-bit integer.";
142 case 0x80042431: // VDS_E_OBJECT_STATUS_FAILED
143 return "The component that the object represents has failed.";
144 case 0x80042432: // VDS_E_VOLUME_INCOMPLETE
145 return "The volume is incomplete.";
146 case 0x80042433: // VDS_E_EXTENT_SIZE_LESS_THAN_MIN
147 return "The specified extent size is too small.";
148 case 0x00042434: // VDS_S_UPDATE_BOOTFILE_FAILED
149 return "The operation was successful, but VDS failed to update the boot options.";
150 case 0x00042436: // VDS_S_BOOT_PARTITION_NUMBER_CHANGE
151 case 0x80042436: // VDS_E_BOOT_PARTITION_NUMBER_CHANGE
152 return "The boot partition's partition number will change as a result of the operation.";
153 case 0x80042437: // VDS_E_NO_FREE_SPACE
154 return "The specified disk does not have enough free space to complete the operation.";
155 case 0x80042438: // VDS_E_ACTIVE_PARTITION
156 return "An active partition was detected on the selected disk.";
157 case 0x80042439: // VDS_E_PARTITION_OF_UNKNOWN_TYPE
158 return "The partition information cannot be read.";
159 case 0x8004243A: // VDS_E_LEGACY_VOLUME_FORMAT
160 return "A partition with an unknown type was detected on the specified disk.";
161 case 0x8004243C: // VDS_E_MIGRATE_OPEN_VOLUME
162 return "A volume on the specified disk could not be opened.";
163 case 0x8004243D: // VDS_E_VOLUME_NOT_ONLINE
164 return "The volume is not online.";
165 case 0x8004243E: // VDS_E_VOLUME_NOT_HEALTHY
166 return "The volume is failing or has failed.";
167 case 0x8004243F: // VDS_E_VOLUME_SPANS_DISKS
168 return "The volume spans multiple disks.";
169 case 0x80042440: // VDS_E_REQUIRES_CONTIGUOUS_DISK_SPACE
170 return "The volume does not consist of a single disk extent.";
171 case 0x80042441: // VDS_E_BAD_PROVIDER_DATA
172 return "A provider returned bad data.";
173 case 0x80042442: // VDS_E_PROVIDER_FAILURE
174 return "A provider failed to complete an operation.";
175 case 0x00042443: // VDS_S_VOLUME_COMPRESS_FAILED
176 return "The file system was formatted successfully but could not be compressed.";
177 case 0x80042444: // VDS_E_PACK_OFFLINE
178 return "The pack is offline.";
179 case 0x80042445: // VDS_E_VOLUME_NOT_A_MIRROR
180 return "The volume is not a mirror.";
181 case 0x80042446: // VDS_E_NO_EXTENTS_FOR_VOLUME
182 return "No extents were found for the volume.";
183 case 0x80042447: // VDS_E_DISK_NOT_LOADED_TO_CACHE
184 return "The migrated disk failed to load to the cache.";
185 case 0x80042448: // VDS_E_INTERNAL_ERROR
186 return "VDS encountered an internal error.";
187 case 0x8004244A: // VDS_E_PROVIDER_TYPE_NOT_SUPPORTED
188 return "The method call is not supported for the specified provider type.";
189 case 0x8004244B: // VDS_E_DISK_NOT_ONLINE
190 return "One or more of the specified disks are not online.";
191 case 0x8004244C: // VDS_E_DISK_IN_USE_BY_VOLUME
192 return "One or more extents of the disk are already being used by the volume.";
193 case 0x0004244D: // VDS_S_IN_PROGRESS
194 return "The asynchronous operation is in progress.";
195 case 0x8004244E: // VDS_E_ASYNC_OBJECT_FAILURE
196 return "Failure initializing the asynchronous object.";
197 case 0x8004244F: // VDS_E_VOLUME_NOT_MOUNTED
198 return "The volume is not mounted.";
199 case 0x80042450: // VDS_E_PACK_NOT_FOUND
200 return "The pack was not found.";
201 case 0x80042453: // VDS_E_OBJECT_OUT_OF_SYNC
202 return "The reference to the object might be stale.";
203 case 0x80042454: // VDS_E_MISSING_DISK
204 return "The specified disk could not be found.";
205 case 0x80042455: // VDS_E_DISK_PNP_REG_CORRUPT
206 return "The provider's list of PnP registered disks has become corrupted.";
207 case 0x80042457: // VDS_E_NO_DRIVELETTER_FLAG
208 return "The provider does not support the VDS_VF_NO DRIVELETTER volume flag.";
209 case 0x80042459: // VDS_E_REVERT_ON_CLOSE_SET
210 return "Some volume flags are already set.";
211 case 0x0004245B: // VDS_S_UNABLE_TO_GET_GPT_ATTRIBUTES
212 return "Unable to retrieve the GPT attributes for this volume.";
213 case 0x8004245C: // VDS_E_VOLUME_TEMPORARILY_DISMOUNTED
214 return "The volume is already dismounted temporarily.";
215 case 0x8004245D: // VDS_E_VOLUME_PERMANENTLY_DISMOUNTED
216 return "The volume is already permanently dismounted.";
217 case 0x8004245E: // VDS_E_VOLUME_HAS_PATH
218 return "The volume cannot be dismounted permanently because it still has an access path.";
219 case 0x8004245F: // VDS_E_TIMEOUT
220 return "The operation timed out.";
221 case 0x80042461: // VDS_E_LDM_TIMEOUT
222 return "The operation timed out in the LDMA service. Retry the operation.";
223 case 0x80042462: // VDS_E_REVERT_ON_CLOSE_MISMATCH
224 return "The flags to be cleared do not match the flags that were set previously.";
225 case 0x80042463: // VDS_E_RETRY
226 return "The operation failed. Retry the operation.";
227 case 0x80042464: // VDS_E_ONLINE_PACK_EXISTS
228 return "The operation failed, because an online pack object already exists.";
229 case 0x80042468: // VDS_E_MAX_USABLE_MBR
230 return "Only the first 2TB are usable on large MBR disks.";
231 case 0x80042500: // VDS_E_NO_SOFTWARE_PROVIDERS_LOADED
232 return "There are no software providers loaded.";
233 case 0x80042501: // VDS_E_DISK_NOT_MISSING
234 return "The disk is not missing.";
235 case 0x80042502: // VDS_E_NO_VOLUME_LAYOUT
236 return "The volume's layout could not be retrieved.";
237 case 0x80042503: // VDS_E_CORRUPT_VOLUME_INFO
238 return "The volume's driver information is corrupted.";
239 case 0x80042504: // VDS_E_INVALID_ENUMERATOR
240 return "The enumerator is corrupted";
241 case 0x80042505: // VDS_E_DRIVER_INTERNAL_ERROR
242 return "An internal error occurred in the volume management driver.";
243 case 0x80042507: // VDS_E_VOLUME_INVALID_NAME
244 return "The volume name is not valid.";
245 case 0x00042508: // VDS_S_DISK_IS_MISSING
246 return "The disk is missing and not all information could be returned.";
247 case 0x80042509: // VDS_E_CORRUPT_PARTITION_INFO
248 return "The disk's partition information is corrupted.";
249 case 0x0004250A: // VDS_S_NONCONFORMANT_PARTITION_INFO
250 return "The disk's partition information does not conform to what is expected on a dynamic disk.";
251 case 0x8004250B: // VDS_E_CORRUPT_EXTENT_INFO
252 return "The disk's extent information is corrupted.";
253 case 0x0004250E: // VDS_S_SYSTEM_PARTITION
254 return "Warning: There was a failure while checking for the system partition.";
255 case 0x8004250F: // VDS_E_BAD_PNP_MESSAGE
256 return "The PNP service sent a corrupted notification to the provider.";
257 case 0x80042510: // VDS_E_NO_PNP_DISK_ARRIVE
258 case 0x80042511: // VDS_E_NO_PNP_VOLUME_ARRIVE
259 return "No disk/volume arrival notification was received.";
260 case 0x80042512: // VDS_E_NO_PNP_DISK_REMOVE
261 case 0x80042513: // VDS_E_NO_PNP_VOLUME_REMOVE
262 return "No disk/volume removal notification was received.";
263 case 0x80042514: // VDS_E_PROVIDER_EXITING
264 return "The provider is exiting.";
265 case 0x00042517: // VDS_S_NO_NOTIFICATION
266 return "No volume arrival notification was received.";
267 case 0x80042519: // VDS_E_INVALID_DISK
268 return "The specified disk is not valid.";
269 case 0x8004251A: // VDS_E_INVALID_PACK
270 return "The specified disk pack is not valid.";
271 case 0x8004251B: // VDS_E_VOLUME_ON_DISK
272 return "This operation is not allowed on disks with volumes.";
273 case 0x8004251C: // VDS_E_DRIVER_INVALID_PARAM
274 return "The driver returned an invalid parameter error.";
275 case 0x8004253D: // VDS_E_DRIVER_OBJECT_NOT_FOUND
276 return "The object was not found in the driver cache.";
277 case 0x8004253E: // VDS_E_PARTITION_NOT_CYLINDER_ALIGNED
278 return "The disk layout contains partitions which are not cylinder aligned.";
279 case 0x8004253F: // VDS_E_DISK_LAYOUT_PARTITIONS_TOO_SMALL
280 return "The disk layout contains partitions which are less than the minimum required size.";
281 case 0x80042540: // VDS_E_DISK_IO_FAILING
282 return "The I/O to the disk is failing.";
283 case 0x80042543: // VDS_E_GPT_ATTRIBUTES_INVALID
284 return "Invalid GPT attributes were specified.";
285 case 0x8004254D: // VDS_E_UNEXPECTED_DISK_LAYOUT_CHANGE
286 return "An unexpected layout change occurred external to the volume manager.";
287 case 0x8004254E: // VDS_E_INVALID_VOLUME_LENGTH
288 return "The volume length is invalid.";
289 case 0x8004254F: // VDS_E_VOLUME_LENGTH_NOT_SECTOR_SIZE_MULTIPLE
290 return "The volume length is not a multiple of the sector size.";
291 case 0x80042550: // VDS_E_VOLUME_NOT_RETAINED
292 return "The volume does not have a retained partition association.";
293 case 0x80042551: // VDS_E_VOLUME_RETAINED
294 return "The volume already has a retained partition association.";
295 case 0x80042553: // VDS_E_ALIGN_BEYOND_FIRST_CYLINDER
296 return "The specified alignment is beyond the first cylinder.";
297 case 0x80042554: // VDS_E_ALIGN_NOT_SECTOR_SIZE_MULTIPLE
298 return "The specified alignment is not a multiple of the sector size.";
299 case 0x80042555: // VDS_E_ALIGN_NOT_ZERO
300 return "The specified partition type cannot be created with a non-zero alignment.";
301 case 0x80042556: // VDS_E_CACHE_CORRUPT
302 return "The service's cache has become corrupt.";
303 case 0x80042557: // VDS_E_CANNOT_CLEAR_VOLUME_FLAG
304 return "The specified volume flag cannot be cleared.";
305 case 0x80042558: // VDS_E_DISK_BEING_CLEANED
306 return "The operation is not allowed on a disk that is in the process of being cleaned.";
307 case 0x8004255A: // VDS_E_DISK_REMOVEABLE
308 return "The operation is not supported on removable media.";
309 case 0x8004255B: // VDS_E_DISK_REMOVEABLE_NOT_EMPTY
310 return "The operation is not supported on a non-empty removable disk.";
311 case 0x8004255C: // VDS_E_DRIVE_LETTER_NOT_FREE
312 return "The specified drive letter is not free to be assigned.";
313 case 0x8004255E: // VDS_E_INVALID_DRIVE_LETTER
314 return "The specified drive letter is not valid.";
315 case 0x8004255F: // VDS_E_INVALID_DRIVE_LETTER_COUNT
316 return "The specified number of drive letters to retrieve is not valid.";
317 case 0x80042560: // VDS_E_INVALID_FS_FLAG
318 return "The specified file system flag is not valid.";
319 case 0x80042561: // VDS_E_INVALID_FS_TYPE
320 return "The specified file system is not valid.";
321 case 0x80042562: // VDS_E_INVALID_OBJECT_TYPE
322 return "The specified object type is not valid.";
323 case 0x80042563: // VDS_E_INVALID_PARTITION_LAYOUT
324 return "The specified partition layout is invalid.";
325 case 0x80042564: // VDS_E_INVALID_PARTITION_STYLE
326 return "VDS only supports MBR or GPT partition style disks.";
327 case 0x80042565: // VDS_E_INVALID_PARTITION_TYPE
328 return "The specified partition type is not valid for this operation.";
329 case 0x80042566: // VDS_E_INVALID_PROVIDER_CLSID
330 case 0x80042567: // VDS_E_INVALID_PROVIDER_ID
331 case 0x8004256A: // VDS_E_INVALID_PROVIDER_VERSION_GUID
332 return "A NULL GUID was passed to the provider.";
333 case 0x80042568: // VDS_E_INVALID_PROVIDER_NAME
334 return "The specified provider name is invalid.";
335 case 0x80042569: // VDS_E_INVALID_PROVIDER_TYPE
336 return "The specified provider type is invalid.";
337 case 0x8004256B: // VDS_E_INVALID_PROVIDER_VERSION_STRING
338 return "The specified provider version string is invalid.";
339 case 0x8004256C: // VDS_E_INVALID_QUERY_PROVIDER_FLAG
340 return "The specified query provider flag is invalid.";
341 case 0x8004256D: // VDS_E_INVALID_SERVICE_FLAG
342 return "The specified service flag is invalid.";
343 case 0x8004256E: // VDS_E_INVALID_VOLUME_FLAG
344 return "The specified volume flag is invalid.";
345 case 0x8004256F: // VDS_E_PARTITION_NOT_OEM
346 return "The operation is only supported on an OEM, ESP, or unknown partition.";
347 case 0x80042570: // VDS_E_PARTITION_PROTECTED
348 return "Cannot delete a protected partition without the force protected parameter set.";
349 case 0x80042571: // VDS_E_PARTITION_STYLE_MISMATCH
350 return "The specified partition style is not the same as the disk's partition style.";
351 case 0x80042572: // VDS_E_PROVIDER_INTERNAL_ERROR
352 return "An internal error has occurred in the provider.";
353 case 0x80042575: // VDS_E_UNRECOVERABLE_PROVIDER_ERROR
354 return "An unrecoverable error occurred in the provider.";
355 case 0x80042576: // VDS_E_VOLUME_HIDDEN
356 return "Cannot assign a mount point to a hidden volume.";
357 case 0x00042577: // VDS_S_DISMOUNT_FAILED
358 case 0x00042578: // VDS_S_REMOUNT_FAILED
359 return "Failed to dismount/remount the volume after setting the volume flags.";
360 case 0x80042579: // VDS_E_FLAG_ALREADY_SET
361 return "Cannot set the specified flag as revert-on-close because it is already set.";
362 case 0x8004257B: // VDS_E_DISTINCT_VOLUME
363 return "The input volume id cannot be the id of the volume that is the target of the operation.";
364 case 0x00042583: // VDS_S_FS_LOCK
365 return "Failed to obtain a file system lock.";
366 case 0x80042584: // VDS_E_READONLY
367 return "The volume is read only.";
368 case 0x80042585: // VDS_E_INVALID_VOLUME_TYPE
369 return "The volume type is invalid for this operation.";
370 case 0x80042588: // VDS_E_VOLUME_MIRRORED
371 return "This operation is not supported on a mirrored volume.";
372 case 0x80042589: // VDS_E_VOLUME_SIMPLE_SPANNED
373 return "The operation is only supported on simple or spanned volumes.";
374 case 0x8004258C: // VDS_E_PARTITION_MSR
375 case 0x8004258D: // VDS_E_PARTITION_LDM
376 return "The operation is not supported on this type of partitions.";
377 case 0x0004258E: // VDS_S_WINPE_BOOTENTRY
378 return "The boot entries cannot be updated automatically on WinPE.";
379 case 0x8004258F: // VDS_E_ALIGN_NOT_A_POWER_OF_TWO
380 return "The alignment is not a power of two.";
381 case 0x80042590: // VDS_E_ALIGN_IS_ZERO
382 return "The alignment is zero.";
383 case 0x80042593: // VDS_E_FS_NOT_DETERMINED
384 return "The default file system could not be determined.";
385 case 0x80042595: // VDS_E_DISK_NOT_OFFLINE
386 return "This disk is already online.";
387 case 0x80042596: // VDS_E_FAILED_TO_ONLINE_DISK
388 return "The online operation failed.";
389 case 0x80042597: // VDS_E_FAILED_TO_OFFLINE_DISK
390 return "The offline operation failed.";
391 case 0x80042598: // VDS_E_BAD_REVISION_NUMBER
392 return "The operation could not be completed because the specified revision number is not supported.";
393 case 0x80042599: // VDS_E_SHRINK_USER_CANCELLED
394 return "The shrink operation was cancelled by the user.";
395 case 0x8004259a: // VDS_E_SHRINK_DIRTY_VOLUME
396 return "The volume you have selected to shrink may be corrupted. Use Chkdsk to fix the corruption problem, and then try again.";
397 case 0x00042700: // VDS_S_NAME_TRUNCATED
398 return "The name was set successfully but had to be truncated.";
399 case 0x80042701: // VDS_E_NAME_NOT_UNIQUE
400 return "The specified name is not unique.";
401 case 0x8004270F: // VDS_E_NO_DISK_PATHNAME
402 return "The disk's path could not be retrieved. Some operations on the disk might fail.";
403 case 0x80042711: // VDS_E_NO_VOLUME_PATHNAME
404 return "The path could not be retrieved for one or more volumes.";
405 case 0x80042712: // VDS_E_PROVIDER_CACHE_OUTOFSYNC
406 return "The provider's cache is not in sync with the driver cache.";
407 case 0x80042713: // VDS_E_NO_IMPORT_TARGET
408 return "No import target was set for the subsystem.";
409 case 0x00042714: // VDS_S_ALREADY_EXISTS
410 return "The object already exists.";
411 case 0x00042715: // VDS_S_PROPERTIES_INCOMPLETE
412 return "Some, but not all, of the properties were successfully retrieved.";
413 case 0x80042803: // VDS_E_UNABLE_TO_FIND_BOOT_DISK
414 return "Volume disk extent information could not be retrieved for the boot volume.";
415 case 0x80042807: // VDS_E_BOOT_DISK
416 return "Disk attributes cannot be changed on the boot disk.";
417 case 0x00042808: // VDS_S_DISK_MOUNT_FAILED
418 case 0x00042809: // VDS_S_DISK_DISMOUNT_FAILED
419 return "One or more of the volumes on the disk could not be mounted/dismounted.";
420 case 0x8004280A: // VDS_E_DISK_IS_OFFLINE
421 case 0x8004280B: // VDS_E_DISK_IS_READ_ONLY
422 return "The operation cannot be performed on a disk that is offline or read-only.";
423 case 0x8004280C: // VDS_E_PAGEFILE_DISK
424 case 0x8004280D: // VDS_E_HIBERNATION_FILE_DISK
425 case 0x8004280E: // VDS_E_CRASHDUMP_DISK
426 return "The operation cannot be performed on a disk that contains a pagefile, hibernation or crashdump volume.";
427 case 0x8004280F: // VDS_E_UNABLE_TO_FIND_SYSTEM_DISK
428 return "A system error occurred while retrieving the system disk information.";
429 case 0x80042810: // VDS_E_INCORRECT_SYSTEM_VOLUME_EXTENT_INFO
430 return "Multiple disk extents reported for the system volume - system error.";
431 case 0x80042811: // VDS_E_SYSTEM_DISK
432 return "Disk attributes cannot be changed on the current system disk or BIOS disk 0.";
433 case 0x80042823: // VDS_E_SECTOR_SIZE_ERROR
434 return "The sector size MUST be non-zero, a power of 2, and less than the maximum sector size.";
435 case 0x80042907: // VDS_E_SUBSYSTEM_ID_IS_NULL
436 return "The provider returned a NULL subsystem identification string.";
437 case 0x8004290C: // VDS_E_REBOOT_REQUIRED
438 return "A reboot is required before any further operations are initiated.";
439 case 0x8004290D: // VDS_E_VOLUME_GUID_PATHNAME_NOT_ALLOWED
440 return "Volume GUID pathnames are not valid input to this method.";
441 case 0x8004290E: // VDS_E_BOOT_PAGEFILE_DRIVE_LETTER
442 return "Assigning or removing drive letters on the current boot or pagefile volume is not allowed.";
443 case 0x8004290F: // VDS_E_DELETE_WITH_CRITICAL
444 return "Delete is not allowed on a critical volume.";
445 case 0x80042910: // VDS_E_CLEAN_WITH_DATA
446 case 0x80042911: // VDS_E_CLEAN_WITH_OEM
447 return "The FORCE parameter MUST be set to TRUE in order to clean a disk that contains a data or OEM volume.";
448 case 0x80042912: // VDS_E_CLEAN_WITH_CRITICAL
449 return "Clean is not allowed on a critical disk.";
450 case 0x80042913: // VDS_E_FORMAT_CRITICAL
451 return "Format is not allowed on a critical volume.";
452 case 0x80042914: // VDS_E_NTFS_FORMAT_NOT_SUPPORTED
453 case 0x80042915: // VDS_E_FAT32_FORMAT_NOT_SUPPORTED
454 case 0x80042916: // VDS_E_FAT_FORMAT_NOT_SUPPORTED
455 return "The requested file system format is not supported on this volume.";
456 case 0x80042917: // VDS_E_FORMAT_NOT_SUPPORTED
457 return "The volume is not formattable.";
458 case 0x80042918: // VDS_E_COMPRESSION_NOT_SUPPORTED
459 return "The specified file system does not support compression.";
465 static const char* GetVimError(DWORD error_code
)
467 switch (error_code
) {
469 return "The specified image in the specified wim is already mounted for read and write access.";
475 #define sfree(p) do {if (p != NULL) {free((void*)(p)); p = NULL;}} while(0)
476 #define wconvert(p) wchar_t* w ## p = utf8_to_wchar(p)
477 #define walloc(p, size) wchar_t* w ## p = (p == NULL)?NULL:(wchar_t*)calloc(size, sizeof(wchar_t))
478 #define wfree(p) sfree(w ## p)
479 #define wchar_to_utf8_no_alloc(wsrc, dest, dest_size) \
480 WideCharToMultiByte(CP_UTF8, 0, wsrc, -1, dest, dest_size, NULL, NULL)
482 static __inline DWORD
FormatMessageU(DWORD dwFlags
, LPCVOID lpSource
, DWORD dwMessageId
,
483 DWORD dwLanguageId
, char* lpBuffer
, DWORD nSize
, va_list *Arguments
)
485 DWORD ret
= 0, err
= ERROR_INVALID_DATA
;
486 // coverity[returned_null]
487 walloc(lpBuffer
, nSize
);
488 ret
= FormatMessageW(dwFlags
, lpSource
, dwMessageId
, dwLanguageId
, wlpBuffer
, nSize
, Arguments
);
489 err
= GetLastError();
490 if ((ret
!= 0) && ((ret
= wchar_to_utf8_no_alloc(wlpBuffer
, lpBuffer
, nSize
)) == 0)) {
491 err
= GetLastError();
500 // Convert a windows error to human readable string
501 const char *WindowsErrorString(DWORD error_code
)
503 static char err_string
[256] = { 0 };
508 // Check for VDS error codes
509 if ((HRESULT_FACILITY(error_code
) == FACILITY_ITF
) && (GetVdsError(error_code
) != NULL
)) {
510 sprintf_s(err_string
, sizeof(err_string
), "[0x%08lX] %s", error_code
, GetVdsError(error_code
));
513 if ((HRESULT_FACILITY(error_code
) == 322) && (GetVimError(error_code
) != NULL
)) {
514 sprintf_s(err_string
, sizeof(err_string
), "[0x%08lX] %s", error_code
, GetVimError(error_code
));
517 sprintf_s(err_string
, sizeof(err_string
), "[0x%08lX] ", error_code
);
518 presize
= (DWORD
)strlen(err_string
);
520 size
= FormatMessageU(FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
, NULL
,
521 HRESULT_CODE(error_code
), MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
),
522 &err_string
[presize
], sizeof(err_string
)-(DWORD
)strlen(err_string
), NULL
);
524 format_error
= GetLastError();
525 if ((format_error
) && (format_error
!= ERROR_MR_MID_NOT_FOUND
) && (format_error
!= ERROR_MUI_FILE_NOT_LOADED
))
526 sprintf_s(err_string
, sizeof(err_string
), "Windows error code 0x%08lX (FormatMessage error code 0x%08lX)",
527 error_code
, format_error
);
529 sprintf_s(err_string
, sizeof(err_string
), "Windows error code 0x%08lX", error_code
);
532 // Microsoft may suffix CRLF to error messages, which we need to remove...
534 // Cannot underflow if the above assert passed since our first char is neither of the following
535 while ((err_string
[size
] == 0x0D) || (err_string
[size
] == 0x0A) || (err_string
[size
] == 0x20))
536 err_string
[size
--] = 0;
544 #define INTF_ADVANCEDDISK 1
545 #define INTF_ADVANCEDDISK2 2
546 #define INTF_CREATEPARTITIONEX 3
547 #define INTF_PARTITIONMF 4
548 #define INTF_VOLUME 5
549 #define INTF_VOLUME_MF3 6
552 * Some code and functions in the file are copied from rufus.
553 * https://github.com/pbatard/rufus
555 #define VDS_SET_ERROR SetLastError
556 #define IVdsServiceLoader_LoadService(This, pwszMachineName, ppService) (This)->lpVtbl->LoadService(This, pwszMachineName, ppService)
557 #define IVdsServiceLoader_Release(This) (This)->lpVtbl->Release(This)
558 #define IVdsService_QueryProviders(This, masks, ppEnum) (This)->lpVtbl->QueryProviders(This, masks, ppEnum)
559 #define IVdsService_WaitForServiceReady(This) ((This)->lpVtbl->WaitForServiceReady(This))
560 #define IVdsService_CleanupObsoleteMountPoints(This) ((This)->lpVtbl->CleanupObsoleteMountPoints(This))
561 #define IVdsService_Refresh(This) ((This)->lpVtbl->Refresh(This))
562 #define IVdsService_Reenumerate(This) ((This)->lpVtbl->Reenumerate(This))
563 #define IVdsSwProvider_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
564 #define IVdsProvider_Release(This) (This)->lpVtbl->Release(This)
565 #define IVdsSwProvider_QueryPacks(This, ppEnum) (This)->lpVtbl->QueryPacks(This, ppEnum)
566 #define IVdsSwProvider_Release(This) (This)->lpVtbl->Release(This)
567 #define IVdsPack_QueryDisks(This, ppEnum) (This)->lpVtbl->QueryDisks(This, ppEnum)
568 #define IVdsDisk_GetProperties(This, pDiskProperties) (This)->lpVtbl->GetProperties(This, pDiskProperties)
569 #define IVdsDisk_Release(This) (This)->lpVtbl->Release(This)
570 #define IVdsDisk_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
571 #define IVdsAdvancedDisk_QueryPartitions(This, ppPartitionPropArray, plNumberOfPartitions) (This)->lpVtbl->QueryPartitions(This, ppPartitionPropArray, plNumberOfPartitions)
572 #define IVdsAdvancedDisk_DeletePartition(This, ullOffset, bForce, bForceProtected) (This)->lpVtbl->DeletePartition(This, ullOffset, bForce, bForceProtected)
573 #define IVdsAdvancedDisk_ChangeAttributes(This, ullOffset, para) (This)->lpVtbl->ChangeAttributes(This, ullOffset, para)
574 #define IVdsAdvancedDisk_CreatePartition(This, ullOffset, ullSize, para, ppAsync) (This)->lpVtbl->CreatePartition(This, ullOffset, ullSize, para, ppAsync)
575 #define IVdsAdvancedDisk_Clean(This, bForce, bForceOEM, bFullClean, ppAsync) (This)->lpVtbl->Clean(This, bForce, bForceOEM, bFullClean, ppAsync)
576 #define IVdsAdvancedDisk_Release(This) (This)->lpVtbl->Release(This)
578 #define IVdsAdvancedDisk2_ChangePartitionType(This, ullOffset, bForce, para) (This)->lpVtbl->ChangePartitionType(This, ullOffset, bForce, para)
579 #define IVdsAdvancedDisk2_Release(This) (This)->lpVtbl->Release(This)
581 #define IVdsCreatePartitionEx_CreatePartitionEx(This, ullOffset, ullSize, ulAlign, para, ppAsync) (This)->lpVtbl->CreatePartitionEx(This, ullOffset, ullSize, ulAlign, para, ppAsync)
582 #define IVdsCreatePartitionEx_Release(This) (This)->lpVtbl->Release(This)
584 #define IVdsPartitionMF_FormatPartitionEx(This, ullOffset, pwszFileSystemTypeName, usFileSystemRevision, ulDesiredUnitAllocationSize, pwszLabel, bForce, bQuickFormat, bEnableCompression, ppAsync) \
585 (This)->lpVtbl->FormatPartitionEx(This, ullOffset, pwszFileSystemTypeName, usFileSystemRevision, ulDesiredUnitAllocationSize, pwszLabel, bForce, bQuickFormat, bEnableCompression, ppAsync)
586 #define IVdsPartitionMF_Release(This) (This)->lpVtbl->Release(This)
588 #define IEnumVdsObject_Next(This, celt, ppObjectArray, pcFetched) (This)->lpVtbl->Next(This, celt, ppObjectArray, pcFetched)
589 #define IVdsPack_QueryVolumes(This, ppEnum) (This)->lpVtbl->QueryVolumes(This, ppEnum)
590 #define IVdsVolume_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)
591 #define IVdsVolume_Release(This) (This)->lpVtbl->Release(This)
592 #define IVdsVolumeMF3_QueryVolumeGuidPathnames(This, pwszPathArray, pulNumberOfPaths) (This)->lpVtbl->QueryVolumeGuidPathnames(This,pwszPathArray,pulNumberOfPaths)
593 #define IVdsVolumeMF3_FormatEx2(This, pwszFileSystemTypeName, usFileSystemRevision, ulDesiredUnitAllocationSize, pwszLabel, Options, ppAsync) (This)->lpVtbl->FormatEx2(This, pwszFileSystemTypeName, usFileSystemRevision, ulDesiredUnitAllocationSize, pwszLabel, Options, ppAsync)
594 #define IVdsVolumeMF3_Release(This) (This)->lpVtbl->Release(This)
595 #define IVdsVolume_GetProperties(This, pVolumeProperties) (This)->lpVtbl->GetProperties(This,pVolumeProperties)
596 #define IVdsAsync_Cancel(This) (This)->lpVtbl->Cancel(This)
597 #define IVdsAsync_QueryStatus(This,pHrResult,pulPercentCompleted) (This)->lpVtbl->QueryStatus(This,pHrResult,pulPercentCompleted)
598 #define IVdsAsync_Wait(This,pHrResult,pAsyncOut) (This)->lpVtbl->Wait(This,pHrResult,pAsyncOut)
599 #define IVdsAsync_Release(This) (This)->lpVtbl->Release(This)
601 #define IVdsVolume_Shrink(This, ullNumberOfBytesToRemove, ppAsync) (This)->lpVtbl->Shrink(This, ullNumberOfBytesToRemove, ppAsync)
603 #define IUnknown_QueryInterface(This, a, b) (This)->lpVtbl->QueryInterface(This,a,b)
604 #define IUnknown_Release(This) (This)->lpVtbl->Release(This)
606 typedef BOOL(*VDS_Callback_PF
)(void *pInterface
, VDS_DISK_PROP
*pDiskProp
, UINT64 data
);
608 static BOOL g_vds_available
= TRUE
;
610 BOOL
VDS_IsLastAvaliable(void)
612 return g_vds_available
;
615 STATIC IVdsService
* VDS_InitService(void)
618 IVdsServiceLoader
*pLoader
;
619 IVdsService
*pService
;
622 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
623 CoInitializeSecurity(NULL
, -1, NULL
, NULL
, RPC_C_AUTHN_LEVEL_CONNECT
, RPC_C_IMP_LEVEL_IMPERSONATE
, NULL
, 0, NULL
);
625 // Create a VDS Loader Instance
626 hr
= CoCreateInstance(&CLSID_VdsLoader
, NULL
, CLSCTX_LOCAL_SERVER
| CLSCTX_REMOTE_SERVER
, &IID_IVdsServiceLoader
, (void **)&pLoader
);
630 Log("Could not create VDS Loader Instance: 0x%x", LASTERR
);
634 // Load the VDS Service
635 hr
= IVdsServiceLoader_LoadService(pLoader
, L
"", &pService
);
636 IVdsServiceLoader_Release(pLoader
);
640 Log("Could not load VDS Service: 0x%x", LASTERR
);
641 g_vds_available
= FALSE
;
645 // Wait for the Service to become ready if needed
646 hr
= IVdsService_WaitForServiceReady(pService
);
650 Log("VDS Service is not ready: 0x%x", LASTERR
);
654 Log("VDS init OK, service %p", pService
);
655 g_vds_available
= TRUE
;
659 STATIC BOOL
VDS_VolumeCommProc(int intf
, const WCHAR
* wVolumeGuid
, VDS_Callback_PF callback
, UINT64 data
)
666 IUnknown
* pUnk
= NULL
;
667 IEnumVdsObject
* pEnum
= NULL
;
668 IVdsService
* pService
= NULL
;
670 pService
= VDS_InitService();
673 Log("Could not query VDS Service");
677 // Query the VDS Service Providers
678 hr
= IVdsService_QueryProviders(pService
, VDS_QUERY_SOFTWARE_PROVIDERS
, &pEnum
);
682 Log("Could not query VDS Service Providers: 0x%lx %u", hr
, LASTERR
);
686 while (IEnumVdsObject_Next(pEnum
, 1, &pUnk
, &ulFetched
) == S_OK
)
688 IVdsProvider
* pProvider
;
689 IVdsSwProvider
* pSwProvider
;
690 IEnumVdsObject
* pEnumPack
;
694 hr
= IUnknown_QueryInterface(pUnk
, &IID_IVdsProvider
, (void**)&pProvider
);
695 IUnknown_Release(pUnk
);
699 Log("Could not get VDS Provider: %u", LASTERR
);
703 // Get VDS Software Provider
704 hr
= IVdsSwProvider_QueryInterface(pProvider
, &IID_IVdsSwProvider
, (void**)&pSwProvider
);
705 IVdsProvider_Release(pProvider
);
709 Log("Could not get VDS Software Provider: %u", LASTERR
);
713 // Get VDS Software Provider Packs
714 hr
= IVdsSwProvider_QueryPacks(pSwProvider
, &pEnumPack
);
715 IVdsSwProvider_Release(pSwProvider
);
719 Log("Could not get VDS Software Provider Packs: %u", LASTERR
);
723 // Enumerate Provider Packs
724 while (IEnumVdsObject_Next(pEnumPack
, 1, &pPackUnk
, &ulFetched
) == S_OK
)
727 IEnumVdsObject
* pEnumVolume
;
728 IUnknown
* pVolumeUnk
;
730 hr
= IUnknown_QueryInterface(pPackUnk
, &IID_IVdsPack
, (void**)&pPack
);
731 IUnknown_Release(pPackUnk
);
735 Log("Could not query VDS Software Provider Pack: %u", LASTERR
);
739 // Use the pack interface to access the volume
740 hr
= IVdsPack_QueryVolumes(pPack
, &pEnumVolume
);;
743 Log("Could not query VDS volume: %u", LASTERR
);
748 while (IEnumVdsObject_Next(pEnumVolume
, 1, &pVolumeUnk
, &ulFetched
) == S_OK
)
751 IVdsVolumeMF3
* pVolumeMF3
;
752 LPWSTR
* wszPathArray
;
753 ULONG ulNumberOfPaths
;
755 // Get the disk interface.
756 hr
= IUnknown_QueryInterface(pVolumeUnk
, &IID_IVdsVolumeMF3
, (void**)&pVolumeMF3
);
759 Log("Could not query VDS Volume Interface: %u", LASTERR
);
763 // Get the volume properties
764 hr
= IVdsVolumeMF3_QueryVolumeGuidPathnames(pVolumeMF3
, &wszPathArray
, &ulNumberOfPaths
);
765 if ((hr
!= S_OK
) && (hr
!= VDS_S_PROPERTIES_INCOMPLETE
))
767 Log("Could not query VDS VolumeMF3 GUID PathNames: %s", GetVdsError(hr
));
768 IVdsVolume_Release(pVolumeMF3
);
769 IUnknown_Release(pVolumeUnk
);
773 Log("Get Volume %d %lu <%S>", intf
, ulNumberOfPaths
, wszPathArray
[0]);
775 if ((ulNumberOfPaths
>= 1) && wcsstr(wszPathArray
[0], wVolumeGuid
))
778 Log("Call back for this Volume %d <%S>", intf
, wVolumeGuid
);
780 if (INTF_VOLUME_MF3
== intf
)
782 r
= callback(pVolumeMF3
, NULL
, data
);
784 else if (INTF_VOLUME
== intf
)
786 // Get the disk interface.
787 hr
= IUnknown_QueryInterface(pVolumeUnk
, &IID_IVdsVolume
, (void**)&pVolume
);
790 Log("Could not query VDS Volume Interface: %u", LASTERR
);
793 r
= callback(pVolume
, NULL
, data
);
794 IVdsVolume_Release(pVolume
);
799 CoTaskMemFree(wszPathArray
);
800 IVdsVolume_Release(pVolumeMF3
);
801 IUnknown_Release(pVolumeUnk
);
816 STATIC BOOL
VDS_DiskCommProc(int intf
, int DriveIndex
, VDS_Callback_PF callback
, UINT64 data
)
821 IUnknown
*pUnk
= NULL
;
822 IEnumVdsObject
*pEnum
= NULL
;
823 IVdsService
*pService
= NULL
;
824 wchar_t wPhysicalName
[48];
826 swprintf_s(wPhysicalName
, ARRAYSIZE(wPhysicalName
), L
"\\\\?\\PhysicalDrive%d", DriveIndex
);
828 pService
= VDS_InitService();
831 Log("Could not query VDS Service");
835 // Query the VDS Service Providers
836 hr
= IVdsService_QueryProviders(pService
, VDS_QUERY_SOFTWARE_PROVIDERS
, &pEnum
);
840 Log("Could not query VDS Service Providers: 0x%lx %u", hr
, LASTERR
);
844 while (IEnumVdsObject_Next(pEnum
, 1, &pUnk
, &ulFetched
) == S_OK
)
846 IVdsProvider
*pProvider
;
847 IVdsSwProvider
*pSwProvider
;
848 IEnumVdsObject
*pEnumPack
;
852 hr
= IUnknown_QueryInterface(pUnk
, &IID_IVdsProvider
, (void **)&pProvider
);
853 IUnknown_Release(pUnk
);
857 Log("Could not get VDS Provider: %u", LASTERR
);
861 // Get VDS Software Provider
862 hr
= IVdsSwProvider_QueryInterface(pProvider
, &IID_IVdsSwProvider
, (void **)&pSwProvider
);
863 IVdsProvider_Release(pProvider
);
867 Log("Could not get VDS Software Provider: %u", LASTERR
);
871 // Get VDS Software Provider Packs
872 hr
= IVdsSwProvider_QueryPacks(pSwProvider
, &pEnumPack
);
873 IVdsSwProvider_Release(pSwProvider
);
877 Log("Could not get VDS Software Provider Packs: %u", LASTERR
);
881 // Enumerate Provider Packs
882 while (IEnumVdsObject_Next(pEnumPack
, 1, &pPackUnk
, &ulFetched
) == S_OK
)
885 IEnumVdsObject
*pEnumDisk
;
888 hr
= IUnknown_QueryInterface(pPackUnk
, &IID_IVdsPack
, (void **)&pPack
);
889 IUnknown_Release(pPackUnk
);
893 Log("Could not query VDS Software Provider Pack: %u", LASTERR
);
897 // Use the pack interface to access the disks
898 hr
= IVdsPack_QueryDisks(pPack
, &pEnumDisk
);
901 Log("Could not query VDS disks: %u", LASTERR
);
906 while (IEnumVdsObject_Next(pEnumDisk
, 1, &pDiskUnk
, &ulFetched
) == S_OK
)
908 VDS_DISK_PROP diskprop
;
910 IVdsAdvancedDisk
*pAdvancedDisk
;
911 IVdsAdvancedDisk2
*pAdvancedDisk2
;
912 IVdsCreatePartitionEx
*pCreatePartitionEx
;
913 IVdsDiskPartitionMF
*pPartitionMP
;
915 // Get the disk interface.
916 hr
= IUnknown_QueryInterface(pDiskUnk
, &IID_IVdsDisk
, (void **)&pDisk
);
919 Log("Could not query VDS Disk Interface: %u", LASTERR
);
923 // Get the disk properties
924 hr
= IVdsDisk_GetProperties(pDisk
, &diskprop
);
927 Log("Could not query VDS Disk Properties: %u", LASTERR
);
931 // Isolate the disk we want
932 if (_wcsicmp(wPhysicalName
, diskprop
.pwszName
) != 0)
934 IVdsDisk_Release(pDisk
);
938 if (intf
== INTF_ADVANCEDDISK
)
940 // Instantiate the AdvanceDisk interface for our disk.
941 hr
= IVdsDisk_QueryInterface(pDisk
, &IID_IVdsAdvancedDisk
, (void **)&pAdvancedDisk
);
942 IVdsDisk_Release(pDisk
);
946 Log("Could not access VDS Advanced Disk interface: %u", LASTERR
);
951 Log("Callback %d process for disk <%S>", intf
, diskprop
.pwszName
);
952 r
= callback(pAdvancedDisk
, &diskprop
, data
);
954 IVdsAdvancedDisk_Release(pAdvancedDisk
);
956 else if (intf
== INTF_ADVANCEDDISK2
)
958 // Instantiate the AdvanceDisk interface for our disk.
959 hr
= IVdsDisk_QueryInterface(pDisk
, &IID_IVdsAdvancedDisk2
, (void **)&pAdvancedDisk2
);
960 IVdsDisk_Release(pDisk
);
964 Log("Could not access VDS Advanced Disk2 interface: %u", LASTERR
);
969 Log("Callback %d process for disk2 <%S>", intf
, diskprop
.pwszName
);
970 r
= callback(pAdvancedDisk2
, &diskprop
, data
);
972 IVdsAdvancedDisk2_Release(pAdvancedDisk2
);
974 else if (intf
== INTF_CREATEPARTITIONEX
)
976 // Instantiate the CreatePartitionEx interface for our disk.
977 hr
= IVdsDisk_QueryInterface(pDisk
, &IID_IVdsCreatePartitionEx
, (void **)&pCreatePartitionEx
);
978 IVdsDisk_Release(pDisk
);
982 Log("Could not access VDS CreatePartitionEx interface: %u", LASTERR
);
987 Log("Callback %d process for disk <%S>", intf
, diskprop
.pwszName
);
988 r
= callback(pCreatePartitionEx
, &diskprop
, data
);
990 IVdsCreatePartitionEx_Release(pCreatePartitionEx
);
992 else if (intf
== INTF_PARTITIONMF
)
994 // Instantiate the DiskPartitionMF interface for our disk.
995 hr
= IVdsDisk_QueryInterface(pDisk
, &IID_IVdsDiskPartitionMF
, (void **)&pPartitionMP
);
996 IVdsDisk_Release(pDisk
);
1000 Log("Could not access VDS PartitionMF interface: %u", LASTERR
);
1005 Log("Callback %d process for disk <%S>", intf
, diskprop
.pwszName
);
1006 r
= callback(pPartitionMP
, &diskprop
, data
);
1008 IVdsPartitionMF_Release(pPartitionMP
);
1020 STATIC BOOL
VDS_CallBack_CleanDisk(void *pInterface
, VDS_DISK_PROP
*pDiskProp
, UINT64 data
)
1025 IVdsAdvancedDisk
*pAdvancedDisk
= (IVdsAdvancedDisk
*)pInterface
;
1030 hr
= IVdsAdvancedDisk_Clean(pAdvancedDisk
, TRUE
, TRUE
, FALSE
, &pAsync
);
1031 while (SUCCEEDED(hr
))
1033 hr
= IVdsAsync_QueryStatus(pAsync
, &hr2
, &completed
);
1039 Log("Disk clean QueryStatus OK");
1042 else if (hr
== VDS_E_OPERATION_PENDING
)
1048 Log("QueryStatus invalid status:%u", hr
);
1057 Log("Could not clean disk 0x%lx err:%u", hr
, LASTERR
);
1064 BOOL
VDS_CleanDisk(int DriveIndex
)
1066 BOOL ret
= VDS_DiskCommProc(INTF_ADVANCEDDISK
, DriveIndex
, VDS_CallBack_CleanDisk
, 0);
1067 Log("VDS_CleanDisk %d ret:%d (%s)", DriveIndex
, ret
, ret
? "SUCCESS" : "FAIL");
1071 STATIC BOOL
VDS_CallBack_DeletePartition(void *pInterface
, VDS_DISK_PROP
*pDiskProp
, UINT64 data
)
1075 VDS_PARTITION_PROP
* prop_array
= NULL
;
1076 LONG i
, prop_array_size
;
1077 UINT64 PartOffset
= data
;
1078 IVdsAdvancedDisk
*pAdvancedDisk
= (IVdsAdvancedDisk
*)pInterface
;
1080 if (PartOffset
== 0)
1082 Log("Deleting ALL partitions from disk '%S':", pDiskProp
->pwszName
);
1086 Log("Deleting partition(offset=%llu) from disk '%S':", PartOffset
, pDiskProp
->pwszName
);
1089 // Query the partition data, so we can get the start offset, which we need for deletion
1090 hr
= IVdsAdvancedDisk_QueryPartitions(pAdvancedDisk
, &prop_array
, &prop_array_size
);
1094 for (i
= 0; i
< prop_array_size
; i
++)
1096 if (PartOffset
== 0 || PartOffset
== prop_array
[i
].ullOffset
)
1098 Log("* Partition %d (offset: %lld, size: %llu) delete it.",
1099 prop_array
[i
].ulPartitionNumber
, prop_array
[i
].ullOffset
, (ULONGLONG
)prop_array
[i
].ullSize
);
1103 Log(" Partition %d (offset: %lld, size: %llu) skip it.",
1104 prop_array
[i
].ulPartitionNumber
, prop_array
[i
].ullOffset
, (ULONGLONG
)prop_array
[i
].ullSize
);
1108 hr
= IVdsAdvancedDisk_DeletePartition(pAdvancedDisk
, prop_array
[i
].ullOffset
, TRUE
, TRUE
);
1113 Log("Could not delete partitions: 0x%x", LASTERR
);
1118 Log("Delete this partitions success");
1124 Log("No partition to delete on disk '%S'", pDiskProp
->pwszName
);
1130 CoTaskMemFree(prop_array
);
1136 BOOL
VDS_DeleteAllPartitions(int DriveIndex
)
1138 BOOL ret
= VDS_DiskCommProc(INTF_ADVANCEDDISK
, DriveIndex
, VDS_CallBack_DeletePartition
, 0);
1139 Log("VDS_DeleteAllPartitions %d ret:%d (%s)", DriveIndex
, ret
, ret
? "SUCCESS" : "FAIL");
1143 BOOL
VDS_DeleteVtoyEFIPartition(int DriveIndex
, UINT64 EfiPartOffset
)
1145 BOOL ret
= VDS_DiskCommProc(INTF_ADVANCEDDISK
, DriveIndex
, VDS_CallBack_DeletePartition
, EfiPartOffset
);
1146 Log("VDS_DeleteVtoyEFIPartition %d ret:%d (%s)", DriveIndex
, ret
, ret
? "SUCCESS" : "FAIL");
1150 STATIC BOOL
VDS_CallBack_ChangeEFIAttr(void *pInterface
, VDS_DISK_PROP
*pDiskProp
, UINT64 data
)
1154 VDS_PARA
*VdsPara
= (VDS_PARA
*)data
;
1155 VDS_PARTITION_PROP
* prop_array
= NULL
;
1156 LONG i
, prop_array_size
;
1157 CHANGE_ATTRIBUTES_PARAMETERS AttrPara
;
1158 IVdsAdvancedDisk
*pAdvancedDisk
= (IVdsAdvancedDisk
*)pInterface
;
1160 // Query the partition data, so we can get the start offset, which we need for deletion
1161 hr
= IVdsAdvancedDisk_QueryPartitions(pAdvancedDisk
, &prop_array
, &prop_array_size
);
1164 for (i
= 0; i
< prop_array_size
; i
++)
1166 if (prop_array
[i
].ullSize
== VENTOY_EFI_PART_SIZE
&&
1167 prop_array
[i
].PartitionStyle
== VDS_PST_GPT
&&
1168 memcmp(prop_array
[i
].Gpt
.name
, L
"VTOYEFI", 7 * 2) == 0 &&
1169 VdsPara
->Offset
== prop_array
[i
].ullOffset
)
1171 Log("** Partition %d (offset: %lld, size: %llu, Attr:0x%llx)", prop_array
[i
].ulPartitionNumber
,
1172 prop_array
[i
].ullOffset
, (ULONGLONG
)prop_array
[i
].ullSize
, prop_array
[i
].Gpt
.attributes
);
1174 if (prop_array
[i
].Gpt
.attributes
== VdsPara
->Attr
)
1176 Log("Attribute match, No need to change.");
1181 AttrPara
.style
= VDS_PST_GPT
;
1182 AttrPara
.GptPartInfo
.attributes
= VdsPara
->Attr
;
1183 hr
= IVdsAdvancedDisk_ChangeAttributes(pAdvancedDisk
, prop_array
[i
].ullOffset
, &AttrPara
);
1187 Log("Change this partitions attribute success");
1193 Log("Could not change partitions attr: %u", LASTERR
);
1202 Log("No partition found on disk '%S'", pDiskProp
->pwszName
);
1204 CoTaskMemFree(prop_array
);
1209 BOOL
VDS_ChangeVtoyEFIAttr(int DriveIndex
, UINT64 Offset
, UINT64 Attr
)
1214 Para
.Offset
= Offset
;
1216 BOOL ret
= VDS_DiskCommProc(INTF_ADVANCEDDISK
, DriveIndex
, VDS_CallBack_ChangeEFIAttr
, (UINT64
)&Para
);
1217 Log("VDS_ChangeVtoyEFIAttr %d (offset:%llu) ret:%d (%s)", DriveIndex
, Offset
, ret
, ret
? "SUCCESS" : "FAIL");
1223 STATIC BOOL
VDS_CallBack_ChangeEFIType(void *pInterface
, VDS_DISK_PROP
*pDiskProp
, UINT64 data
)
1227 IVdsAdvancedDisk2
*pAdvancedDisk2
= (IVdsAdvancedDisk2
*)pInterface
;
1228 VDS_PARA
*VdsPara
= (VDS_PARA
*)data
;
1229 CHANGE_PARTITION_TYPE_PARAMETERS para
;
1231 para
.style
= VDS_PST_GPT
;
1232 memcpy(&(para
.GptPartInfo
.partitionType
), &VdsPara
->Type
, sizeof(GUID
));
1234 hr
= IVdsAdvancedDisk2_ChangePartitionType(pAdvancedDisk2
, VdsPara
->Offset
, TRUE
, ¶
);
1241 Log("Failed to change partition type 0x%lx(%s)", hr
, WindowsErrorString(hr
));
1248 BOOL
VDS_ChangeVtoyEFI2ESP(int DriveIndex
, UINT64 Offset
)
1251 GUID EspPartType
= { 0xc12a7328, 0xf81f, 0x11d2, { 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } };
1253 memcpy(&(Para
.Type
), &EspPartType
, sizeof(GUID
));
1254 Para
.Offset
= Offset
;
1256 BOOL ret
= VDS_DiskCommProc(INTF_ADVANCEDDISK2
, DriveIndex
, VDS_CallBack_ChangeEFIType
, (UINT64
)&Para
);
1257 Log("VDS_ChangeVtoyEFI2ESP %d ret:%d (%s)", DriveIndex
, ret
, ret
? "SUCCESS" : "FAIL");
1262 BOOL
VDS_ChangeVtoyEFI2Basic(int DriveIndex
, UINT64 Offset
)
1265 GUID WindowsDataPartType
= { 0xebd0a0a2, 0xb9e5, 0x4433, { 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7 } };
1267 memcpy(&(Para
.Type
), &WindowsDataPartType
, sizeof(GUID
));
1268 Para
.Offset
= Offset
;
1270 BOOL ret
= VDS_DiskCommProc(INTF_ADVANCEDDISK2
, DriveIndex
, VDS_CallBack_ChangeEFIType
, (UINT64
)&Para
);
1271 Log("VDS_ChangeVtoyEFI2Basic %d ret:%d (%s)", DriveIndex
, ret
, ret
? "SUCCESS" : "FAIL");
1275 STATIC BOOL
CHKDSK_Volume(CHAR LogicalDrive
)
1279 PROCESS_INFORMATION Pi
;
1281 if ((!IsFileExist("C:\\Windows\\System32\\chkdsk.exe")) || (LogicalDrive
== 0))
1286 GetStartupInfoA(&Si
);
1287 Si
.dwFlags
|= STARTF_USESHOWWINDOW
;
1288 Si
.wShowWindow
= SW_HIDE
;
1290 sprintf_s(CmdBuf
, sizeof(CmdBuf
), "C:\\Windows\\System32\\chkdsk.exe %C: /f", LogicalDrive
);
1292 Log("CreateProcess <%s>", CmdBuf
);
1293 CreateProcessA(NULL
, CmdBuf
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &Si
, &Pi
);
1295 Log("Wair process ...");
1296 WaitForSingleObject(Pi
.hProcess
, INFINITE
);
1297 Log("Process finished...");
1299 CHECK_CLOSE_HANDLE(Pi
.hProcess
);
1300 CHECK_CLOSE_HANDLE(Pi
.hThread
);
1305 STATIC HRESULT
VDS_RealShrinkVolume(void* pInterface
, VDS_DISK_PROP
* pDiskProp
, UINT64 data
)
1308 IVdsVolume
* pVolume
= (IVdsVolume
*)pInterface
;
1311 VDS_PARA
* VdsPara
= (VDS_PARA
*)data
;
1315 Log("VDS_ShrinkVolume (%C:) (%llu) ...", VdsPara
->DriveLetter
, (ULONGLONG
)VdsPara
->Offset
);
1317 hr
= IVdsVolume_Shrink(pVolume
, (ULONGLONG
)VdsPara
->Offset
, &pAsync
);
1319 while (SUCCEEDED(hr
))
1321 hr
= IVdsAsync_QueryStatus(pAsync
, &hr2
, &completed
);
1327 Log("ShrinkVolume QueryStatus OK, %lu%%", completed
);
1330 else if (hr
== VDS_E_OPERATION_PENDING
)
1332 Log("ShrinkVolume: %lu%%", completed
);
1337 Log("ShrinkVolume invalid status:0x%lx", hr
);
1346 STATIC BOOL
VDS_CallBack_ShrinkVolume(void* pInterface
, VDS_DISK_PROP
* pDiskProp
, UINT64 data
)
1350 VDS_PARA
*VdsPara
= (VDS_PARA
*)data
;
1352 Log("VDS_CallBack_ShrinkVolume (%C:) (%llu) ...", VdsPara
->DriveLetter
, (ULONGLONG
)VdsPara
->Offset
);
1354 hr
= VDS_RealShrinkVolume(pInterface
, pDiskProp
, data
);
1355 if (hr
== VDS_E_SHRINK_DIRTY_VOLUME
)
1357 Log("Volume %C: is dirty, run chkdsk and retry.", VdsPara
->DriveLetter
);
1358 CHKDSK_Volume(VdsPara
->DriveLetter
);
1360 hr
= VDS_RealShrinkVolume(pInterface
, pDiskProp
, data
);
1361 if (hr
== VDS_E_SHRINK_DIRTY_VOLUME
)
1363 Log("################################################################");
1364 Log("################################################################");
1365 for (i
= 0; i
< 20; i
++)
1367 Log("###### Volume dirty, Please run \"chkdsk /f %C:\" and retry. ######", VdsPara
->Name
[0]);
1369 Log("################################################################");
1370 Log("################################################################");
1377 Log("Could not ShrinkVolume, 0x%x err:0x%lx (%s)", hr
, LASTERR
, WindowsErrorString(hr
));
1386 BOOL
VDS_ShrinkVolume(int DriveIndex
, const char* VolumeGuid
, CHAR DriveLetter
, UINT64 OldBytes
, UINT64 ReduceBytes
)
1390 WCHAR wGuid
[128] = { 0 };
1391 const char *guid
= NULL
;
1397 guid
= strstr(VolumeGuid
, "{");
1403 for (i
= 0; i
< 128 && guid
[i
]; i
++)
1408 Para
.Offset
= ReduceBytes
;
1409 Para
.DriveLetter
= DriveLetter
;
1411 ret
= VDS_VolumeCommProc(INTF_VOLUME
, wGuid
, VDS_CallBack_ShrinkVolume
, (UINT64
)&Para
);
1412 Log("VDS_ShrinkVolume %C: ret:%d (%s)", DriveLetter
, ret
, ret
? "SUCCESS" : "FAIL");