은 디스크 레이아웃과 파티션 (디스크 크기, 디스크 시작 오프셋, 스타일 (gpt 또는 mbr))에 대한 정보를 유지하는 디스크 드라이버와이 파티션을 마운트하는 파일 시스템간에 다른 점을 이해해야합니다.
IOCTL_DISK_GROW_PARTITION
-이 ioctl은 디스크 드라이버와 확장 파티션에 의해 처리되지만이 ioctl을 처리하지 않고 파일 시스템에 영향을 줄 수는 없으며 파티션이 확장되었습니다. 그래서 ioctl을 추가적으로 사용해야한다. FSCTL_EXTEND_VOLUME
-이 ioctl은 이미 파일 시스템에 보내고 처리한다.
우리는 다음 단계
- 는
- 실제 얻을 수에 대한 출력으로
PARTITION_INFORMATION_EX
와 IOCTL_DISK_GET_PARTITION_INFO_EX
을 보내 출력 버퍼로 DISK_GEOMETRY
와 IOCTL_DISK_UPDATE_DRIVE_SIZE
을 보내 입력 버퍼로 DISK_GROW_PARTITION
와 IOCTL_DISK_GROW_PARTITION
를 전송을 할 필요가 그렇다면 이제 파티션의 크기.
는
LONGLONG SectorsPerPartition = PartitionEntry->PartitionLength.QuadPart/dg.BytesPerSector;
(우리가 3 단계에서 2 단계 및 PartitionEntry에있어 DG)
이
마지막으로 사용하는 분야에서, 볼륨의 새 크기를 계산 FSCTL_EXTEND_VOLUME
전체 코드 c 다음과 같음
int __cdecl SortPartitions(PPARTITION_INFORMATION_EX PartitionEntry1, PPARTITION_INFORMATION_EX PartitionEntry2)
{
if (!PartitionEntry1->PartitionNumber) return PartitionEntry2->PartitionNumber ? -1 : 0;
if (!PartitionEntry2->PartitionNumber) return +1;
if (PartitionEntry1->StartingOffset.QuadPart < PartitionEntry2->StartingOffset.QuadPart) return -1;
if (PartitionEntry1->StartingOffset.QuadPart > PartitionEntry2->StartingOffset.QuadPart) return +1;
return 0;
}
DWORD ExtendTest(HANDLE hDisk)
{
STORAGE_DEVICE_NUMBER sdn;
ULONG dwBytesRet;
if (!DeviceIoControl(hDisk, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesRet, NULL))
{
return GetLastError();
}
if (sdn.DeviceType != FILE_DEVICE_DISK || sdn.PartitionNumber != 0)
{
return ERROR_GEN_FAILURE;
}
GET_LENGTH_INFORMATION gli;
if (!DeviceIoControl(hDisk, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &gli, sizeof(gli), &dwBytesRet, NULL))
{
return GetLastError();
}
DbgPrint("Disk Length %I64x (%I64u)\n", gli.Length.QuadPart, gli.Length.QuadPart);
PVOID stack = alloca(guz);
union {
PVOID buf;
PDRIVE_LAYOUT_INFORMATION_EX pdli;
};
ULONG cb = 0, rcb, PartitionCount = 4;
for (;;)
{
if (cb < (rcb = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[PartitionCount])))
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
if (DeviceIoControl(hDisk, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL, 0, buf, cb, &dwBytesRet, NULL))
{
if (PartitionCount = pdli->PartitionCount)
{
PPARTITION_INFORMATION_EX PartitionEntry = pdli->PartitionEntry;
qsort(PartitionEntry, PartitionCount, sizeof(PARTITION_INFORMATION_EX),
(int (__cdecl *)(const void *, const void *))SortPartitions);
do
{
if (!PartitionEntry->PartitionNumber)
{
continue;
}
LARGE_INTEGER EndOffset;
LARGE_INTEGER MaximumOffset = PartitionCount != 1 ? (PartitionEntry + 1)->StartingOffset : gli.Length;
EndOffset.QuadPart = PartitionEntry->StartingOffset.QuadPart + PartitionEntry->PartitionLength.QuadPart;
if (EndOffset.QuadPart > MaximumOffset.QuadPart)
{
//??
__debugbreak();
}
else if (EndOffset.QuadPart < MaximumOffset.QuadPart)
{
DISK_GROW_PARTITION dgp;
dgp.PartitionNumber = PartitionEntry->PartitionNumber;
dgp.BytesToGrow.QuadPart = MaximumOffset.QuadPart - EndOffset.QuadPart;
WCHAR sz[128];
swprintf(sz, L"\\\\?\\GLOBALROOT\\Device\\Harddisk%d\\Partition%u", sdn.DeviceNumber, dgp.PartitionNumber);
HANDLE hPartition = CreateFile(sz, FILE_READ_ACCESS|FILE_WRITE_ACCESS, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);
if (hPartition != INVALID_HANDLE_VALUE)
{
// +++ begin extend
BOOL fOk = FALSE;
DISK_GEOMETRY dg;
if (DeviceIoControl(hPartition, IOCTL_DISK_GROW_PARTITION, &dgp, sizeof(dgp), 0, 0, &dwBytesRet, 0) &&
DeviceIoControl(hPartition, IOCTL_DISK_UPDATE_DRIVE_SIZE, 0, 0, &dg, sizeof(dg), &dwBytesRet, 0) &&
DeviceIoControl(hPartition, IOCTL_DISK_GET_PARTITION_INFO_EX, 0, 0, PartitionEntry, sizeof(*PartitionEntry), &dwBytesRet, 0)
)
{
LONGLONG SectorsPerPartition = PartitionEntry->PartitionLength.QuadPart/dg.BytesPerSector;
fOk = DeviceIoControl(hPartition, FSCTL_EXTEND_VOLUME, &SectorsPerPartition,
sizeof(SectorsPerPartition), 0, 0, &dwBytesRet, 0);
}
if (!fOk)
{
GetLastError();
}
//--- end extend
CloseHandle(hPartition);
}
}
// else EndOffset.QuadPart == MaximumOffset.QuadPart - partition can not be extended
} while (PartitionEntry++, --PartitionCount);
}
return NOERROR;
}
switch (ULONG err = GetLastError())
{
case ERROR_MORE_DATA:
PartitionCount = pdli->PartitionCount;
continue;
case ERROR_BAD_LENGTH:
case ERROR_INSUFFICIENT_BUFFER:
PartitionCount <<= 1;
continue;
default:
return err;
}
}
}
DWORD ExtendTest()
{
HANDLE hDisk = CreateFileW(L"\\\\?\\PhysicalDrive0", FILE_GENERIC_READ|FILE_GENERIC_WRITE,
FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);
if (hDisk != INVALID_HANDLE_VALUE)
{
DWORD err = ExtendTest(hDisk);
CloseHandle(hDisk);
return err;
}
return GetLastError();
}
'IOCTL_DISK_GROW_PARTITION'을 사용하면 디스크 드라이브보기에서 파티션 만 확장 할 수 있습니다. 하지만이 파티션을 마운트 한 파일 시스템도 확장해야합니다. 이 * * 후에 파티션을 확장하려면 [F2STL_EXTEND_VOLUME'] (https://msdn.microsoft.com/en-us/library/windows/desktop/aa364564(v=vs.85).aspx)을 사용해야한다고 생각합니다. – RbMm
* 새 볼륨 크기는 이전 볼륨 크기보다 적어도 하나 큰 클러스터 여야합니다. 기본 파티션에는 확장 볼륨을 포함 할 수있는 충분한 섹터가 있어야합니다. IOCTL_DISK_GROW_PARTITION은 기본 장치에 충분한 공간이있는 경우 사용할 수 있습니다. * - 따라서 IOCTL_DISK_GROW_PARTITION 뒤에 'FSCTL_EXTEND_VOLUME'을 시도하십시오. – RbMm
['IOCTL_DISK_UPDATE_DRIVE_SIZE'] (https://msdn.microsoft.com/en-us)를 사용해야합니다. /library/windows/hardware/ff560419(v=vs.85).aspx)'IOCTL_DISK_GROW_PARTITION'과'FSCTL_EXTEND_VOLUME' 사이 – RbMm