2006 年 10 月 27 日 23 時 54 分

ボリュームマウントポイントの作成


このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。


ボリュームマウントポイントの API も充実している。
ボリュームを、ドライブやパスに割り当てるには、
SetVolumeMountPoint API を使うだけでできる。

    BOOL SetVolumeMountPoint(
        LPCSTR lpszVolumeMountPoint,
        LPCSTR lpszVolumeName
    );

lpszVolumeMountPoint には、割り当てるドライブの
ルートディレクトリや、マウント先ディレクトリを指定する。
例えば、「R:\」や「D:\mnt\cdrom\」などとなる。
どちらの場合でも、パスの最後には \ 記号が必要だ。

lpszVolumeName にはボリュームを示すパスを指定する。
昨日も見た \\?\ で始まる特殊なデバイスパスだ。
\\?\Volume{f08e7d20-64f1-11db-b10d-001125868411}\
これにも、パスの最後には \ 記号が必要だ。

逆に、ボリュームのマウント解除は、
DeleteVolumeMountPoint 関数で行うことができる。

    BOOL DeleteVolumeMountPoint(
        LPCSTR lpszVolumeMountPoint
    );

この lpszVolumeMountPoint は、
マウントされているドライブやディレクトリのパスである。

システムに存在するボリュームは、FindFirstVolume,
FindNextVolume, FindVolumeClose API で列挙できる。

    TCHAR volumePath[MAX_PATH];
    HANDLE handle;

    handle = FindFirstVolume(volumePath, MAX_PATH);
    if (handle != INVALID_HANDLE_VALUE) {
        do {
            fwprintf(stdout, L"%s\n", volumePath);
        } while (FindNextVolume(handle, volumePath, MAX_PATH));
        FindVolumeClose(handle);
    }

ボリュームを扱う場合、その識別子を知る必要がある。
事前に識別子が分かっている場合や、
全てのボリュームを処理する場合は上記の API で済むが、
デバイスからボリュームを調べる際には困ったことになる。

実は、パーティションなどの物理的なデバイス位置から、
その識別子を得るのは容易ではない。

ボリュームがドライブやディレクトリにマウントされていれば、
そのボリュームの識別子を得る方法はある。

    BOOL GetVolumeNameForVolumeMountPoint(
        LPTSTR lpszVolumeMountPoint,
        LPTSTR lpszVolumeName,
        DWORD cchBufferLength
    );

lpszVolumeMountPoint にマウント先のパスを渡すと、
lpszVolumeName バッファに \\?\Volume{~} が得られる。

もし、マウントされていないボリュームを調べる場合は、
少し面倒な手順を踏む必要がある。

ボリューム識別子やマウント先は、Windows の内部にある、
ドライバオブジェクトマネージャで管理されており、
ボリューム識別子は、実際のデバイスに関連付けられている。

例えば、俺の環境の場合、デバイスパス、
Volume{f08e7d20-64f1-11db-b10d-001125868411} は、
\Device\CdRom3 を示していることは分かるのだが、
\Device\CdRom3 が上の識別子であることは分からない。

そのため、一度 DefineDosDevice を使って、
\Device\CdRom0 や、\Device\HarddiskVolume1 などの
デバイスパスをドライブに一時的に関連付けた後、
割り当てたドライブに対して、
GetVolumeNameForVolumeMountPoint を呼び出して
ボリューム識別子(ボリュームパス)を取得し、
最後に一時的なドライブを削除するという手順になる。

例えば、CD-ROM ドライブ 3 を、
「D:\mnt\cdrom」に割り当てる場合は、
以下のような手順となる。

    DefineDosDevice(DDD_RAW_TARGET_PATH,
            "W:", "\\Device\\CdRom3");

    GetVolumeNameForVolumeMountPoint(
            "W:\\", <volume_path>, <length>);

    DefineDosDevice(DDD_RAW_TARGET_PATH
            | DDD_REMOVE_DEFINITION
            | DDD_EXACT_MATCH_ON_REMOVE,
            "W:", "\\Device\\CdRom3");

    SetVolumeMountPoint("D:\\mnt\\cdrom\\",
            <volume_path>);

これについては、MSDN にもサンプルがある。
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/editing_drive_letter_assignments.asp

かなり低水準の操作となるので、
深い世界に足を踏み込み必要があるのだ。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.