[Previous] [Next]

Программные средства от Microsoft

Основным средством разработки является Microsoft Windows DDK, Device Driver Kit, — пакет разработки драйверов, включающий компилятор, редактор связей (линкер), заголовочные файлы, библиотеки, большой набор примеров (часть из которых является драйверами, реально работающими в операционной системе) и, разумеется, документацию. В состав пакета входит также отладчик WinDbg, позволяющий проводить интерактивную отладку драйвера на двухкомпьютерной конфигурации и при наличии файлов отладочных идентификаторов операционной системы WinDbg кроме того, позволяет просматривать файлы дампа (образа) памяти, полученного при фатальных сбоях операционной системы (так называемый crash dump file).

Следует особо отметить, что языком программирования, который используется в DDK является язык С, разумеется, допускающий вставки на языке ассемблер, который в былые времена был основным и единственным языком программирования драйверов.

В бесплатно распространяемом пакете DDK всегда отсутствовала интегрированная среда разработки. Поэтому программисты драйверов всегда были вынуждены подбирать для себя и средство редактирования исходного кода. Выбор был, практически, безальтернативен — пакет Visual С++ (теперь это Visual Studio 7 Net). При должной настройке этой среды процесс выявлений синтаксических ошибок существенно облегчается — неотъемлемое преимущество интегрированных сред программирования. Компилятор и редактор связей Visual Studio C++ создают нормальный бинарный код, вполне работоспособный при указании соответствующих опций (настроек) компиляции, однако эталоном следует считать бинарный код, получающийся при компиляции кода драйвера с использованием утилиты Build из состава пакета DDK. Разумеется, встроенный интерактивный отладчик Visual Studio и прилагаемая документация становятся для разработки драйвера совершенно бесполезными, поскольку не предназначены для работы с программным обеспечением для режима ядра.

Разработчику драйвера могут быть полезны некоторые вспомогательные программы, поставляемые теперь в составе Platform SDK, например утилита Depends, подробнее о которой будет сказано ниже.

Многие программные средства, упоминаемые в данной главе, являются коммерческими продуктами, их использование затрагивает вопросы приобретения и лицензирования, что выходит за рамки рассмотрения технических проблем, которым посвящена данная книга.

Настройки проекта в Visual Studio 7 Net

Настройка проекта для компиляции и сборки драйвера режима ядра существенно отличаются от настроек, которые используются для работы с приложениями и динамическими библиотеками пользовательского режима. Ниже приводится точный текст файл Example.sln ("sln" является сокращением от "solution"), который описывает проект драйвера Example, рассматриваемого в следующей главе.

Microsoft Visual Studio Solution File, Format Version 7.00
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Example",
	"Example.vcproj", "{E524BA09-7993-4528-91A9-7E27FAA3565F}"
EndProject
Global
	GlobalSection(SolutionConfiguration) = preSolution
	ConfigName.0 = Checked
	EndGlobalSection
	GlobalSection(ProjectDependencies) = postSolution
	EndGlobalSection
	GlobalSection(ProjectConfiguration) = postSolution
	{E524BA09-7993-4528-91A9-7E27FAA3565F}.Checked.ActiveCfg =
		Checked|Win32
	{E524BA09-7993-4528-91A9-7E27FAA3565F}.Checked.Build.0 =
		Checked|Win32
	EndGlobalSection
	GlobalSection(ExtensibilityGlobals) = postSolution
	EndGlobalSection
	GlobalSection(ExtensibilityAddIns) = postSolution
	EndGlobalSection
EndGlobal

Значительно более важным в проекте Example является файл Example.vcproj, который содержит конкретные значения настроек и описания используемых файлов. Точный текст Example.vcproj (файла настроек для компиляции и сборки простейшего не-WDM драйвера checked-версии в среде Visual Studio 7 Net) приводится ниже.

<?xml version="1.0" encoding = "windows-1251"?>
<VisualStudioProject ProjectType="Visual C++"
Version="7.00"
Name="Example"
SccProjectName=""
SccLocalPath="">
<Platforms><Platform Name="Win32"/></Platforms>
<Configurations> <Configuration Name="Release|Win32"
		OutputDirectory=".\checked"
		IntermediateDirectory=".\checked"
		ConfigurationType="2"
		UseOfMFC="0"
		ATLMinimizesCRunTimeLibraryUsage="FALSE"
		CharacterSet="1">
		<Tool Name="VCCLCompilerTool"
			AdditionalOptions="/Zel -cbstring /QIfdiv- /QIf /Gi- /Gm- /GX"
			Optimization="0"
			EnableIntrinsicFunctions="FALSE"
			OmitFramePointers="TRUE"
			OptimizeForProcessor="2"
			AdditionalIncludeDirectories="C:\WinDDK\2600\inc\ddk\w2k;
				C:\WinDDK\2600\inc\w2k;C:\WinDDK\2 600\inc\crt"
			PreprocessorDefinitions="_X86_=l;i386=l;
				CONDITION_HANDLING=1;NT_UP=1;
				NT_INST=0; WIN32=100;_NT1X_=100;WINNT=l;
				_WIN32_WINNT=0x0400;WIN32_LEAN_AND_MEAN=1;
				DEVL=l;DBG=l;FPO=0"
			IgnoreStandardIncludePath="TRUE"
			StringPooling="TRUE"
			ExceptionHandling="TRUE"
			RuntimeLibrary="O"
			StructMemberAlignment="4"
			BufferSecurityCheck="FALSE"
			EnableFunctionLevelLinking="TRUE"
			PrecompiledHeaderFile=".\checked/Example.pch"
			AssemblerListingLocation=".\checked/"
			ObjectFile=".\checked/"
			ProgramDataBaseFileName=".\checked\Example.pdb"
			WarningLevel="3"
			SuppressStartupBanner="TRUE"
			DebugInformationFormat="l"
			CallingConvention="2"
			CompileAs="0"
			ForcedIncludeFiles="warning.h"/>
		<Tool Name="VCCustomBuildTool"/>
		<Tool Name="VCLinkerTool" AdditionalOptions=""
			AdditionalDependencies="hal.lib ntoskrnl.lib int64.1ib
				msvcrt.lib "
			OutputFile=".\checked\Example.sys"
			Version="5.0"
			LinkIncremental="l"
			SuppressStartupBanner="TRUE"
			AdditionalLibraryDirectories="C:\WinDDK\2 600\lib\w2k\i386"
			IgnoreAllDefaultLibraries="TRUE"
			ProgramDatabaseFile=".\checked/Example.pdb"
			GenerateMapFile="TRUE"
			MapFileName="Example.map"
			StackReserveSize="262144" 			
			StackCommitSize="4096"
			OptimizeReferences="2"
			EnableCOMDATFolding="2"
			EntryPointSymbol="DriverEntry"
			SetChecksum="TRUE"
			BaseAddress="0x10000"
			ImportLibrary=""
			MergeSections=".rdata=.text"
			TargetMachine="1"/>
		<Tool Name="VCMIDLTool"
			MkTypLibCompatible="TRUE"
			SuppressStartupBanner="TRUE"
			TargetEnvironment="1"
			TypeLibraryName=".\checked/Example.tlb"/>
		<Tool Name="VCPostBuildEventTool"/>
		<Tool Name="VCPreBuildEventTool">
		<Tool Name="VCPreLinkEventTool"/>
		<Tool Name="VCResourceCompilerTool"/>
		<Tool Name="VCWebServiceProxyGeneratorTool"/>
		<Tool Name="VCWebDeploymentTool"/>
</Configuration>
</Configurations>
<Files> <Filter Name="Header Files" Filter=".h">
		<File RelativePath=".\Driver.h"> </File>
	</Filter>
	<Filter Name="Source Files" Filter=".c;.cpp">
		<File RelativePath="Init.cpp"> </File>
	</Filter>
</Files>
<Globals></Globals>
</VisualStudioProject>

Приведенный выше текст переформатирован (для удобства чтения в формате книги), поэтому расположение слов несколько отличается от их размещения в оригинальных .vcproj файлах, генерируемых средой Visual Studio 7 Net. Значения строковых параметров AdditionalIncludeDirectories и PreprocessorDefinitions обязательно должны быть записаны в одну строку.

Следует отметить, что особую важность для компиляции имеют значения пара метров IgnoreStandardIncludePath (здесь он отменяет стандартные пути для обнаружения заголовочных файлов, которые явно заданы теперь в параметре AdditionalIncludeDirectories), AdditionalOptions и PreprocessOrDefinitions (значения которых рекомендуется повторить в точности), CallingConvention (здесь определяет __stdcall).

Из параметров сборки следует отметить параметры IgnoreAllDefaultLibraries (здесь он отменяет использование библиотек, назначаемых в Visual Studio по умолчанию), AdditionalLibraryDirectories и AdditionalDependencies (они определяют используемые библиотеки — в данном случае для сборки не-WDM драйвера под Windows 2000), BaseAddress (обязательно следует указать равным 0x10000) и "неприметный" коварный параметр SetChecksum (должен быть "TRUE").

Все эти параметры можно настроить интерактивно и в самой интегрированной среде Visual Studio, однако, затем рекомендуется сравнить содержимое файла .vcproj с приведенным текстом, стараясь получить полное совпадение.

Компиляция и сборка драйвера утилитой Build пакета DDK

В том варианте, как поставляется пакет DDK, весьма просто использовать компилятор и редактор связей этого пакета. Для этого следует выбрать в меню запуска программ Пуск — Программы — ... запуск соответствующей среды (по ряду причин наиболее предпочтителен выбор среды Window 2000, checked или free), в результате чего появится консольное окно, для которого уже (автоматически) будут должным образом установлены переменные окружения. В том случае, если у разработчика имеются файлы makefile, sources (описывающие процесс сборки данного конкретного драйвера), а пакет DDK установлен корректно, то необходимо лишь перейти в рабочую директорию проекта командой cd (для драйвера, рассматриваемого в следующей главе, это — директория C:\Example) и ввести команду build (см. рисунок 2.1). Разумеется, что в случае ошибок компиляции или сборки вывод будет содержать и их диагностику.

Рис. 2.1
Рабочее окно сборки драйвера под Windows 2000 DDK версии checked

Программа Depends

Программа Depends предназначена для просмотра вызовов дополнительных библиотек. Программа Depends была создана в 1996 году и ранее поставлялась в составе Visual Studio 6. Теперь она является частью Platform SDK.

Скриншот (снимок экрана), представленный на рисунке 2.2, выполнен для просмотра дерева вызовов известного драйвера GiveIo.Sys. (Этот драйвер разблокирует доступ к портам ввода/вывода из приложений пользовательского режима при работе под Windows NT, используя при этом недокументированные возможности Windows.)

На приведенном рисунке видно, что драйвер обращается к функциям, экспортируемым NTOSKRNL.EXE, причем видно, что первыми (в порядке алфавита) являются вызовы IoCreateDevice, IoCreateSymbolicLink, IoDeleteDevice, IoDeleteSymbolicLink и др.

Программа может быть использована для просмотра вызовов, выполняемых из драйверов, исполняемых файлов (.exe файлов) и динамических библиотек. Программа работает и под Windows 98.

Рис. 2.2
Программа Depends для драйвера GiveIo

Программа ReBase

Программа ReBase (консольное приложение) поставляется в составе Visual Studio и выполняет удаление отладочной информации из бинарных файлов, скомпилированных и собранных проектов, в нашем случае — из бинарных файлов драйверов (.sys файлов). Даже после сборки окончательной (релизной, free) версии драйвера при помощи программ DDK в нем еще остается некоторая отладочная информация (например, внутренние имена функций), которую программа ReBase может выделить и поместить в файл отладочных идентификаторов. Размер бинарного файла может уменьшиться при этом на четверть.

Ниже приведены примеры командной строки для запуска программы ReBase применительно к драйверу:

rebase -В 0x10000 -X . example.sys
rebase -xa dbgdir -Ь 0x10000 -l protocol example.sys 

Во втором примере ключ -xa (расширение ключа -x из первого примера) задает удаление всей отладочной информации (с перемещением ее в файл с расширением .dbg). Директория, где будет размещен этот .dbg файл в первом примере — текущая (поскольку указана точка после -x), во втором — вложенная поддиректория .\dbgdir. Ключ -b указывает базовый адрес (для драйверов режима ядра всегда указывается значение 0x10000), ключ -l (эль) указывает файл протокола (log file), во втором примере файл protocol.

Более подробно с командами ReBase можно ознакомиться через сообщение, которое программа выведет по команде

rebase -? 

Программа ErrLook

Программа ErrLook, поставляемая и в составе DDK и в составе Visual Studio, представляет собой декодер сообщений об ошибках. Полученный в приложениях пользовательского режима код ошибки (целое число) по вызову функции GetLastError несет мало информации для недостаточно квалифицированного пользователя. Получить по этому коду текстовое представления сообщения об ошибке можно с помощью специальных функций (при программировании приложения), либо подставив это число в программу ErrLook, как это показано на рисунке 2.3.

Рис. 2.3
Программа ErrLook

Предположим, рабочая процедура драйвера возвратила управление Диспетчеру ввода/вывода, установив код завершения обработки пакета IRP равным STATUS_DEVICE_POWERED_OFF. В результате, если пользовательское приложение обратилось к драйверу с вызовом DeviceIoControl, но драйвером ответил отказом такого рода, то Диспетчер ввода/вывода передает приложению код ошибочного завершения вызова функции (для DeviceIoControl это 0) и устанавливает код ошибки (известный в документации MSDN под названием "system error code"). B свою очередь, пользовательское приложение может вызвать функцию GetLastError и в результате получит число 21 (которое и определил Диспетчер вода/вывода), что соответствует ошибке ERROR_NOT_READY — "The device is not ready". В примере, представленном на рисунке 2.3, программа ErrLook транслирует код 21 в текстовое сообщение, которое в русскоязычной версии Windows выдается в нижнем окошке на русском языке.

Следует обратить внимание, что, например, коду ошибки 21 (который выдается функцией GetLastError пользовательского режима в пользовательских приложениях) соответствует сразу несколько кодов завершения обработки IRP пакетов в драйвере:

Эту особенность неоднозначного соответствия кодов ошибок в пользовательском режиме (system error code) и кодов завершения обработки запросов на ввод/вывод от Диспетчера BB (IRP запросов к драйверу) следует учитывать при выборе соответствующих значений STATUS_Xxx для достоверного информирования клиентов драйвера об ошибочных ситуациях.

Транслировать код ошибки в текстовую форму программно можно при помощи несложной функции, текст которой приведен ниже. Функция получает код ошибки (system error code, например, 21) и выводит текст, расшифровывающий это значение.

#include <winbase.h>
#include <stdio.h>
void PrintErrorMessage(DWORD err)
{
	LPTSTR msg;
	DWORD res= ::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
			FORMAT_MESSAGE_ALLOCATE_BUFFER,
			NULL,
			err,    // код ошибки
			0,      // идентификатор языка по-умолчанию
			(LPTSTR) &msg, 0, NULL);
	if(res == 0) { /* неудача */ }
	else { /* успешное завершение */
		printf("%s",msg);    // вывод сообщения на экран
		LocalFree(msg);     // освобождение буфера с текстом сообщения
	} return;
} 

Программа GuidGen (UUIDGEN)

Программа GuidGen (UUIDGEN — ее консольная версия) выполняет генерацию 128 разрядного уникального ключа (GUID — глобально уникальный идентификатор), который может использоваться для регистрации интерфейса драйвера, в процессе инсталляции и т.п. Вероятность повторения данного значения весьма и весьма низка (хотя и не равна нулю), так что программа GuidGen является типовым инструментом для этих целей. Программа встречается во всех пакетах Microsoft.

Как показано на рисунке 2.4, программа создала GUID в формате, удобном для включения в текст на языке С. Нажав на кнопку "Сору" можно перенести его текст в буфер обмена и вставить в нужное место в тексте программы или драйвера.

Значения GUID можно встретить и в программах, работающих по технологии СОМ, и в Системном Реестре, где они часто используются как идентификаторы классов устройств или входят в состав имен параметров, описывающих устройства.

Рис. 2.4
Программа GuidGen

Программа редактирования Системного Реестра

Программа, без которой не обойтись ни одному разработчику драйвера — программа редактирования Системного Реестра, которая запускается командой Пуск - Выполнить - regedit (в Windows 2000 — командой regedit32). Целостность информации, находящейся в Системном Реестре весьма важна для операционной системы. Поэтому проводить эксперименты над Реестром следует весьма осторожно, поскольку даже резервное копирование Реестра (а также защита отдельных разделов от какого бы то ни было редактирования) может не спасти от необходимости переустановки всей системы. Без достаточной необходимости не следует оставлять изменения, сделанные в Системном Реестре (рекомендуется возвращать его состояние к начальному, имевшему место до экспериментов).

Ниже будет упомянута и еще одна полезная программа по изучению Системного Реестра — RegMon (Registry Monitor)

Программа DeviceTree

В составе Windows DDK поставляется программа DeviceTree (рисунок 2.5), абсолютно незаменимая при самостоятельном изучении WDM модели, поскольку визуализирует представление о стеке драйверов (устройств) в операционной системе Windows.

Данная программа выполняет построение дерева устройств с двух точек зрения: с точки зрения принадлежности объектов устройств драйверам (режим D, рисунок 2.6) и с точки зрения взаимной подчиненности объектов устройств при выполнении операции перечисления устройств, enumeration process (режим P, рисунок 2.7). Программа позволяет отслеживать подчиненность объектов устройств в локальных стеках драйверов, их принадлежность драйверам, выявлять существующие фильтр-драйверы, устанавливать (выяснять) коды IPP пакетов, обслуживание которых объявил драйвер, и некоторую другую специфическую информацию.

Рис. 2.5
Заставка программы DeviceTree

На рисунке 2.6 показан фрагмент дерева устройств на участке шинного драйвера PCI. 11 объектов устройств (за исключением безымянного нижнего) представляют созданные этим шинным драйвером физические объекты устройств (так называемые PDO) для всех имеющихся в системе реальных PCI устройств, включая мосты (PCI-PCI, PCI-ISA), контроллеры USB, AGP адаптер, аудио на материнской плате, PCI адаптер Ethernet и т.п.

Рис. 2.6
Шинный драйвер PCI и его объекты устройств

Другой взгляд на этот же участок драйверного стека приведен на рисунке 2.7. Здесь показана взаимная подчиненность объектов устройств, возникающая в операционной системе при последовательно проводимой переписи устройств. Данное дерево отражает в своей структуре иерархию реальных устройств и очередность их обнаружения драйверами родительских устройств. Например, шинный драйвер PCI обнаруживает подключенные к шине устройства, что приводит к загрузке их драйверов, что, в свою очередь, приводит к обнаружению новых устройств, подключенных к ним — как в случае с шиной USB (ee контроллер является дочерним устройством шины PCI).

Программа DeviceTree является исследовательским инструментом, вносящим большое возмущение в работу системы, поэтому нередки случаи сбоя при некоторых ее операциях (наиболее часто - при выходе из программы).

Рис.2.7
Драйверный стек от ACPI драйвера до шинного драйвера PCI

Программа DevCon

Консольное приложение DevCon из состава вспомогательных утилит пакета DDK позволяет запускать, останавливать драйверы и собирать информацию об отдельных устройствах или их группах. Например, по команде

devcon stack =usb >stack_usb.txt 

(собрать информацию обо всех устройствах в стеке USB) данная утилита выводит в файл stack_usb.txt следующую информацию (немного изменен формат):

PCI\VEN_1106&DEV_3038&SUBSYS_12340925&REV_1A\3&61AAA01&0&3A
Name: VIA Rev 5 USB Setup
Class: {36FC9E60-C465-11CF-8056-444553540000} USB
Controlling service:        usbuhci

PCI\VEN_1106&DEV_3038&SUBSYS_12340925&REV_1A\3&61AAA01&0&3B
Name: VIA Rev 5 USB Setup
Class: {36FC9E60-C465-11CF-8056-444553540000} USB
Controlling service:        usbuhci

USB\ROOT_HUB\4&1E8F7657&0
Name: Setup
Class: {36FC9E60-C465-11CF-8056-444553540000} USB
Controlling service:        usbhub

USB\ROOT_HUB\4&BD5C5B2&0
Name: Setup
Class: {36FC9E60-C465-11CF-8056-444553540000} USB
Controlling service:        usbhub

4 matching device(s) found. 

Программа DevCtl

Консольное приложение DevCtl из состава вспомогательных утилит пакета DDK проводит тестирование драйвера путем применения к нему наиболее употребительных вызовов ввода/вывода пользовательского режима, например NtCreateFile или DeviceIoControl. B процессе тестирования могут быть выявлены серьезные упущения в программировании драйвера, например, некорректная обработка неожиданных (для тестируемого драйвера) IOCTL запросов или запрос на получение данных, когда приложение указало заведомо малый размер буфера для получаемых данных.

В качестве указателя на тестируемый драйвер программе DevCtl следует передавать имя устройства (из числа тех, что видны в директории Device в рабочем окне программы WinObj, описание которой см. ниже). Более подробное описание программы DevCtl можно найти в DDK.

Программы ChkInf и GenInf

Программа ChkInf (точнее, скрипт для интерпретатора Perl) предназначена для проверки inf файлов, необходимых для выполнения установки драйвера в операционной системе, и подробно будет рассмотрена в главе 11.

Программа GenInf предназначена для генерации inf файлов в режиме вопросов и ответов (Wizard).

Программа Task Manager (Диспетчер Задач)

Не следует недооценивать значение использования стандартных системных средств в процессе получения нужных сведений о функционировании приложений, использующих драйверы. Всем известное системное программное средство Диспетчер Задач, вызываемый комбинацией клавиш Ctrl-Alt-Delete, позволяет оперативно получать сведения о работающих процессах (рисунок 2.8). Необходимо лишь в пункте меню "Вид" выбрать интересующие параметры для отображения. Хотя относятся они к приложениям пользовательского режима, могут дать косвенное представление и о работе вызываемых драйверов.

Закладка "Быстродействие" позволяет настроить отображение времени пребывания процесса в режиме ядра (в процентном отношении) — параметр "Вывод времени ядра" в пункте меню "Вид" для этой закладки. По этим показаниям можно оценить, какую часть времени работы приложения занимает обращение к драйверу.

Рис.2.8
Рабочее окно системного Диспетчера Задач

Системный апплет "Производительность"

Более глубоко лежащим средством мониторинга системы и отдельных процессов и служб является апплет "Производительность" системной панели "Администрирование", вызываемой запускающей последовательностью Пуск — Настройка — Панель управления — Администрирование — Производительность.

Рабочее окно данного системного апплета показано на рисунке 2.9. По нажатию правой кнопки мышки появляется меню, допускающее добавление новых графиков в окно работающего апплета ("Добавить счетчики").Сочетание параметров, которые можно просматривать таким образом, настолько велико, что для их описания потребовалась бы отдельная глава. Для просмотра доступны параметры функционирования памяти, процессора, КЭШа, протоколов IP, TCP, UDP, отдельных процессов и сервисов, включая их отдельные потоки, — всего чуть менее полусотни информативных единиц. Для каждой такой единицы возможен просмотр достаточно большого набора счетчиков (как правило, не менее полутора десятков). Например, для процессора среди счетчиков, доступных для просмотра, можно назвать счетчики числа прерываний в секунду, процента времени бездействия, процента времени работы в пользовательском и привилегированном режимах, счетчика DPC процедур, поставленных в очередь, в секунду.

Краткие пояснения, касающиеся смысла указываемых счетчиков, можно получить при выборе счетчика по нажатию кнопки "Объяснение".

Рис. 2.9
Рабочее окно системного Диспетчера Задач

Программное средство тестирования драйвера Driver Verifier

Программа Driver Verifier (последовательность старта Пуск — Программы — Development Kits — Windows DDK — Tools — Driver Verifier) проверяет драйвер на правильность выполнения следующих тестов:

Проверка начинается после перезагрузки системы и при серьезных ошибках в драйвере может привести к необходимости переустановки системы. Поэтому не следует выполнять данные тесты на компьютере с ценными данными.

Программное средство проверки логики функционирования PreFast

Программа PreFast, появившаяся в составе пакета DDK Server 2003, предназначена для выявления ошибочных паттернов (шаблонов) программного кода на уровне исходного текста. Она запускается в качестве наблюдателя за процессом сборки или компиляции какого-либо программного кода и по завершении этого процесса сообщает о дополнительно замеченных ошибочных фрагментах кода (в случае ошибки собственно сборки или собственно компиляции программа PreFast в работу не вступает). Например, компиляция файла запускается под управлением PreFast следующей командной строкой:

> prefast cl /с myfile.cpp
> prefast view 

Вторая строка при удачной компиляции покажет (если таковые имеются) логические ошибки в тексте, представленном в файле myfile.cpp.

Каковы логические ошибки, пропущенные компилятором и выявляемые программой PreFast? Например, в следующем фрагменте

void *ptr1 = malloc(1000);
void *ptr2 = malloc(1000);
if(ptr2 == NULL) return FALSE;   // не выделена область памяти
free(ptr1);
free(ptr2);

программа PreFast выявит потенциально возможную утечку памяти, поскольку возможна ситуация, когда при втором неудачном выделении памяти, не будет освобождена первая, выделенная ранее. То есть произойдет утечка памяти.

На обнаружение такого типа логических ошибок, проявляющихся в пределах кода каждой отдельно взятой функции, и настроена программа PreFast. Количество выявляемых ошибочных паттернов на настоящий момент составляет более трех десятков.

Самым важным недостатком поставки PreFast в пакете DDK Server 2003 сборки 3790 (на данный момент) является то, что поставляемые настройки позволяют работать только с кодом пользовательского режима (хотя и это бывает нужно разработчику драйвера), поскольку распознает только имена функций типа malloc, sprintf и т.п. В режиме ядра, как будет показано позже, используются совершенно другие имена, которые, пока что, выходят за рамки настроек распознавания PreFast.