вторник, 2 апреля 2013 г.

Преобразование имен файлов в формате Universal Naming Convention (UNC)

Как можно преобразовать UNC имя в ядре, чтобы оно соответствовало юзермодному имени?

То есть, например, путь:
"\Device\LanmanRedirector\Home\Users\Гость\Desktop\test.exe"
требуется преобразовать в:
"\Home\Users\Гость\Desktop\test.exe"

Немного теории.

Все удаленные файловые операции проходят через multiple UNC provider (MUP), который перенаправляет запросы подходящему сетевому редиректору (UNC провайдеру). Перенаправление происходит через подмену имени файла и установки STATUS_REPARSE, что вынуждает менеджер ввода-вывода перепослать IRP уже с новым именем.

В новое имя входит имя провайдера, ответственного за обработку запроса. Как же MUP выбирает нужного провайдера? Логично предположить, что существует некий список провайдеров. Действительно, такой список есть в реестре, в ветке:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\NetworkProvider\Order]
"ProviderOrder"="RDPNP,LanmanWorkstation,webclient"

Через наличие префиксов в имени файла, или через посылку IOCTL_REDIR_QUERY_PATH всем провайдером в списке, MUP выбирает нужного провайдера.

Каждый провайдер является службой, соответственно, имеет свою запись в ветке HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services.
Например, для LanmanWorkstation можно найти соответствующее имя девайса:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\LanmanWorkstation\NetworkProvider]
"DeviceName"="\\Device\\LanmanRedirector"

Таким образом, решение задачи преобразования имени состоит в перечислении всех имен служб UNC провайдеров, и получение имени девайса.
Соот-но последним шагом будет удаление \Device\unc provider name из исходного имени файла. Захардкодить имена провайдеров нельзя, т.к. они могут добавляться вызовом ф-ции FsRtlRegisterUncProvider.