2017-05-22 15 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 
    ); 

私は、ディスクのMBRが変更されたが、ドライブのクラスタビットマップが変更されていない、このAPIを使用していることがわかりました。この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

*新しいボリュームサイズは、以前のボリュームサイズよりも少なくとも1つのクラスタ以上でなければなりません。基本パーティションには、拡張ボリュームを格納するのに十分なセクタが必要です。 IOCTL_DISK_GROW_PARTITIONは、基盤デバイスに十分な空き容量がある場合に使用できます。* - IOCTL_DISK_GROW_PARTITIONの後で 'FSCTL_EXTEND_VOLUME'を試してください。 – RbMm

+0

[' 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. は、実際の取得のための出力として PARTITION_INFORMATION_EXIOCTL_DISK_GET_PARTITION_INFO_EXを送信する出力バッファとしてDISK_GEOMETRYIOCTL_DISK_UPDATE_DRIVE_SIZEを送信する入力バッファとして DISK_GROW_PARTITIONIOCTL_DISK_GROW_PARTITIONを送信を行う必要がありそうならば パーティションのサイズ。
  2. ついにFSCTL_EXTEND_VOLUME

  3. を使用

    DG我々はステップ3で、ステップ2とPartitionEntryで得た)部門

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

    で、

  4. のボリュームの新しいサイズを計算

フルコード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(); 
} 
関連する問題