質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

Q&A

1回答

1341閲覧

ダイナミックディスクでGPTなPhysicalDriveから パーティションの空き位置の情報の取得方法について

juner

総合スコア95

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

0グッド

1クリップ

投稿2018/08/13 07:06

編集2022/01/12 10:55

前提・実現したいこと

現在、ディスクの管理にて次の様に表示されるダイナミックディスクでGPTなドライブよりパーティションの空き情報を取得方法を探しています。
[100MB 正常(EFI システムパーティション)][97.66GB 未割り当て][D: 833.63GB NTFS 正常]
※ソフトウェアRAIDを使用している4つのディスクの一つとなっております。

発生している問題

パーティションの空き情報はパーティションの情報からることができる思い、 GPTな物理ドライブの \.\PhysicaDrive0 より DeviceIoControlIOCTL_DISK_GET_DRIVE_LAYOUT_EX 経由でパーティション間の空き領域情報を取得しようとしてみたのですが、それにより取得される。 DRIVE_LAYOUT_INFORMATION_EXPartitionEntry[] こと PARTITION_INFORMATION_EX に設定される パーティションの各情報は次の様な形となります。

PartitionNumberStartOffsetPartitionLengthStartOffset+PartitionLengthType
11048576104857600105906176c12a7328-f81f-11d2-ba4b-00a0c93ec93b
210590617610485761069547525808c8aa-7e8f-42e0-85d2-e1e90434cfb3
3106954752133169152240123904e3c9e316-0b5c-4db8-817d-f92df00215ae
42401239049999647452161000204869120af9b60a0-1431-4f62-bc68-3311714a69ad

想定していた隙間がどこにも空いていませんでした。

試したこと

以下の方法を試しました。

list partition

尚、disikpartlist partition すると、次の様な表示となりました。

diskpart

1 Partition ### Type Size Offset 2 ------------- ------------------ ------- ------- 3 Partition 1 システム 100 MB 1024 KB 4 Partition 2 予約済みダイナミック 1024 KB 101 MB 5 Partition 3 予約 127 MB 102 MB 6 Partition 4 ダイナミック データ 931 GB 229 MB

####FindVolume で取得されたVolumeに対しての読み込み
FindVolume で取得されたVolumeに対して IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTSにより読み込んだ場合対象のドライブに関しての情報は次のものだけとなった。

StartOffsetExtentLengthStartOffset+ExtentLegnth
1050977239048951064166401000204140544

マウントしているボリュームのみ取得される様で、RAID構成されているDドライブの位置だけわかる状態となっておりました。(計4ディスクの位置も取得されているがここでは必要な情報だけ載せる形で省略。

使用したコード
juner/IoControl#93f655872fb7bda6e60d0f0ca13ff96c47680e30
IoControlPhysicalExample

####QueryDosDevice() より取得されたパス群の中より、ボリュームを探して取得
QueryDosDevice()より取得したデバイス名群より、HarddiskVolumeX 形式の名前を探し、それを元にIOCTL_VOLUME_GET_VOLUME_DISK_EXTENTSを実施した。

FilePathStartOffsetExtentLengthStartOffset+ExtentLegnth
.\HarddiskVolume11048576104857600105906176
.\HarddiskVolume2106954752133169152240123904
.\HarddiskVolume101050977239048951064166401000204140544

一部のパーティションが取得できていないが、これがほしかった情報であろうか?

このコードは FindVolume で取得されたVolumeに対しての読み込み の確認に使ったコードに含まれる。

GPTPartition情報を直に読み込む

PartitionNumberFirst(LBA8)Last(LBA8)SectorSizeFirst*SectorSizeLast*SectorSize
10x8000x327FF5121048576105905664
20x328000x32FFF512105906176106954240
30x330000x727FF512106954752240123392
40x728000x74706D8E5122401239041000204868608

FirstSectorSize が合致しているのでこの情報はほぼ同じ情報と想定される。LastSectorSize がずれるのは誤差?

確認に使用したコード
juner/ReadHeader#8591d9704b9b5dd4c2ffdc2192e9c779563c89e5
ReadHeaderExample

補足情報(FW/ツールのバージョンなど)

OS: Windows10 (1803)

以上、よろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

okrt

2018/08/14 13:47

C:ではなくD:で\\.\PhysicaDrive0というのが気になるところではありますが、ここが問題ではないとすれば「ダイナミックディスクを使用しているということで合ってますか?」合ってるとすれば、それが要因かもしれません。 https://stackoverflow.com/questions/33384413/how-to-open-a-partition-handle-to-get-its-information-on-a-dynamic-disk の回答のコメント欄に何か書かれてます。ちなみに、「ダイナミック ディスクは Windows では推奨されなくなりました。 」だそうです。 https://docs.microsoft.com/ja-jp/windows-server/storage/disk-management/change-a-dynamic-disk-back-to-a-basic-disk
juner

2018/08/16 02:54

今回のこのディスクは ソフトウェアRAID構成を行った4つのディスクの一つな為、ダイナミックディスクであることが必須な為、上記の様な状態となっております。
guest

回答1

0

ダイナミックディスクに関してstackoverflowのコメント欄では「VDSかWindows Storage Management API」が提案されてますけど、具体的にどれをどのように使えばいいのか、それで本当に正しい情報が得られるのかどうかは私にはわかりません。

また別の方法としては、FindFirstVolume~FindNextVolume~FindVolumeCloseでボリュームを列挙して、各ボリュームに対してIOCTL_VOLUME_GET_VOLUME_DISK_EXTENTSで情報を取得して「ディスク全体から全ボリュームの分を引き算した結果が空き位置」という手法が使えるかもしれません。少し手間はかかりそうですが。

(ここから下は2018/08/20に追記)
QueryDosDevice()を利用する場合、HarddiskVolumeX形式だけで良いかどうかを調査したほうが良いかもしれません。
(昔のWindowsのダイナミックディスクでストライピングか何かにすると、普通のとは少し違った形式になってた物もあったかも……)
そこさえクリアすれば、以下の内容は無視していいかもしれません。

GitHubのソースはきちんと理解できていませんが、
・FindVolumes()の中でFindFirstVolume~FindNextVolume~FindVolumeCloseを使用している
・FindVolumes()ではD:の部分は得られたけど(EFI システムパーティション)の部分が得られなかった
ということですよね?
一応、以下のソースではドライブレターが割り当てられてなくても列挙できています。C言語またはC++のソースとして適当なWindows用のコンパイラでコンパイルできるはずです。

C

1#include <Windows.h> 2#include <tchar.h> 3#include <stdio.h> 4 5void print_volume_info(TCHAR szVolumeName[]) 6{ 7 HANDLE hV; 8 VOLUME_DISK_EXTENTS VolumeDiskExtents[16]; /* 本当はVOLUME_DISK_EXTENTSの配列じゃないけど適当 */ 9 BOOL Bret; 10 DWORD lBytesReturned; 11 int loop; 12 13 _tprintf(_T("%s\n"), szVolumeName); 14 szVolumeName[_tcslen(szVolumeName)-1] = _T('\0'); /* 末尾1文字を削除する */ 15 hV = CreateFile( 16 szVolumeName, 17 0, 18 FILE_SHARE_READ|FILE_SHARE_WRITE, 19 NULL, 20 OPEN_EXISTING, 21 FILE_ATTRIBUTE_READONLY, 22 NULL ); 23 if (hV == INVALID_HANDLE_VALUE) { 24 return; 25 } 26 Bret = DeviceIoControl( 27 hV, 28 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, 29 NULL, 30 0, 31 &VolumeDiskExtents, 32 sizeof(VOLUME_DISK_EXTENTS)*16, 33 &lBytesReturned, 34 NULL); 35 if (Bret != 0) { 36 _tprintf(_T("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS\n")); 37 _tprintf(_T("%d NumberOfDiskExtents\n"), VolumeDiskExtents[0].NumberOfDiskExtents); 38 for(loop=0; loop<(int)VolumeDiskExtents[0].NumberOfDiskExtents; loop++) { 39 _tprintf(_T(" %d DiskNumber\n"), VolumeDiskExtents[0].Extents[loop].DiskNumber); 40 _tprintf(_T(" %f StartingOffset\n"), VolumeDiskExtents[0].Extents[loop].StartingOffset.QuadPart/1.0); 41 _tprintf(_T(" %f ExtentLength\n"), VolumeDiskExtents[0].Extents[loop].ExtentLength.QuadPart/1.0); 42 } 43 _tprintf(_T("OK\n\n"), szVolumeName); 44 } 45 /* DVDドライブも列挙されたりするのでOKが出ない物もある */ 46 CloseHandle(hV); 47} 48 49int list_all_volumes(void) 50{ 51 HANDLE hFV; 52 TCHAR szVolumeName[MAX_PATH]; 53 54 hFV = FindFirstVolume(szVolumeName, MAX_PATH); 55 if (hFV == INVALID_HANDLE_VALUE) { 56 return 1; 57 } 58 do { 59 print_volume_info(szVolumeName); 60 } while(FindNextVolume(hFV, szVolumeName, MAX_PATH)); 61 FindVolumeClose(hFV); 62 return 0; 63} 64 65int main(int argc, TCHAR **argv) 66{ 67 return list_all_volumes(); 68}

投稿2018/08/16 13:45

編集2018/08/20 14:28
okrt

総合スコア366

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問