Ответ 1
В NT "\?? \" - это префикс пути, который обозначает каталог объектов, зарезервированный для пользовательских устройств, или, более конкретно, псевдонимы устройств. Псевдоним устройства реализован в пространстве имен объекта в виде символической ссылки, которая обычно разрешается для объекта устройства в каталоге "\ Device". Иногда в документации эти псевдонимы устройств называются "соединениями" в пространстве имен объектов, что не следует путать с "соединениями каталогов" (или точками монтирования) в файловой системе.
Использование префикса "\?? \" дает указание диспетчеру объектов выполнить поиск в каталоге локального устройства вызывающего абонента "\ Sessions\0\DosDevices\[ID аутентификации входа в систему]", который связан (то есть с тенями) с каталогом глобального устройства, "\Глобальный??". Для эффективности оба этих каталога кэшируются записью сеанса входа в систему, связанной с маркером доступа, а также каждым объектом процесса. Вход в систему (ID 0x3E7) использует "\ Global??" как его локальный каталог устройств. Обратите внимание, что локальный каталог имеет ссылку "Global", чтобы разрешить доступ к глобальным устройствам, когда локальное устройство скрывает глобальное устройство (например, "\\?\Global\Z:"), или разрешить драйверу устройства создавать глобальное устройство, когда не выполняется в системном потоке. Изначально NT использовала один каталог \DosDevices независимо от вызывающего. С введением служб терминалов и быстрой коммутации пользователей в NT 5 им пришлось обобщить его для существующей системы локальных и глобальных устройств. В настоящее время для обратной совместимости "\ DosDevices" представляет собой ссылку на "\??".
Преобразование путей DOS в собственные пути NT осуществляется библиотекой времени выполнения пользовательского режима NT (то есть префиксными функциями Rtl
, которые экспортируются с помощью "ntdll.dll").
Простой случай - это путь с префиксом "\\. \" Или "\\? \". Это путь к локальному устройству, а не путь UNC. (Строго говоря, это в форме UNC-пути, но "." И "?" Являются зарезервированными доменами устройства.) В этом случае префикс просто заменяется на NT "\?? \". Разница между двумя префиксами пути устройства WINAPI заключается в том, что путь \\?\(Все обратные слэши, без прямой косой черты) - это так называемый "расширенный" путь, который обходит всю нормализацию, тогда как "\\.\"путь нормализуется.
Нормализация пути устройства разрешает "." и компоненты "..", заменяет прямую косую черту обратной косой чертой и удаляет конечные пробелы и точки из конечного компонента пути. Поскольку прямые косые черты переводятся в обратную косую черту, префикс нормализованного пути к устройству может быть "//./" или "//?/" Или любой комбинацией косой черты и обратной косой черты, за исключением точно "\\? \". Обратите внимание, что если процесс не поддерживает длинные пути, нормализованные пути ограничиваются длиной менее MAX_PATH
(260) символов. (Поддержка длинных путей может быть включена в Windows 10 через комбинацию параметров реестра и манифеста приложения; обратитесь к соответствующей документации.) GetFullPathNameW
обрабатывает оба префикса одинаково и даже нормализует расширенный путь, начинающийся с "\\? \".
UNC пути также неудивительны. Библиотека времени выполнения просто заменяет начальный "\\" в нормализованном пути явной ссылкой на устройство "UNC", то есть "\??\UNC \" (например, "\\ server\share" → "\??\UNC\сервер\доля "). Обратите внимание, что "\ Global??\UNC" является символической ссылкой на "\ Device\Mup", устройство с несколькими поставщиками UNC, которое отвечает за сопоставление "server\share" с правильным поставщиком UNC (например, с перенаправителем LanmanWorkstation для доли SMB).
Пути дисков DOS (то есть те, которые начинаются с диска "[A-Z]:") интересны в нескольких случаях. Во-первых, библиотека времени выполнения поддерживает рабочие каталоги для каждого диска, используя условно "скрытые" переменные среды, такие как "= C:". Например, "C: System32" разрешается в "C:\Windows\System32", если для переменной среды "= C:" установлено значение "C:\Windows". Кроме того, если последний компонент пути представляет собой зарезервированное имя устройства DOS, в том числе, если имя имеет конечные двоеточия, пробелы, точки и даже расширение файла, путь преобразуется в путь устройства (например, "C:\Windows \" nul:.txt "->"\??\nul "). (Устройства DOS также зарезервированы в конечном компоненте относительных путей, у которых нет диска.) В противном случае библиотека времени выполнения просто добавляет "\?? \" к нормализованному пути (например, "C: /Windows" → "\??\C:\Windows ")
.Диск DOS, такой как "C:" (то есть "\ Global??\C:"), является псевдонимом для устройства тома NT (то есть символьная ссылка на объект). Имя устройства NT не является постоянным и обычно перечисляется, поэтому конечная цель зависит от относительного порядка, в котором добавляются тома, и может даже измениться, если том будет удален и впоследствии восстановлен. Например, окончательный путь NT для "E:\Temp" на съемном диске может начинаться с "\ Device\HarddiskVolume8\Temp", а затем, после удаления и повторной установки его, новый окончательный путь - "\ Device\HarddiskVolume10 \". Temp". Диспетчер точек монтирования реализует постоянство, используя уникальный идентификатор тома, который он связывает с именем GUID тома (например, "Том {00000000-0000-0000-0000-000000000000}") и, опционально (обычно), буквой диска DOS. Имя GUID используется для реализации точек монтирования томов в файловых системах, которые поддерживают соединения (т.е. точки повторной обработки IO_REPARSE_TAG_MOUNT_POINT
), таких как NTFS и ReFS.