Windows NT 4.0 Installation of Printer Drivers with Device Information Files

Updated: December 4, 2001

Note: Information on printer INF files under Microsoft Windows 2000 is available in the Windows  2000 DDK.

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 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.

On This Page
Printer InstallationPrinter Installation
Printer INF FilesPrinter INF Files
Printer INF Section DescriptionsPrinter INF Section Descriptions
How Windows NT 4.0 Setup Works on INF FilesHow Windows NT 4.0 Setup Works on INF Files
How Port Monitors and Print Processors Are InstalledHow Port Monitors and Print Processors Are Installed
Registry EntriesRegistry Entries
Debugging INF Files and Other Installation ProblemsDebugging INF Files and Other Installation Problems
*

Printer Installation

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 the installation of 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:

Your distribution disk must include an empty file named Disk1 and a text file named Oemsetup.inf that meets the rules summarized in this paper.

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.

All files required for the operation or configuration of a printer device driver are stored in the Windows NT system directory or one of its subdirectories.

In order to install a driver, the driver image file must be copied into the NT_root\system32\drivers 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:

Printer Installation During Setup. After completing the text setup installation phase, Setup boots Windows NT and proceeds with the GUI mode part of Windows NT installation. During this phase, Setup gives the user an opportunity to install printer components.

Printer Installation After Setup. Only a user with administrator privileges can install printer drivers. If a device is added to the hardware configuration that was not present when Windows NT was installed or if the user wants to install a different or updated driver for an existing print device, the user without administrator privileges is prevented from this by Windows NT.

When the user runs the Add Printer Wizard to install a printer driver, the operating system runs the Start, Settings, Printers, Add Printer applet.

Top of pageTop of page

Printer INF Files

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. There are about 20 different sections that can be used in an GUI INF file, but since printers like most other driver classes, have their own .inf parser, there is a small subset of possible GUI INF sections which are supported. Extraneous sections are ignored.

Even though INF files might seem complex, they must follow some simple syntactical rules:

Sections begin with the section name enclosed in brackets, for example: [Section].

Values can be macros expressed as %stringtext%. To use a % character in the string, use %%. The variable stringtext must be defined in a [Strings] section of the INF file.

Each INF file must contain a [Version] section identifying it as a Windows NT 4.0 install file and this version must match the driver .dll defined version.

Each section must contain at least one item that has an equal sign (=) assigning a value.

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
Top of pageTop of page

Printer INF Section Descriptions

This part of the paper describes the sections and entries that can be included in a printer INF or Oemsetup.inf file.

Add Registry Section

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]

ClassInstall32 Section

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.

Copy Files Section

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

Delete Registry Section

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]]

Delete Files Section

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

DestinationDirs Section

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 drivers directory:

[DestinationDirs]
DefaultDestDir = 66000

Note:

66000 represents the path returned by the GetPrinterDriverDirectory function-for driver files.

66001 represents the path returned by the GetPrintProcessorDirectory function-for print processor files.

66002 represents the directory path to additional files to be copied to \system32 of the local system.

66003 represents the directory path returned by the GetColorDirectory function-ICM color profile files.

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.

Device Section

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 upon 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]

Install Section

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 with a comma. Items must specify the name of the corresponding section in the INF file. The only exception to this 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 following extensions are recognized by the Setup functions:

.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

INI File to Registry Section

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

Manufacturer Section

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

SourceDisksFiles Section

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

SourceDisksNames Section

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

Strings Section

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"

Update INI Fields Section

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]

Update INI File Section

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

Version Section

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.

Signature
For Windows NT, this field can only be "$Windows NT$"
Class
This field should be Printer.
ClassGUID
The ClassGUID field is optional and is only used on Windows NT. The GUID for the printer class is {4D36E979-E325-11CE-BFC1-08002BE10318}.
Provider
Identifies the creator of the INF file. Typically, this is the name of the organization that creates the INF file.
LayoutFile
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
Top of pageTop of page

How Windows NT 4.0 Setup Works on INF Files

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 a 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:

pName
The model name used in the INF file is used as the pName field.
pDriverPath
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.
pDataFile
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.
pConfigFile
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).
pHelpFile
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.
pDependentFiles
The dependent files field is generated slightly differently on Windows 95 and Windows NT 4.0
Windows NT 4.0
Every file that is specified in the driver section to be copied during the driver installation is added as a dependent file. The list of files that must be copied is given with the key CopyFiles.
pMonitorName
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>.
pDefaultDataType
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.

Top of pageTop of page

How Port Monitors and Print Processors Are Installed

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.

Port Monitor
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.
Print Processor
Not supported on Windows NT 4.0.

Top of pageTop of page

Registry Entries

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.

Top of pageTop of page

Debugging INF Files and Other Installation Problems

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. Make sure all files related to the driver are deleted too and you 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:

No DISK1 file on distribution disk.

[SourceDisksNames] section names greater than 11 characters.

Missing files referenced by INF file.

Misuse of the Layout= item in [Version] section.

Driver .dll fails on load.

Driver version is wrong. If Setup does not copy into the spool\drivers\w32x86\2 directory then it thinks the driver is the wrong version. If Setup copies it into the ...\1 directory it thinks it's a NT3.51 driver. If it copies it into the ...\0 directory it thinks it's a Win31 driver. If FILE_VERSION or PRODUCT_VERSION defines are wrong or absent setup will think the driver is not an NT4 drive and install will fail.


Top of pageTop of page