質問するログイン新規登録

回答編集履歴

1

情報追加およびC言語のサンプル

2018/08/20 14:28

投稿

okrt
okrt

スコア366

answer CHANGED
@@ -1,3 +1,84 @@
1
1
  ダイナミックディスクに関してstackoverflowのコメント欄では「VDSかWindows Storage Management API」が提案されてますけど、具体的にどれをどのように使えばいいのか、それで本当に正しい情報が得られるのかどうかは私にはわかりません。
2
2
 
3
- また別の方法としては、FindFirstVolume~FindNextVolume~FindVolumeCloseでボリュームを列挙して、各ボリュームに対してIOCTL_VOLUME_GET_VOLUME_DISK_EXTENTSで情報を取得して「ディスク全体から全ボリュームの分を引き算した結果が空き位置」という手法が使えるかもしれません。少し手間はかかりそうですが。
3
+ また別の方法としては、FindFirstVolume~FindNextVolume~FindVolumeCloseでボリュームを列挙して、各ボリュームに対してIOCTL_VOLUME_GET_VOLUME_DISK_EXTENTSで情報を取得して「ディスク全体から全ボリュームの分を引き算した結果が空き位置」という手法が使えるかもしれません。少し手間はかかりそうですが。
4
+
5
+ (ここから下は2018/08/20に追記)
6
+ QueryDosDevice()を利用する場合、HarddiskVolumeX形式だけで良いかどうかを調査したほうが良いかもしれません。
7
+ (昔のWindowsのダイナミックディスクでストライピングか何かにすると、普通のとは少し違った形式になってた物もあったかも……)
8
+ そこさえクリアすれば、以下の内容は無視していいかもしれません。
9
+
10
+ GitHubのソースはきちんと理解できていませんが、
11
+ ・FindVolumes()の中でFindFirstVolume~FindNextVolume~FindVolumeCloseを使用している
12
+ ・FindVolumes()ではD:の部分は得られたけど(EFI システムパーティション)の部分が得られなかった
13
+ ということですよね?
14
+ 一応、以下のソースではドライブレターが割り当てられてなくても列挙できています。C言語またはC++のソースとして適当なWindows用のコンパイラでコンパイルできるはずです。
15
+ ```C
16
+ #include <Windows.h>
17
+ #include <tchar.h>
18
+ #include <stdio.h>
19
+
20
+ void print_volume_info(TCHAR szVolumeName[])
21
+ {
22
+ HANDLE hV;
23
+ VOLUME_DISK_EXTENTS VolumeDiskExtents[16]; /* 本当はVOLUME_DISK_EXTENTSの配列じゃないけど適当 */
24
+ BOOL Bret;
25
+ DWORD lBytesReturned;
26
+ int loop;
27
+
28
+ _tprintf(_T("%s\n"), szVolumeName);
29
+ szVolumeName[_tcslen(szVolumeName)-1] = _T('\0'); /* 末尾1文字を削除する */
30
+ hV = CreateFile(
31
+ szVolumeName,
32
+ 0,
33
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
34
+ NULL,
35
+ OPEN_EXISTING,
36
+ FILE_ATTRIBUTE_READONLY,
37
+ NULL );
38
+ if (hV == INVALID_HANDLE_VALUE) {
39
+ return;
40
+ }
41
+ Bret = DeviceIoControl(
42
+ hV,
43
+ IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
44
+ NULL,
45
+ 0,
46
+ &VolumeDiskExtents,
47
+ sizeof(VOLUME_DISK_EXTENTS)*16,
48
+ &lBytesReturned,
49
+ NULL);
50
+ if (Bret != 0) {
51
+ _tprintf(_T("IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS\n"));
52
+ _tprintf(_T("%d NumberOfDiskExtents\n"), VolumeDiskExtents[0].NumberOfDiskExtents);
53
+ for(loop=0; loop<(int)VolumeDiskExtents[0].NumberOfDiskExtents; loop++) {
54
+ _tprintf(_T(" %d DiskNumber\n"), VolumeDiskExtents[0].Extents[loop].DiskNumber);
55
+ _tprintf(_T(" %f StartingOffset\n"), VolumeDiskExtents[0].Extents[loop].StartingOffset.QuadPart/1.0);
56
+ _tprintf(_T(" %f ExtentLength\n"), VolumeDiskExtents[0].Extents[loop].ExtentLength.QuadPart/1.0);
57
+ }
58
+ _tprintf(_T("OK\n\n"), szVolumeName);
59
+ }
60
+ /* DVDドライブも列挙されたりするのでOKが出ない物もある */
61
+ CloseHandle(hV);
62
+ }
63
+
64
+ int list_all_volumes(void)
65
+ {
66
+ HANDLE hFV;
67
+ TCHAR szVolumeName[MAX_PATH];
68
+
69
+ hFV = FindFirstVolume(szVolumeName, MAX_PATH);
70
+ if (hFV == INVALID_HANDLE_VALUE) {
71
+ return 1;
72
+ }
73
+ do {
74
+ print_volume_info(szVolumeName);
75
+ } while(FindNextVolume(hFV, szVolumeName, MAX_PATH));
76
+ FindVolumeClose(hFV);
77
+ return 0;
78
+ }
79
+
80
+ int main(int argc, TCHAR **argv)
81
+ {
82
+ return list_all_volumes();
83
+ }
84
+ ```