Pal*_*vel 5 c windows winapi ntfs
我的要求是通过程序扩展驱动器音量。当我在 DeviceIO 中使用 IOCTL_DISK_GROW_PARTITION 扩展它时,磁盘管理显示新修改的大小,而这台电脑(我的电脑)中的驱动器大小保持不变。
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
);
Run Code Online (Sandbox Code Playgroud)
通过一些分析,我发现在使用这个API时,磁盘的MBR被修改了,但驱动器的簇位图并没有改变。我想知道使用此 DeviceIO 扩展卷或其他一些 API 来执行相同过程的正确方法。
需要了解磁盘驱动程序和文件系统之间的区别,磁盘驱动程序维护有关磁盘布局和分区的信息(它的大小、距磁盘开始的偏移量、样式(gpt 或 mbr))和安装此分区的文件系统。
IOCTL_DISK_GROW_PARTITION
- 此 ioctl 由磁盘驱动程序和扩展分区处理,但这对文件系统不起作用,文件系统不处理此 ioctl 并且根本不知道分区已扩展。所以你需要额外的 ioctl 使用FSCTL_EXTEND_VOLUME
- 这个 ioctl 已经发送并处理到文件系统。
所以如果我们必须采取下一步行动
IOCTL_DISK_GROW_PARTITION
作为
DISK_GROW_PARTITION
输入缓冲区发送IOCTL_DISK_UPDATE_DRIVE_SIZE
作为DISK_GEOMETRY
输出缓冲区发送IOCTL_DISK_GET_PARTITION_INFO_EX
作为
PARTITION_INFORMATION_EX
输出以立即获取分区的实际大小。计算卷的新大小(以扇区为单位)
LONGLONG SectorsPerPartition = PartitionEntry->PartitionLength.QuadPart / dg.BytesPerSector;
(我们在步骤 2 中得到dg ,在步骤 3 中得到PartitionEntry)
完整的代码可以像下一个一样
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();
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
627 次 |
最近记录: |