Поделиться через


Из примера кода в рабочий драйвер — что изменить в примерах

В этом разделе описываются важные изменения, которые необходимо вносить в пример драйверов WDK перед выпуском драйверов устройств на основе примера кода.

Помимо описанных здесь изменений, все драйверы должны использовать рекомендации, описанные в статье "Создание драйверов в режиме надежного ядра" и рекомендации по разработке драйверов surface Team Driver. Все драйверы также должны соответствовать рекомендациям, указанным в руководстве по безопасности драйверов.

Примеры драйверов WDK — уникальные идентификаторы

Комплект драйверов Windows (WDK) содержит широкий спектр примеров драйверов, демонстрирующих полезные методы разработки драйверов. Эти примеры можно использовать в качестве основы для собственных драйверов, но перед выпуском драйвера необходимо изменить определенные аспекты примера для конкретного устройства , помимо очевидного операционного кода, чтобы уникально применяться к собственному устройству и драйверу. Авторы драйверов иногда упускают из виду эти подробности.

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

  • Глобальные уникальные идентификаторы (GUID)

  • Имена символьных ссылок

  • Имя объекта устройства

  • Теги пула

  • Определения кода управления ввода-вывода (IOCTL)

  • Имена всех файлов, скопированных в системную папку

  • самонастраивающийся идентификатор устройства, идентификатор оборудования и совместимые идентификаторы

  • Имя службы драйверов

  • Описание устройства

  • Файл ресурсов

Забыв внести эти изменения, могут привести к сбою установки, конфликтов с другими устройствами и драйверами в системе и трудностями в отладке, а также других ошибок.

Например, если вы получаете сообщение об ошибке, например ...\toastDrv\kmdf\toastmon\wdftoastmon.inx(18-18): error 1284: Class "Sample" is reserved for use by Microsoft. это означает, что имя "Sample" должно быть изменено на уникальное имя для примера драйвера.

Идентификаторы GUID

Драйверы используют идентификаторы GUID для идентификации классов установки устройств, классов интерфейсов устройств, пользовательских событий PnP, пользовательских событий инструментария управления Windows (WMI) и поставщиков трассировки Windows PreProcessor (WPP). Некоторые идентификаторы GUID определяются корпорацией Майкрософт, а другие определяются поставщиками устройств и драйверов.

Идентификаторы GUID класса установки устройств, идентификаторы GUID класса интерфейса устройства и идентификаторы GUID WMI для общих устройств и данных WMI определяются в WDK или в общедоступных файлах заголовков для использования любым драйвером. Эти идентификаторы GUID не следует изменять.

Например, если вы реализуете мышь, вы будете продолжать использовать GUID_DEVINTERFACE_MOUSE, которая определена в файле заголовка WDK Ntddmou.h в качестве класса интерфейса устройства. Однако если вы определяете новый класс установки устройства, необходимо создать новый GUID класса установки устройства и имя класса установки, а также новый GUID класса интерфейса устройства. Guid класса установки и GUID класса интерфейса устройства должны быть уникальными значениями; они не могут предоставить общий доступ к GUID.

Для большинства примеров драйверов следует изменить только идентификаторы GUID, определенные в локальном заголовке или исходном файле примера, поэтому они относятся к образцу. К таким идентификаторам GUID могут относиться следующие:

  • Пользовательские события PnP

  • Пользовательские события WMI

  • Классы интерфейса устройства для новых или пользовательских устройств

  • Поставщики трассировки WPP

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

Следующий отрывок из файла Driver.h, который включен во все примеры драйвера Тостера. Он определяет GUID интерфейса устройства для устройств Тостера:

DEFINE_GUID(GUID_TOASTER_INTERFACE_STANDARD, \
            0xe0b27630, 0x5434, 0x11d3, 0xb8, 0x90, 0x0, 0xc0, \
            0x4f, 0xad, 0x51, 0x71);
// {E0B27630-5434-11d3-B890-00C04FAD5171}

Если вы используете этот файл в собственном драйвере, замените образец GUID (показанный выше полужирным текстом) идентификатором GUID интерфейса для собственного устройства. Чтобы создать GUID, используйте средство создания GUID в Microsoft Visual Studio или Guidgen.exe, оба из которых включены в пакет средств разработки программного обеспечения Microsoft Windows (SDK). Затем можно связать GUID с символьной константой в файле заголовка драйвера, как показано в примере.

Кроме того, вам может потребоваться создать новые идентификаторы GUID для событий WMI драйвера. Примеры драйверов тостера определяют следующий GUID для уведомления о поступлении устройства тостера:

DEFINE_GUID (TOASTER_NOTIFY_DEVICE_ARRIVAL_EVENT, \
             0x1cdaff1, 0xc901, 0x45b4, 0xb3, 0x59, 0xb5, 0x54, \
             0x27, 0x25, 0xe2, 0x9c);
// {01CDAFF1-C901-45b4-B359-B5542725E29C}

Необходимо создать новый GUID для каждого события WMI в драйвере.

Если пример драйвера использует трассировку программного обеспечения WPP, создайте новый GUID поставщика трассировки для всех драйверов, которые вы используете в примере. Например, файл заголовка Trace.h примера Osrusbfx2 в %WinDDK%\Src\Kmdf\Osrusbfx2\Final определяет GUID элемента управления следующим образом:

#define WPP_CONTROL_GUIDS \
    WPP_DEFINE_CONTROL_GUID( \
           OsrUsbFxTraceGuid,(d23a0c5a,d307,4f0e,ae8e,E2A355AD5DAB), \
        WPP_DEFINE_BIT(DBG_INIT)          /* bit  0 = 0x00000001 */ \
        WPP_DEFINE_BIT(DBG_PNP)           /* bit  1 = 0x00000002 */ \
        WPP_DEFINE_BIT(DBG_POWER)         /* bit  2 = 0x00000004 */ \
        WPP_DEFINE_BIT(DBG_WMI)           /* bit  3 = 0x00000008 */ \
        WPP_DEFINE_BIT(DBG_CREATE_CLOSE)  /* bit  4 = 0x00000010 */ \
        WPP_DEFINE_BIT(DBG_IOCTL)         /* bit  5 = 0x00000020 */ \
        WPP_DEFINE_BIT(DBG_WRITE)         /* bit  6 = 0x00000040 */ \
        WPP_DEFINE_BIT(DBG_READ)          /* bit  7 = 0x00000080 */ \
       )

В собственном драйвере вы замените полужирный текст именем конкретного драйвера и созданным ИДЕНТИФИКАТОРом GUID.

Если пример определяет имя символьной ссылки, замените имя в образце именем, которое применяется к вашему собственному драйверу. Однако не изменяйте известные имена ссылок, например \DosDevices\COM1. В общем случае, если имя ссылки довольно похоже на имя примера (например, \DosDevices\CancelSamp),необходимо изменить его.

Использование той же символьной ссылки, что и другой драйвер, имеет тот же эффект, что и использование неправильного GUID интерфейса устройства, так как интерфейсы устройств по сути являются символьными ссылками.

Драйвер фильтра тостера KMDF в %WinDDK\Src\Kmdf\Тостер\Filter создает символьное имя ссылки, которое использует строку, определенную следующим образом в файле заголовка Filter.h:

#define SYMBOLIC_NAME_STRING     L"\\DosDevices\\ToasterFilter"

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

Имя объекта устройства

Если в примере создается имя объекта устройства, необходимо изменить имя при адаптации примера кода.

Драйвер фильтра тостера KMDF называет его объект устройства в файле заголовка Filter.h следующим образом:

#define NTDEVICE_NAME_STRING      L\\Device\\ToasterFilter

Как и в случае с именем символьной ссылки, необходимо изменить строку, чтобы описать драйвер.

Помните, что именованные объекты устройства могут представлять угрозу безопасности. Объекты физических устройств (PDOs) должны иметь имена, и большинство таких имен создаются системой вместо явного назначения драйвером. Другие объекты устройства должны называться только в том случае, если они представляют объекты управления устройствами, которые используются для взаимодействия между приложением и драйвером. Платформа драйверов в режиме ядра (KMDF) и модель драйвера Windows (WDM) позволяют создавать имя Windows. Этот подход гарантирует, что имя объекта устройства уникально и что непривилегированные пользователи не могут получить к нему доступ. Дополнительные сведения см. в разделе "Управление доступом к пространству имен устройств и управление доступом к устройству" в драйверах KMDF.

Теги пула

Тег пула — это литерал с четырьмя символами, определяющий выделение определенной памяти и помогающий в отладке.

Многие из примеров драйверов определяют тег пула в файле заголовка драйвера, как показано в следующей строке из Тостер.h:

#define TOASTER_POOL_TAG (ULONG) 'saoT'

Драйвер определяет тег назад, так как отладчик отображает его в обратном порядке. Таким образом, этот тег отображается как Toas в выходных данных отладчика. Вместо использования тега, определяемого примером, измените строку на уникальное определение собственного кода.

В файле Pooltag.txt перечислены теги пула, используемые компонентами и драйверами в режиме ядра, предоставляемыми в Windows. Pooltag.txt устанавливается с помощью WDK в %winddk%\Tools\Other<i>platform\Poolmon, где платформа amd64, i386 или ia64. Не используйте ни один из тегов, отображаемых в этом списке.

Определения IOCTL

Измените коды элементов управления ввода-вывода, определяемые примерами, чтобы использовать имя, тип устройства, код функции, тип передачи и тип доступа, подходящий для устройства и драйвера.

Например, пример Osrusbfx2 содержит следующее определение для IOCTL_OSRUSBFX2_READ_SWITCHES:

#define IOCTL_OSRUSBFX2_READ_SWITCHES   
                    CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
                             IOCTL_INDEX + 6, \
                             METHOD_BUFFERED, \
                             FILE_READ_ACCESS)

Пример драйвера для другого устройства потребует изменений в этом определении.

Имена файлов

В INF или INX измените имена драйвера, предоставленного поставщиком совместного установщика, и все другие файлы, скопированные процедурой установки в системную папку. Эти имена файлов обычно отображаются в разделах [SourceDisksFiles] и [ClassInstall32] в записях INF и CopyFiles .

Следующий пример приведен в файле INX для примера тостера KMDF, который доступен в %WinDDK%\src\kmdf\Тостер\Func\Featured. Имена файлов, которые необходимо изменить, отображаются полужирным шрифтом:

[ClassInstall32]
Addreg=ToasterClassReg
CopyFiles=ToasterClassInstallerCopyFileshighlight

[ToasterClassReg]
...
HKR,,Installer32,,"tostrcls.dll,ToasterClassInstaller"
...

[ToasterClassInstallerCopyFiles]
tostrcls.dll									    
...

Чтобы адаптировать эту часть файла для другого драйвера, вы измените "tostrcls.dll" на имя файла установщика класса и измените строку "ТостерClassInstaller", чтобы описать собственный установщик. Эти изменения гарантируют, что процедура установки копирует правильный файл со установщика и записывает правильное имя файла реестра.

Не изменяйте имя совместно используемых установщиков в WDK или Windows, таких как KMDF, UMDF и WinUSB.

Дополнительные изменения требуются позже в разделе установки устройства файла, как показано в этом примере:

[Toaster_Device.NT]
CopyFiles=Toaster_Device.NT.Copy

[Toaster_Device.NT.Copy]
wdffeatured.sys

В этом примере вы измените полужирное имя файла на имя созданного файла драйвера.

Когда программа установки копирует файлы КАТАЛОГА INF и драйверов, они переименовываются, поэтому вам не требуется изменять их имена в пакете драйверов. Однако обычно рекомендуется убедиться, что имена файлов INF и каталога похожи на имя файла драйвера.

Идентификатор устройства PnP, идентификатор оборудования и совместимые идентификаторы

Программа установки использует идентификатор устройства вместе с аппаратными идентификаторами и совместимыми идентификаторами, чтобы выбрать INF-файл, используемый для установки устройства.

Идентификатор устройства — это определяемая поставщиком строка, которая однозначно идентифицирует конкретное устройство. Каждое устройство имеет ровно один идентификатор устройства. Драйвер шины сообщает идентификатор устройства во время перечисления, и программа установки использует его для сопоставления устройства с правильным INF-файлом. Идентификатор устройства определен в разделе [Производитель] INF.

В следующем примере показан идентификатор устройства ДЛЯ устройства OSR USB Fx2, как указано в файле Osrusbfx2.inx:

[Manufacturer]
%MfgName%=Microsoft,NT$ARCH$

; For Win2K
[Microsoft]
%USB\VID_045E&PID_930A.DeviceDesc%=osrusbfx2.Dev, 
        USB\VID_0547&PID_1002
...

; For XP and later
[Microsoft.NT$ARCH$]
%USB\VID_045E&PID_930A.DeviceDesc%=osrusbfx2.Dev, 
        USB\VID_0547&PID_1002

Чтобы адаптировать эту директиву INF для собственного драйвера, замените идентификатор устройства, отображаемый полужирным шрифтом, идентификатором устройства для собственного устройства. Вы также должны изменить имя производителя на имя вашей компании.

Идентификатор оборудования и совместимый идентификатор являются менее конкретными идентификаторами, которые программа установки использует, если она не может соответствовать идентификатору устройства с INF. Если inf может поддерживать другие устройства, эти значения следует изменить в дополнение к идентификатору устройства. В следующем примере из драйвера тостера KMDF показан идентификатор оборудования:

[Manufacturer]
%StdMfg%=Standard,NT$ARCH$

; For Win2K
[Standard]
; DisplayName                   Section           DeviceId
; -----------                   -------           --------
%ToasterDevice.DeviceDesc%=Toaster_Device, 
         {b85b7c50-6a01-11d2-b841-00c04fad5171}\MsToaster

; For XP and later
[Standard.NT$ARCH$]
%ToasterDevice.DeviceDesc%=Toaster_Device, 
         {b85b7c50-6a01-11d2-b841-00c04fad5171}\MsToaster

Чтобы адаптировать эту директиву INF для собственного драйвера, замените идентификатор оборудования идентификатором драйвера и измените msToaster на более описательную строку.

Имя службы драйверов

Обновите имя службы в директиве AddService в INF до значения, подходящего для драйвера. Если имя службы драйверов конфликтует с именем другого драйвера в системе, драйвер не установит или не загружается.

Драйвер KMDF Featured Тостер называет свою службу следующим образом:

[Toaster_Device.NT.Services]
AddService = wdffeatured, %SPSVCINST_ASSOCSERVICE%,
     wdffeatured_Service_Inst
      

Имя службы — это первая запись в директиве AddService . Чтобы адаптировать inf-файл "Избранный тостер", вы измените полужирную строку на строку, более подходящую для драйвера. В примере запись wdffeatured_Service_Inst просто ссылается на определенный INF-раздел, поэтому изменение не является критическим.

Описание устройства

Описание устройства состоит из нескольких строк, которые обычно определены в разделе [Strings] INF и используются в различных местах в INF. Например, пример компонента KMDF Тостер определяет следующие строки в файле WdfFeatured.inx:

[Strings]
SPSVCINST_ASSOCSERVICE   = 0x00000002
MSFT                     = "Microsoft"
StdMfg                   = "(Standard system devices)"
ClassName                = "Toaster"
DiskId1                  = "Toaster Device Installation Disk #1"
ToasterDevice.DeviceDesc = "Microsoft WDF Featured Toaster"
Toaster.SVCDESC          = "Microsoft WDF Toaster Featured Device Driver"

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

Если имя компании также отображается в разделе [Производитель] в INF, необходимо также изменить имя там.

Файл ресурсов

Драйверы и другие компоненты, такие как примеры со установщиков, также имеют файлы ресурсов (RC), определяющие строки, относящиеся к драйверу, включая имя продукта, версию файла и название компании. Измените эти строки на соответствующие значения для пакета драйвера.

Сводка- Что делать?

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

  • Создайте и используйте идентификаторы GUID, относящиеся к вашему драйверу, если это необходимо.

  • Обновите имя символьной ссылки.

  • Обновите имя объекта устройства или используйте автоматическое имя.

  • Используйте теги пула, которые определяют драйвер и не конфликтуют с известными тегами.

  • Определите коды IOCTL, соответствующие драйверу и устройству.

  • Обновите имена всех файлов, скопированных в системную папку.

  • Вставьте правильный идентификатор устройства самонастраивающийся, идентификаторы оборудования и совместимые идентификаторы в INF.

  • Обновите имя службы драйвера в INF.

  • Измените описание устройства.

  • Измените все строки, относящиеся к драйверу, в файле ресурсов.

  • Соблюдение рекомендаций по обеспечению безопасности и надежности

Дополнительная информация

Книги

Разработка драйверов с помощью Windows Driver Foundation, Пенни Орвик и Гай Смит

Разделы WDK

Определение и экспорт новых идентификаторов GUID

Управление доступом к устройству в драйверах KMDF

Разработка, тестирование и развертывание драйверов

Создание драйверов в режиме надежного ядра

Рекомендации по разработке surface Team Driver

Руководство по безопасности драйверов

Написание первого драйвера