Преобразование из пути к устройству Windows NT в путь буквы диска

Как я могу разрешить путь с буквой диска из пути к устройству?

Например, преобразовать

\Device\HarddiskVolume4\Windows\System32\RuntimeBroker.exe

в

C:\Windows\System32\RuntimeBroker.exe

Предполагается, что HarddiskVolume4 соответствует C: на этом компьютере.

Я нашел этот вопрос, но хочу использовать его в C # .


person Bruno Zell    schedule 18.01.2018    source источник
comment
действительно все решения по вашей ссылке не самые лучшие. чистое и эффективное решение задачи - используйте IOCTL_MOUNTMGR_QUERY_POINTS. но я могу вставить его только на c ++, но не на c #   -  person RbMm    schedule 18.01.2018
comment
В вашем случае есть точка монтирования C: логического диска, но предположение, что вы можете перебирать точки монтирования с буквой диска с помощью QueryDosDevice, в целом неверно. Том может быть смонтирован в папке или иметь только имя тома {GUID}. Я думаю, что самое простое решение - добавить \\? \ GLOBALROOT к пути; открыть файл с минимальным доступом; и позвоните GetFinalPathNameByHandle, чтобы попытаться получить его VOLUME_NAME_DOS или VOLUME_NAME_GUID. В противном случае вам нужно запросить \\. \ MountPointManager IOCTL_MOUNTMGR_QUERY_POINTS через DeviceIoControl, как указано выше.   -  person Eryk Sun    schedule 18.01.2018
comment
@eryksun Это кажется очень интересным. Я разберусь!   -  person Bruno Zell    schedule 18.01.2018
comment
Зависит от того, какая вам нужна буква имени диска. если нужен вызов CreateFileW - можно просто добавить префикс \\\\? \\ GLOBALROOT. или используйте NtOpenFile. однако, если вам нужно использовать его в оболочке api - правильный способ получил массив MOUNTMGR_MOUNT_POINT через IOCTL_MOUNTMGR_QUERY_POINTS и нашел, где DeviceName был точным префиксом для вашего пути. и замените этот префикс на префикс SymbolicLinkName, если он в форме MOUNTMGR_IS_DRIVE_LETTER   -  person RbMm    schedule 18.01.2018


Ответы (1)


string devicePath = @"\Device\HarddiskVolume4\Windows\System32\RuntimeBroker.exe";
string driveLetterPath = DevicePathMapper.FromDevicePath(devicePath);

// driveLetterPath == C:\Windows\System32\RuntimeBroker.exe

Поскольку нам нужен путь с буквой диска, нам нужно заменить \Device\HarddiskVolume4 на правильную букву диска, например C:. Для этого используйте _4 _ и сопоставьте устройство dos с каждой буквой диска. Затем мы можем искать и заменять путь к устройству dos.

Это возможная реализация. Он использует внутренние методы расширения:

public static class DevicePathMapper {
    [DllImport("Kernel32.dll", CharSet = CharSet.Unicode)]
    private static extern uint QueryDosDevice([In] string lpDeviceName, [Out] StringBuilder lpTargetPath, [In] int ucchMax);

    public static string FromDevicePath(string devicePath) {
        var drive = Array.Find(DriveInfo.GetDrives(), d => devicePath.StartsWith(d.GetDevicePath(), StringComparison.InvariantCultureIgnoreCase));
        return drive != null ?
            devicePath.ReplaceFirst(drive.GetDevicePath(), drive.GetDriveLetter()) :
            null;
    }

    private static string GetDevicePath(this DriveInfo driveInfo) {
        var devicePathBuilder = new StringBuilder(128);
        return QueryDosDevice(driveInfo.GetDriveLetter(), devicePathBuilder, devicePathBuilder.Capacity + 1) != 0 ?
            devicePathBuilder.ToString() :
            null;
    }

    private static string GetDriveLetter(this DriveInfo driveInfo) {
        return driveInfo.Name.Substring(0, 2);
    }

    private static string ReplaceFirst(this string text, string search, string replace) {
        int pos = text.IndexOf(search);
        if (pos < 0) {
            return text;
        }
        return text.Substring(0, pos) + replace + text.Substring(pos + search.Length);
    }
}
person Bruno Zell    schedule 18.01.2018