我的要求是通过程序来扩大驱动器的音量。 当我在DeviceIO中使用IOCTL_DISK_GROW_PARTITION扩展它时,磁盘pipe理将显示新修改的大小,而此PC(我的电脑)中的驱动器大小保持不变。
BOOL DeviceIoControl( (HANDLE) hDevice, // handle to device IOCTL_DISK_GROW_PARTITION, // dwIoControlCode (LPVOID) lpInBuffer, // input buffer (DWORD) nInBufferSize, // size of the input buffer NULL, // lpOutBuffer 0, // nOutBufferSize (LPDWORD) lpBytesReturned, // number of bytes returned (LPOVERLAPPED) lpOverlapped // OVERLAPPED structure );
通过一些分析,我发现在使用这个API时,磁盘的MBR被修改,但是驱动器的簇位图没有改变。 我想知道使用此DeviceIO扩展卷或其他一些API来执行相同过程的正确方法。
需要了解不同的磁盘驱动程序,这些驱动程序维护有关磁盘布局和分区(磁盘大小,从磁盘开始的偏移量,样式(gpt或mbr))和挂载此分区的文件系统的信息。
IOCTL_DISK_GROW_PARTITION
– 这个ioctl由磁盘驱动器和扩展分区处理,但是这对文件系统不起作用,它不能处理这个ioctl,并且根本不知道这个分区是否被扩展。 所以你需要额外的ioctl使用FSCTL_EXTEND_VOLUME
– 这个ioctl已经发送和处理文件系统。
所以如果我们必须做下一步
DISK_GROW_PARTITION
发送IOCTL_DISK_GROW_PARTITION
作为输入缓冲区 DISK_GEOMETRY
作为输出缓冲区发送IOCTL_DISK_UPDATE_DRIVE_SIZE
IOCTL_DISK_GET_PARTITION_INFO_EX
用PARTITION_INFORMATION_EX
发送IOCTL_DISK_GET_PARTITION_INFO_EX
作为输出,以获取分区的实际大小。 在扇区中计算卷的新大小
LONGLONG SectorsPerPartition = PartitionEntry->PartitionLength.QuadPart / dg.BytesPerSector;
( dg我们在步骤2和PartitionEntry在步骤3)
最后使用FSCTL_EXTEND_VOLUME
完整的代码可以像下一个
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(); }