2017-05-22 59 views
3

我的要求是通过程序扩展驱动器卷。当我在DeviceIO中使用IOCTL_DISK_GROW_PARTITION对其进行扩展时,磁盘管理将显示新修改的大小,而此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来执行相同过程的正确方法。

+0

'IOCTL_DISK_GROW_PARTITION'你只从磁盘驱动器视图扩展分区。但是你也需要扩展文件系统,它挂载了这个分区。我认为需要使用['FSCTL_EXTEND_VOLUME'(https://msdn.microsoft.com/en-us/library/windows/desktop/aa364564(V = vs.85)的.aspx)这个* *后您扩展分区 – RbMm

+0

*新的卷大小必须至少比以前的卷大小大一个群集。底层分区必须有足够的扇区来容纳扩展卷。如果没有,则可以使用IOCTL_DISK_GROW_PARTITION,如果底层设备有足够的可用空间。* - 因此请在'IOCTL_DISK_GROW_PARTITION' – RbMm

+0

后尝试'FSCTL_EXTEND_VOLUME'并且需要使用['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

回答

2

需要了解的磁盘驱动器,它维护有关磁盘布局和分区(它的大小,从磁盘偏移开始,样式(GPT或MBR))和文件系统,安装这一分区信息之间的不同。

IOCTL_DISK_GROW_PARTITION - 此ioctl由磁盘驱动程序和扩展分区处理,但这对文件系统无效,该文件系统无法处理此ioctl,并且根本不知道该分区已扩展。所以你需要额外的ioctl使用FSCTL_EXTEND_VOLUME - 这个ioctl已经发送并处理文件系统。

所以如果我们要做的下一步

  1. DISK_GROW_PARTITION作为输入发送缓冲区IOCTL_DISK_GROW_PARTITION
  2. DISK_GEOMETRY 发送IOCTL_DISK_UPDATE_DRIVE_SIZE作为输出缓冲
  3. PARTITION_INFORMATION_EX发送IOCTL_DISK_GET_PARTITION_INFO_EX为得到实际输出现在分区大小为 。
  4. 计算体积的新的大小,以扇区

    LONGLONG SectorsPerPartition = PartitionEntry->PartitionLength.QuadPart/dg.BytesPerSector;

    DG我们在步骤2和PartitionEntry在步骤3得到)

  5. 最后使用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(); 
} 
相关问题