Использование версий nt и Zw собственных системных служб
API собственных служб операционной системы Windows реализуется в виде набора подпрограмм, которые выполняются в режиме ядра. Эти подпрограммы имеют имена, начинающиеся с префикса NT или Zw. Драйверы режима ядра могут вызывать эти подпрограммы напрямую. Приложения в пользовательском режиме могут получать доступ к этим подпрограммам с помощью системных вызовов.
За некоторыми исключениями каждая собственная подпрограмма системных служб имеет две немного разные версии с похожими именами, но разными префиксами. Например, вызовы NtCreateFile и ZwCreateFile выполняют аналогичные операции и фактически обслуживаются одной системной подпрограммой режима ядра. Для системных вызовов из пользовательского режима версии подпрограммы Nt и Zw ведут себя одинаково. Для вызовов из драйвера режима ядра версии подпрограммы Nt и Zw отличаются тем, как они обрабатывают значения параметров, которые вызывающий объект передает подпрограмме.
Драйвер в режиме ядра вызывает версию Zw собственной подпрограммы системных служб, чтобы сообщить подпрограмме, что параметры поступают из доверенного источника в режиме ядра. В этом случае подпрограмма предполагает, что она может безопасно использовать параметры без предварительной проверки. Однако если параметры могут быть из источника в пользовательском режиме или в режиме ядра, драйвер вместо этого вызывает nt-версию подпрограммы, которая на основе истории вызывающего потока определяет, были ли параметры созданы в пользовательском режиме или режиме ядра. Дополнительные сведения о том, как подпрограмма отличает параметры пользовательского режима от параметров режима ядра, см. в разделе PreviousMode.
Когда приложение в пользовательском режиме вызывает nt илиZw-версию собственной подпрограммы системных служб, подпрограмма всегда обрабатывает получаемые параметры как значения, поступающие из источника пользовательского режима, который не является доверенным. Подпрограмма тщательно проверяет значения параметров, прежде чем использовать параметры. В частности, подпрограмма проверяет все буферы, предоставляемые вызывающим объектом, чтобы убедиться, что буферы находятся в допустимой памяти пользовательского режима и правильно ли они выровнены.
Подпрограммы собственных системных служб делают дополнительные предположения о получаемых ими параметрах. Если подпрограмма получает указатель на буфер, выделенный драйвером режима ядра, подпрограмма предполагает, что буфер был выделен в системной памяти, а не в памяти пользовательского режима. Если подпрограмма получает дескриптор, открытый приложением в пользовательском режиме, подпрограмма ищет дескриптор в таблице дескрипторов пользовательского режима, а не в таблице дескрипторов режима ядра.
В некоторых случаях значение параметра значительно отличается при вызовах из пользовательского режима и режима ядра. Например, подпрограмма ZwNotifyChangeKey (или ее аналог NtNotifyChangeKey ) имеет пару входных параметров ApcRoutine и ApcContext, которые означают разные вещи в зависимости от того, относятся ли параметры к источнику в пользовательском режиме или в режиме ядра. Для вызова из пользовательского режима ApcRoutine указывает на подпрограмму APC, а ApcContext — на контекстное значение, которое предоставляет операционная система при вызове подпрограммы APC. Для вызова из режима ядра ApcRoutine указывает на структуру WORK_QUEUE_ITEM , а ApcContext указывает тип элемента рабочей очереди, описываемый структурой WORK_QUEUE_ITEM .
Этот раздел содержит следующие подразделы: