Microsoft Corporation
July 1998
Summary: Practically no other area of driver development raises more questions for OEMs and IHVs than the customization of the device information files (INFs) used by the Microsoft® Windows NT® operating system to install drivers. Under Windows NT, driver classes are used to identify logical device types (such as display, keyboard, network, or printers) and the associated installation methods and nuances. Windows NT has several subsystems to control various classes of devices and interact with their drivers, and thus there are different installation methods and flavors of INF files for each driver class.
The Windows NT Setup program is responsible for displaying the appropriate dialog boxes or carrying out other installation tasks. With printers, an INF gives Setup full control of the installation process; the INF is not as script-based as the Windows® 3.1 legacy INFs were.
This paper describes some methods and requirements for installing a printer device driver on the Windows NT version 4.0 operating system.
Contents
Printer Installation
Printer INF Files
Printer INF Section Descriptions
How Windows NT 4.0 Setup Works on INF Files
How Port Monitors and Print Processors Are Installed
Registry Entries
Debugging INF Files and Other Installation Problems
Although most other kinds of drivers are installed using Windows NT 4.0 control panel, printers are installed using the AddPrinter wizard in the print folder. Printer driver installation can occur either during or after installing Windows NT.
Installation of drivers that are built into Windows NT 4.0 uses the standard Windows NT printer INF. To see this file and all currently supported printers, look on an installed system for the file %WINNT%\INF\ntprint.inf. For more information about the structure of this file, see the "Printer INFs" section later in this paper.
To be able to install a printer driver, you must provide a distribution disk with items that meet the following requirements:
Oemsetup.inf files use a subset of the GUI INF script language, which you can use to create custom installation and configuration scripts for Windows NT printer device drivers. Windows NT Setup acts as an interpreter and executes the instructions in these text file scripts.
For details about the sections, variables, and operators used in the GUI INF script language, see "Oemsetup.inf Section Descriptions" later in this paper.
In order to install a driver, the driver image file must be copied into the NT_root\system32\driver's directory. Copy all DLL, HLP, or other files into the NT_root\system32 directory.
If you distribute an Oemsetup.inf file with your driver, the installation procedure should copy and rename the driver in the NT_root\system32 directory.
The printer installation methods and samples contained herein provide a way to install printer drivers on a local computer only. Special considerations are necessary for remote installation of printers after the system is installed.
The following differences apply, depending on when the user installs the printer:
When the user runs the Add Printer Wizard to install a printer driver, the operating system runs the Start, Settings, Printers, Add Printer applet.
Although Windows NT 4.0 and Windows® 95 INF files are much the same in their construction and semantics, they differ from the Windows 3.x INF files. Windows NT 4.0 INF files do not contain installation scripts, nor do they have all the same sections as INFs for various Windows versions.
Everything required for installing and loading drivers is included in Windows NT Setup; the INF file just fills in the blanks with control, formatting, and file movement information.
Whether you have a monolithic driver or a minidriver, an INF file must contain one or more sections, and each section must contain one or more items to pass basic sanity checking in Windows NT 4.0 Setup. Each section has a purpose—usually to copy files, make registry entries, or install a service. Approximately 20 different sections can be used in an GUI INF file. However, because printers, like most other driver classes, have their own .inf parser, there is a small subset of possible GUI INF sections that are supported. Extraneous sections are ignored.
Even though INF files might seem complex, they must follow some simple syntactical rules:
A simple generic sample INF file is shown below. It contains sections named [Version], [DestinationDirs], [SourceDisksNames], [SourceDisksFiles], and [Manufacturer]. Each section contains at least one or more items assigning values to some variable. The remainder of this article describes the syntax and meaning of the sections, and provides details about items used in INF files.
It may be useful to note that the INF file on the DDK is %ddk%\src\setup\inf.
; This is a minimal working example for discussion purposes. You will need to carefully
; modify it before it will work with your printer unless modifications are made.
[Version]
Signature="$Windows NT$"
Provider="Microsoft"
ClassGUID={4D36E979-E325-11CE-BFC1-08002BE10318}
Class=Printer
[DestinationDirs]
DefaultDestDir = 66002,spool\drivers\w32x86
PSCRIPT = 66002,spool\drivers\w32x86
SYS32 = 66002
; Here we name the source disk with less than 11 characters.
[SourceDisksNames]
1 = "Postscript"
; Here we enumerate the files on source disk by telling what ordinal (index) number of
; the installation disk set a certain file exists on.
[SourceDisksFiles]
msp.dll = 1
mspp.dll = 1
loaddll.exe = 1
ms.ini = 1
msnps.hlp = 1
msnps.dll = 1
msnpsui.dll = 1
msdrvr.hlp = 1
MyPrintr.ppd = 1
; Manufacturer Specification Section
[Manufacturer]
"Microsoft"
; Model Specifications Section
[Microsoft]
"Postscript Printer Driver" = MYPRINTR.PPD
; Copy File Data
[MYPRINTR.PPD]
CopyFiles=@MYPRINTR.PPD,PSCRIPT,SYS32
DataSection=PSCRIPT_DATA
; Driver files.
[PSCRIPT]
MSNPS.DLL
MSNPSUI.DLL
MSDRVR.HLP
; System files.
[SYS32]
MSP.DLL
LOADDLL.EXE
MSNPS.HLP
MS.INI
MSPP.DLL
; Data Section
[PSCRIPT_DATA]
DriverFile=MSNPS.DLL
ConfigFile=MSNPSUI.DLL
HelpFile=MSDRVR.HLP
For correct driver installation using the above INF example, the distribution disk needs to have the following files on it:
01/18/97 02:28p 1 disk1
01/17/97 02:28p 27,023 msp.dll
01/12/97 02:28p 112,560 msnps.dll
01/31/97 02:28p 87,512 msnpsui.dll
01/03/97 02:28p 27,560 msdrvr.hlp
02/28/97 03:19p 4,564 oemsetup.inf (copy of ms.ini)
02/28/97 11:21a 79,600 loaddll.dll
08/09/96 01:30a 14,234 mspp.dll
02/20/97 01:30p 728,680 msnps.hlp
12/11/96 01:48p 15,657 MyPrintr.ppd
This part of the paper describes the sections and entries that can be included in a printer INF or Oemsetup.inf file.
The [AddRegistry] section adds subkeys or value names to the registry, optionally setting the value. The add-registry-section name must appear in an AddReg= item in an [Install] section.
[add-registry-section]
reg-root-string, [subkey], [value-name], [flags], [value]
reg-root-string, [subkey], [value-name], [flags], [value]
The [ClassInstall32] section installs a new class for a device in the class section of the registry.
[ClassInstall32]
AddReg=add-registry-section[,add-registry-section]...
Copyfiles=file-list-section[,file-list-section]...
Delfiles=file-list section[,file-list-section]...
DelReg=del-registry-section[,del-registry-section]...
Renfiles=file-list-section[,file-list-section]...
UpdateInis=update-ini-section[,update-ini-section]...
UpdateIniFields=update-inifields-section[,update-inifields-section]...
Not all the item types shown in this syntax are needed or required. Typically, a [ClassInstall32] section will use AddReg= items to add a class description and a class icon to the registry.
Every device installed in Windows NT has a class associated with it, even if the class is "Unknown."
Every device installed in Windows NT also has a class installer associated with it. In addition, a [ClassInstall32] section can specify a property provider and exert control over how the class is handled in the user interface.
The [CopyFiles] section lists the files to copy from a source disk to a destination directory. The source disk and destination directory associated with each file are specified in other sections of the INF file. The [file-list-section] name must appear in the CopyFiles= item of an [Install] section.
You can copy a single file with the CopyFiles= item of an [Install] section, without building a [CopyFiles] section.
[file-list-section]
destination-file-name[,source-file-name][,temporary-file-name][,flag]
[destination-file-name[,source-file-name][,temporary-file-name]][,flag]
This example copies two files:
[CopyTheseFiles]
file11 ; copies file11
file31, file32 ; copies file32 to file
A [Delete Registry] section deletes a subkey or value name from the registry. The del-registry-section name must appear in a DelReg= item in an [Install] section.
A [Delete Registry] section can contain any number of items. Each item deletes one subkey or value name from the registry.
[del-registry-section]
reg-root-string, subkey, [value-name]
[reg-root-string, subkey, [value-name]]
A [Delete Files] section lists the files to be deleted. The [file-list-section] name must appear in the DelFiles= item of an [Install] section.
[file-list-section]
file-name[,,,flag]
This example deletes three files:
[DeleteOldFilesSec]
file1
file2
file3
The [DestinationDirs] section defines the destination directories for the operations specified in file-list sections [CopyFiles], [RenameFiles], or [DeleteFiles]. Also, default destination directories can be specified for any [CopyFiles], [RenameFiles], or [DeleteFiles] sections in the INF file that are not explicitly named in the [DestinationDirs] section.
Directory identifiers (DRID) can be used to associate numbers in the INF to specific directories (for example, the Windows home directory has the DRID of 66000). For the list of DRIDs supported by Windows NT Setup, see the Windows NT 4.0 DDK (available through MSDN Professional membership).
On Windows NT, it is possible for installation programs to associate directories with DRIDs at runtime using the API SetupSetDirectoryId. The following section lists the DRIDs that are specific to printer driver INFs.
Syntax for the section is as follows:
[DestinationDirs]
file-list-section=drid[,subdir]
This example sets the default directory for all the sections of the INF file to the driver's directory:
[DestinationDirs]
DefaultDestDir = 66000
Note:
Files in the directory assigned to the DRID of 66002 are copied to the System32 subdirectory when printer drivers for the native architecture are being installed on the local system, such as when x86 drivers are installed locally on an x86 system. Files in this directory are ignored if a driver is being installed to a remote system, or if the drivers are not native, such as Alpha files on an x86 system.
A printer driver is installed when the printer class installer calls the spooler's AddPrinterDriverEx function. This function requires all driver files to be located in the directory that is returned by the GetPrinterDriverDirectory function; otherwise, installation fails.
The [Device] section gives the device description, identifies the [Install] section, and specifies the device identifier for a device. Optionally, a [Device] section can specify one or more device identifiers of compatible devices.
There can be one or more items in the [Device] section, depending on how many devices the INF file installs for a manufacturer.
[device-section]
device-description=install-section-name,device-id[,compatible-device-id]
[device-description=install-section-name,device-id[,compatible-device-id]
Not all the types of items shown in the syntax are needed or required in an [Install] section. Section names must consist of printable characters. More than one section name can be listed in an item; each additional name must be preceded by a comma. Items must specify the name of the corresponding section in the INF file. The only exception is the CopyFiles= item, which need not specify a section if only one file is being copied.
You can use a special notation in the CopyFiles= item to copy a single file directly from the CopyFiles= line. An individual file can be copied by prefixing the file name with an @ symbol. The destination for any file copied using this notation is the DefaultDestDir= as defined in a [DestinationDirs] section.
By appending an extension to the name of the [Install] section, you can have different [Install] sections for different operating systems or platforms if necessary. The setup functions recognize the following extensions:
.nt | Windows NT (all platforms) |
.ntx86 | Windows NT (x86 only) |
.ntalpha | Windows NT (Alpha only) |
The extensions are not case sensitive. The following example [Install] section consists of a single line that lists one file and 3 CopyFiles= sections. The data section registers file types:
[MYPRINTR.PPD]
CopyFiles=@MYPRINTR.PPD,PSCRIPT,SYS32
DataSection=PSCRIPT_DATA
[SYS32]
MSP.DLL
LOADDLL.EXE
MSNPS.HLP
MS.INI
MSPP.DLL
; Data Section
[PSCRIPT_DATA]
DriverFile=MSNPS.DLL
ConfigFile=MSNPSUI.DLL
HelpFile=MSDRVR.HLP
; Data Section
[PSCRIPT_DATA]
DriverFile=MSNPS.DLL
ConfigFile=MSNPSUI.DLL
HelpFile=MSDRVR.HLP
Entries in this section are used to move lines or sections from an INF file to the registry, creating or replacing a registry entry under the specified key in the registry. The section name ini-to-registry-section must appear in an Ini2Reg= item in an [Install] section of the INF file.
[ini-to-registry-section]
ini-file, ini-section, [ini-key],reg-root-string,subkey
The [Manufacturer] section identifies a manufacturer of a device that can be installed using the INF file and lists a [Device] section that describes the device.
[Manufacturer]
manufacturer-name | %strings-key%=device-section-name
The following example shows a typical [Manufacturer] section:
[Manufacturer]
%Microsoft%=Microsoft
The [SourceDisksFiles] section names the source files used during installation and identifies the source disks that contain the files. In order to allow multi-platform distribution of source files, you can construct a platform-specific [SourceDisksFiles] section.
For example, all Setup functions that use a [SourceDisksFiles] section will first look for a [SourceDisksFiles.alpha] section on an Alpha platform and only look in a [SourceDisksFiles] section if the line was not found in [SourceDisksFiles.alpha]. This behavior affects any Setup function that directly or indirectly references a [SourceDisksFiles] section as part of its processing.
[SourceDisksFiles]
filename=disk-number[,subdir][,size]
The following example [SourceDisksFiles] section identifies a single source file, SRS01.x86, on the disk with the ordinal of 1.
[SourceDisksFiles]
msp.dll = 1
mspp.dll = 1
loaddll.exe = 1
ms.ini = 1
msnps.hlp = 1
dmsnps.dll = 1
msnpsui.dll = 1
msdrvr.hlp = 1
MyPrintr.ppd = 1
The [SourceDisksNames] section identifies and names the disk that contains the source files for file copying and renaming operations. In order to allow multi-platform distribution of source files, you can construct a platform-specific [SourceDisksNames] section. This name must be 11 characters or less.
For example, all Setup functions that use a [SourceDisksNames] section will first look for a [SourceDisksNames.alpha] section on an Alpha platform and only look in a [SourceDisksNames] section if the line was not found in [SourceDisksNames]. This behavior affects any Setup function that directly or indirectly references a [SourceDisksNames] section as part of its processing.
[SourceDisksNames]
disk-ordinal="disk-description",tag-file,unused[,path]
The following are examples of how this section is used.
[SourceDisksNames]
1 = "Postscript"
[SourceDisksNames]
1 = "WinNT CDROM", file.tag,,\common
[SourceDisksNames.x86]
2 = "WinNT CD-ROM", file.tag,, \i386
[SourceDisksFiles.ntalpha]
halnecmp.dll = 2
The [Strings] section defines one or more strings keys. A strings key is a name that represents a string of printable characters. Although the [Strings] section is usually the last section in an INF file, a strings key defined in a [Strings] section can be used anywhere in the INF file that uses the string. The installer expands the string key to the specified string and uses it for further processing. When a strings key is used, it must be enclosed by percent signs (%).
[Strings]
strings-key=value
The [Strings] section simplifies translation of strings for international markets by placing all strings that can be displayed in the user interface in a single section of the INF file. Strings keys should be used whenever possible. The following example shows the [Strings] section of an INF file.
[Strings]
String0="Microsoft Corporation"
String1="Printer Driver"
String2="Model X"
The [UpdateIniFields] section replaces, adds, and deletes fields in the value of an INI file entry. Unlike an [UpdateIniFile] section, this type of section replaces, adds, or deletes portions of a value in an INI file entry rather than the whole value. The section name [update-inifields-section-name] must appear in the [UpdateIniFields] item in an [Install] section of the INF file.
[update-inifields-section-name]
ini-file,ini-section,profile-name,[old-field],[new-field],[flags]
The [UpdateIniFile] section replaces, deletes, or adds complete entries in the INI file. The section name, [update-ini-section-name] must appear in the UpdateIni= item in the [Install] section of the INF file.
[update-ini-section-name]
ini-file,ini-section,[old-ini-entry],[new-ini-entry],[flags]
The following examples illustrate individual items in an [UpdateIniFile] section:
%11%\sample.ini, Section1,, Value1=2 ; adds new entry
%11%\sample.ini, Section2, Value3=*, ; deletes old entry
%11%\sample.ini, Section4, Value5=1, Value5=4 ; replaces old entry
The [Version] section is the standard header for all Windows NT 4.0 INF files. Each INF file must contain a [Version] section identifying it as a Windows NT 4.0 compatible file. The following explains what values should be associated with the keys in the [Version] section.
For Windows NT, this field can only be "$Windows NT$"
This field should be Printer.
The ClassGUID field is optional and is only used on Windows NT. The GUID for the printer class is {4D36E979-E325-11CE-BFC1-08002BE10318}.
Identifies the creator of the INF file. Typically, this is the name of the organization that creates the INF file.
This field is optional. If specified, this field gives the name of an INF file that contains layout information (source disks and files) required for installing this driver software. If LayoutFile key is not specified, the [SourceDisksNames] and [SourceDisksFiles] sections must be included in the INF file. Printer drivers requiring some files from the Windows NT CD for installation can include Layout.inf with the key LayoutFile.
The following example shows a typical [Version] section:
[Version]
Signature="$Windows NT$"
Class=Printer
ClassGUID={4D36E96F-E325-11CE-BFC1-08002BE10318}
Provider=%Provider%
LayoutFile=layout.inf
Printer drivers are installed by calling the spooler Win32 API AddPrinterDriver(). Spooler requires all printer driver files to be present in the directory returned by the GetPrinterDriverDirectory() on an AddPrinterDriver() call. Printer driver INFs should be written such that, upon installation of printer drivers, all the required files are copied to this directory.
The Print folder uses the DRIVER_INFO_3 structure with the AddPrinterDriver() call. DRIVER_INFO_3 fields should be specified by using the rules explained in this section. Print folder parses the INF to determine the DRIVER_INFO_3 fields prior to the AddPrinterDriver call.
To reduce the size of an INF file, an INF that lists drivers for multiple printer models can use a data section, identified by DataSection= to list common files shared among multiple models.
The following explains how each field is parsed from the INF file:
The model name used in the INF file is used as the pName field.
The driver file can be specified using the key DriverFile in the [Driver] section or the optional data section. If the DriverFile key is not found, by default the driver file is the same as the [Driver] section name.
The data file can be specified using the key DataFile in the [Driver] section or the optional data section. If the DataFile key is not found, by default the data file is the same as the [Driver] section name.
The configuration file can be specified using the key ConfigFile in the [Driver] section or the optional data section. If the ConfigFile key is not found, by default the config file is the same as the [Driver] file (for example, pDriverPath).
The help file can be specified using the key HelpFile in the [Driver] section or the optional data section. If the HelpFile key is not found, by default the help file field is NULL.
The dependent files field is generated slightly differently on Windows 95 and Windows NT 4.0
Every file that is specified in the driver section to be copied during driver installation is added as a dependent file. The list of files that must be copied is given with the key CopyFiles.
Language monitors are specified with the key LanguageMonitor in the [Driver] section or the optional data section. If the LanguageMonitor field is not found, by default the monitor name field is NULL. The value specified with this key is of the form <MonitorName>, <DLL-name>.
The default data type can be specified using the key DefaultDataType in the [Driver] section or the optional data section. If the DefaultDataType key is not found, then the default data type field is NULL.
Printers are added using the spooler Win32 API AddPrinter() with PRINTER_INFO_2. Printer manufacturers who need other printing components, such as port monitors or print processors, to be used with their driver can do so by following the rules specified in the following section.
When adding a printer, the Print folder will use the arguments specified in the INF for the AddPrinter() call.
In Windows 95, a port monitor could be specified using the key PortMonitor. Windows NT does not work this way, because on Windows NT you have to select a port before selecting a printer driver.
Not supported on Windows NT 4.0.
Device drivers can use the registry to store a variety of information. In general, printer drivers should not make use of the registry to store data that is to be maintained across system boots. The printer tree of interest in the NT registry is the following:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Printers
You should not store information about your printer driver or tamper with the registry, except as modified by AddPrinter. Use the GetPrinterData and SetPrinterData functions for this purpose.
When problems occur, a dialog box will usually display with the message: "Unknown Printer Driver." Use the debugger with a checked build of NT, and examine the messages and line numbers emitted by the Setup.cxx program, which contains the AddPrinter function. Because INF files are not procedural, it does no good to know what line of the INF you are quitting on—you need to know why setup rejected the request and modify your INF accordingly. Problems can only be resolved with certainty using the debugger.
Beware of repeat installs. Uninstalling a driver does not remove the registry entries made; this needs to be done manually. Ensure that all files related to the driver are deleted, and reboot before trying again. (Hint: If you keep getting the same problem over and over—make sure you are doing this—you must get the computer back to a known state before running AddPrinter wizard again.)
Common problems include:
-------------------------------------------
Disclaimer for Working Documents
The information contained in this document represents the current view of Microsoft Corporation of the issues discussed as of the date of publication. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information presented after the date of publication.
This document is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS DOCUMENT.