From Sample Code to Production Driver

Updated: May 13, 2008

The Windows Driver Kit (WDK) contains a wide variety of sample drivers that demonstrate useful techniques for driver development. You can use these samples as a basis for your own drivers, but before you release the driver, you must change certain device-specific aspects of the sample - beyond the obvious operational code - to uniquely apply to your own device and driver. Driver writers sometimes overlook these details.

The exact items that you must change vary from one sample to the next, but in general, they identify a specific device, interface, or driver. For example, if the sample driver contains any of the following items, you must change them to apply to your driver and device:

  • Globally unique identifiers (GUIDs)

  • Symbolic link names

  • Device object name

  • Pool tags

  • I/O control code (IOCTL) definitions

  • User-mode driver framework (UMDF) driver object class ID

  • Names of any files that are copied to the system folder

  • Plug and Play device ID, hardware ID, and compatible IDs

  • Driver service name

  • Device description

  • Resource file

Forgetting to make these changes can result in failed installation, conflicts with other devices and drivers on the system, and difficulties in debugging, along with other errors.

GUIDs. Drivers use GUIDs to identify device setup classes, device interface classes, custom PnP events, custom Windows Management Instrumentation (WMI) events, and Windows PreProcessor (WPP) trace providers. Some GUIDs are defined by Microsoft, and others are defined by device and driver vendors.

Device setup class GUIDs, device interface class GUIDs, and WMI GUIDs for common devices and WMI data are defined in the WDK or in public header files for use by any driver. You should not change these GUIDs. For example, if you are implementing a mouse, you would continue to use GUID_DEVINTERFACE_MOUSE, which is defined in the WDK Ntddmou.h header file, as the device interface class.

However, if you define a new device setup class, you must generate a new device setup class GUID and setup class name, and possibly a new device interface class GUID as well. The setup class GUID and the device interface class GUID must be unique values; they cannot share a GUID.

For most sample-based drivers, you should change only the GUIDs that are defined in a sample's local header or source file and are thus specific to the sample. Such GUIDs might include the following:

  • Custom PnP events

  • Custom WMI events

  • Device interface classes for new or custom devices

  • WPP trace providers

Using a GUID that has been defined for another driver can cause conflicts if both drivers are loaded on the same system. For example, if two different drivers use the same GUID to register a device interface, clients that try to open the device interface might inadvertently open the wrong device.

The following excerpt is from the Driver.h file that is included in all of the Toaster driver samples. It defines the device interface GUID for Toaster devices:

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

If you use this file in your own driver, make sure that you replace the sample GUID (shown above on lines 2-3) with the interface GUID for your own device. To create a GUID, use the Create GUID tool in Microsoft Visual Studio or use Uuidgen.exe or Guidgen.exe, both of which are included in the Microsoft Windows Software Development Kit (SDK). You can then associate the GUID with a symbolic constant in the driver header file, as the example shows.

You might also be required to create new GUIDs for the driver's WMI events. The Toaster driver samples define the following GUID for notification of toaster device arrival:

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

You should create a new GUID for each WMI event in your driver.

If the sample driver uses WPP software tracing, generate a new trace provider GUID for any drivers that you base on the sample. For example, the Osrusbfx2 sample's Trace.h header file in %WinDDK%\Src\Kmdf\Osrusbfx2\Final defines a control GUID as follows:

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

In your own driver, you would replace the text in line 3 with a driver-specific name and the GUID that you created.

Symbolic Link Names. If the sample defines a symbolic link name, replace the name in the sample with a name that applies to your own driver. However, do not change well-known link names such as \DosDevices\COM1. In general, if the link name is quite similar to the sample name—such as \DosDevices\CancelSamp—you should change it. Using the same symbolic link as another driver has the same effect as using the wrong device interface GUID, because device interfaces are essentially symbolic links.

The KMDF Toaster Filter driver in %WinDDK\Src\Kmdf\Toaster\Filter creates a symbolic link name that uses a string defined as follows in the Filter.h header file:

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

Change the “ToasterFilter” string to a string that more accurately describes your own driver.

Device Object Name. If the sample creates a name for the device object, you must change the name when you adapt the sample code.

The KMDF Toaster Filter driver names its device object in the Filter.h header file as follows:

  1. #define NTDEVICE_NAME_STRING L\\Device\\ToasterFilter

As with the symbolic link name, you should change the string to describe your driver.

Remember that named device objects can represent a security risk. Physical device objects (PDOs) must have names, and most such names are system generated instead of explicitly assigned by a driver. Other device objects should be named only if they represent control device objects, which are used for sideband communication between an application and a driver. Both the kernel-mode driver framework (KMDF) and the Windows Driver Model (WDM) enable you to let Windows generate the name. This approach ensures that the name of the device object is unique and that unprivileged users cannot access it. For details, see the WDK.

Pool Tags. A pool tag is a one- to four-character literal that identifies a specific memory allocation and can aid in debugging.

Many of the sample drivers define a pool tag in the driver header file, as in the following line from Toaster.h:

  1. #define TOASTER_POOL_TAG (ULONG) 'saoT'

The driver defines the tag backward because the debugger displays it in reverse order. Thus, this tag appears as ‘Toas' in debugger output. Instead of using the tag that the sample defines, change the string to uniquely identify your own code.

The Pooltag.txt file lists the pool tags used by kernel-mode components and drivers that are supplied with Windows. Pooltag.txt is installed with the WDK in %winddk%\Tools\Other\platform\Poolmon, where platform is amd64, i386, or ia64. Do not use any of the tags that appear in this list.

IOCTL Definitions. Change any sample-defined I/O control codes to use a name, device type, function code, transfer type, and access type that are appropriate for your device and driver.

For example, the Osrusbfx2 sample includes the following definition for IOCTL_OSRUSBFX2_READ_SWITCHES:

  1. #define IOCTL_OSRUSBFX2_READ_SWITCHES
  2. CTL_CODE(FILE_DEVICE_OSRUSBFX2, \
  3. IOCTL_INDEX + 6, \
  4. METHOD_BUFFERED, \
  5. FILE_READ_ACCESS)

A sample-based driver for a different device would require modifications to this definition.

UMDF Driver Object Class ID. If you use a UMDF sample, you must change the class ID for the driver object. This value is typically defined as MYDRIVER_CLASS_ID in the Internal.h header file, although a few samples define it in a different header file.

The following example is from the Skeleton driver's Internal.h header file. You can find this file in %WinDDK\Src\Umdf\Skeleton.

  1. #define MYDRIVER_CLASS_ID { 0xd4112073, 0xd09b, 0x458f, \
  2. { 0xa5, 0xaa, 0x35, 0xef, 0x21, 0xee, 0xf5, 0xde } }

If you base a driver on the Skeleton sample, you would change the definition shown above so that it contains the unique class ID for your driver object.

File Names. In the INF or INX, change the names of the driver, the vendor-supplied co-installer, and any other files that the installation procedure copies to the system folder. These file names typically appear in the [SourceDisksFiles] and [ClassInstall32] sections of the INF and in CopyFiles entries.

The following example is from the INX file for the KMDF Featured Toaster sample, which is available in %WinDDK%\src\kmdf\Toaster\Func\Featured. Change the"tostrcls.dll" file name and the "ToasterClassInstaller" string that are shown on lines 7 and 11:

  1. [ClassInstall32]
  2. Addreg=ToasterClassReg
  3. CopyFiles=ToasterClassInstallerCopyFileshighlight
  4. [ToasterClassReg]
  5. ...
  6. HKR,,Installer32,,"tostrcls.dll,ToasterClassInstaller"
  7. ...
  8. [ToasterClassInstallerCopyFiles]
  9. tostrcls.dll
  10. ...

To adapt this part of the file for a different driver, you would change "tostrcls.dll" to the file name of your class installer and change the "ToasterClassInstaller" string to describe your own installer. These changes ensure that the installation procedure copies the correct co-installer file and that the registry key records the correct file name.

Do not change the name of co-installers that are supplied in the WDK or with Windows, such as the KMDF, UMDF, and WinUSB co-installers.

Additional changes are required later in the file's Device Install section, as shown in this example:

  1. [Toaster_Device.NT]
  2. CopyFiles=Toaster_Device.NT.Copy
  3. [Toaster_Device.NT.Copy]
  4. wdffeatured.sys

In this example, you would change the file name, “wdffeatured.sys”, to the name of your generated driver file.

When Setup copies the INF and driver catalog files, it renames them, so you are not strictly required to change their names in your driver package. However, it's generally a good idea to ensure that the INF and catalog file names are similar to the driver file name.

PnP Device ID, Hardware ID, and Compatible IDs. Setup uses the device ID along with hardware IDs and compatible IDs to select the INF to use for device installation.

The device ID is a vendor-defined string that uniquely identifies a specific device. Every device has exactly one device ID. The bus driver reports the device ID during enumeration, and Setup uses it to match the device with the correct INF file. The device ID is defined in the [Manufacturer] section of the INF.

The following example shows the device ID for the OSR USB Fx2 device on lines 7 and 13, as specified in the Osrusbfx2.inx file:

  1. [Manufacturer]
  2. %MfgName%=Microsoft,NT$ARCH$
  3. ; For Win2K
  4. [Microsoft]
  5. %USB\VID_045E&PID_930A.DeviceDesc%=osrusbfx2.Dev,
  6. USB\VID_0547&PID_1002
  7. ...
  8. ; For XP and later
  9. [Microsoft.NT$ARCH$]
  10. %USB\VID_045E&PID_930A.DeviceDesc%=osrusbfx2.Dev,
  11. USB\VID_0547&PID_1002

To adapt this INF directive for your own driver, replace the device ID (USB\VID_0547&PID_1002) with the device ID for your own device. You should also change the manufacturer name to the name of your company.

The hardware ID and compatible ID are less specific IDs that Setup uses if it cannot match the device ID to an INF. If your INF can support other devices, you should change these values in addition to the device ID. The following example from the KMDF Featured Toaster driver shows a hardware ID on lines 9 and 14:

  1. [Manufacturer]
  2. %StdMfg%=Standard,NT$ARCH$
  3. ; For Win2K
  4. [Standard]
  5. ; DisplayName Section DeviceId
  6. ; ----------- ------- --------
  7. %ToasterDevice.DeviceDesc%=Toaster_Device,
  8. {b85b7c50-6a01-11d2-b841-00c04fad5171}\MsToaster
  9. ; For XP and later
  10. [Standard.NT$ARCH$]
  11. %ToasterDevice.DeviceDesc%=Toaster_Device,
  12. {b85b7c50-6a01-11d2-b841-00c04fad5171}\MsToaster

To adapt this INF directive for your own driver, replace the hardware ID with the device ID of your driver and change "MsToaster" to a more descriptive string.

Driver Service Name. Update the service name in the AddService directive in the INF to a value that is appropriate for your driver. If the driver service name conflicts with that of another driver on the system, the driver will not install or load.

The KMDF Featured Toaster driver names its service as follows:

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

The service name is the first entry in the AddService directive.In the example above, the service name is “wdffeatured”. To adapt the Featured Toaster's INF, you would change “wdffeatured” to a string more suitable for your driver. In the example, the wdffeatured_Service_Inst entry merely references an INF-defined section, so changing it is not critical.

Device Description. The device description consists of several strings that are typically defined in the [Strings] section of the INF and are used in various places throughout the INF. For example, the KMDF Featured Toaster sample defines the following strings in the WdfFeatured.inx file:

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

To modify this file to install your own driver, you should change the string values in lines 3-8 above to reflect information about your company, device, and driver.

If the company name also appears in a [Manufacturer] section in the INF, you must change the name there, too.

Resource File. Drivers and other components such as sample-specific co-installers also have resource (.rc) files, which define driver-specific strings, including the product name, file version, and company name. Change these strings to appropriate values for your driver package.

What should you do?

Before you release a driver that is based on a WDK sample, replace any sample-specific information in the source files, the INF, and any other resources that you used to create your own driver. The required changes vary from one sample to another, but generally include any information that uniquely identifies the sample driver or its device. The following are typical of the changes you must make:

  • Generate and use GUIDs that are specific to your driver where appropriate.

  • Update the symbolic link name.

  • Update the name of the device object or use an autogenerated name.

  • Use pool tags that identify your driver and do not conflict with any known tags.

  • Define IOCTL codes that are appropriate for your driver and device.

  • Use a unique class ID for a UMDF driver object.

  • Update the names of any files that are copied to the system folder.

  • Insert the correct Plug and Play device ID, hardware IDs, and compatible IDs in the INF.

  • Update the service name of the driver in the INF.

  • Change the device description.

  • Modify any driver-specific strings in the resource file.

For more information:

Books
Developing Drivers with the Windows Driver Foundation, by Penny Orwick and Guy Smith

Driver Tips on the WHDC Web site
Who's Using the Pool?

WDK documentation
Defining and Exporting New GUIDs
Controlling Device Access in Framework-Based Drivers
IoCreateDeviceSecure

Windows SDK
Microsoft Windows Software Development Kit (SDK)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章