Actually VOLUME_DISK_EXTENTS
is defined to store 1 item.
typedef struct _VOLUME_DISK_EXTENTS {
DWORD NumberOfDiskExtents;
DISK_EXTENT Extents[ANYSIZE_ARRAY]; // ANYSIZE_ARRAY == 1
} VOLUME_DISK_EXTENTS, *PVOLUME_DISK_EXTENTS;
If we call DeviceIoControl
in the following way
VOLUME_DISK_EXTENTS vde;
ret = DeviceIoControl(
h, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
NULL, 0, &vde, sizeof(vde), &bytesReturned, NULL
);
we'll get ERROR_MORE_DATA
return code, because there's not enough space in that structure. Extents
array is defined of size 1 with the fact that if you'll try to access elements 1 and above, you'll get into the space in the buffer after the VOLUME_DISK_EXTENTS
structure. So what we actually need is to create not a VOLUME_DISK_EXTENTS
but a buffer of size
sizeof(DISK_EXTENT) * (nextents - 1) + sizeof(VOLUME_DISK_EXTENTS)
where nextents
is VOLUME_DISK_EXTENTS::NumberOfDiskExtents
value that we get from the previous call. Then we should use
VOLUME_DISK_EXTENTS *ext = (VOLUME_DISK_EXTENTS*) buff;
and work with this structure, assuming that Extents
array has nextents
elements.
There's no need for extra API calls to free the memory. Everything that is freed is a buffer.