は、ディスクレイアウトとパーティションの情報(このサイズ、ディスクの先頭からのオフセット、スタイル(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
を送信を行う必要がありそうならば パーティションのサイズ。
ついにFSCTL_EXTEND_VOLUME
を使用
(DG我々はステップ3で、ステップ2とPartitionEntryで得た)部門
LONGLONG SectorsPerPartition = PartitionEntry->PartitionLength.QuadPart/dg.BytesPerSector;
で、
- のボリュームの新しいサイズを計算
フルコード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」では、ディスクドライブビューからパーティションのみを拡張します。このパーティションをマウントしたファイルシステムも拡張する必要があります。私はこれを* [* FSCTL_EXTEND_VOLUME'](https://msdn.microsoft.com/en-us/library/windows/desktop/aa364564(v=vs.85).aspx)にする必要があると思います。パーティションを拡張した後 – RbMm
*新しいボリュームサイズは、以前のボリュームサイズよりも少なくとも1つのクラスタ以上でなければなりません。基本パーティションには、拡張ボリュームを格納するのに十分なセクタが必要です。 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