Last month, I began this three-part series about enhancements in Windows 2000 (Win2K) that improve the OS's reliability. This month, I describe Win2K features that Microsoft designed to eliminate the necessity of using recovery tools. These features include driver signing, system file protection, and a powerful tool called the Driver Verifier that I'll focus on next month, in Part 3.
As I mentioned last month, buggy device drivers are the leading cause of instability in Windows NT 4.0. Microsoft's Hardware Compatibility List (HCL) lists devices with their drivers that hardware vendors submit to Microsoft for testing; the devices on the HCL have passed numerous stress tests. Although device drivers for the hardware devices on the HCL aren't guaranteed to be bug-free, you are less likely to run into problems with them than with drivers that haven't passed through Microsoft HCL testing.
Even if you intend to keep non-HCL drivers off your system, you might not remember to check the HCL when you add a device. And if you stay current with a hardware vendor's latest drivers, you can find yourself at odds with the HCL: A device's original driver might be on the HCL, but the driver's update might not be. (For example, if a vendor rewrote a driver to get better performance, the driver update might include new bugs.) In addition, several systems administrators might manage a given system, which makes policing driver installation virtually impossible.
To help you keep your system loaded exclusively with drivers from the HCL, Microsoft introduced driver-signing technology into Win2K. Microsoft Internet Explorer (IE) has had support for Authenticode signing of ActiveX controls for several years, so you can configure IE to ask for approval before downloading a control. By checking a control's signature, IE can determine whether the control is signed and which company published the control. Driver signing in Win2K is virtually the same technology applied to device driver files. Because Microsoft signs only the drivers that the HCL lists, Win2K knows that when it doesn't find a valid signature for a driver, the driver is non-HCL.
Screen 1, page 56, shows the Driver Signing Options dialog box, which you access from the Hardware tab of the System applet in Control Panel. Using this dialog box, you can direct Win2K to react to a non-HCL driver in one of several ways. You can set Win2K to always install unsigned drivers without notice. (This behavior exists in NT 4.0.) Or, you can set Win2K to either ask to in-stall unsigned drivers or never install unsigned drivers.
What does it mean when Microsoft signs a driver? The first step the company takes when it signs a driver is to generate a hash of the driver file. This hash is a relatively short number that uniquely identifies a file's contents—no two driver files will have the same hash. Microsoft then has VeriSign (a company that provides digital authentication services) encrypt the hash with VeriSign's private key. The encrypted hash is the driver's signature, and it ships with the device driver. Anyone with access to VeriSign's public key can decrypt the encrypted hash. (To learn about private and public keys and digital authentication, see Tao Zhou, "Public Key Infrastructure in Windows 2000," January 1999.) For device drivers that the Win2K CD-ROM includes, Microsoft stores the driver signatures in catalog files that Win2K installs onto an installation's hard disk under \%systemroot%\system32\catroot. Device drivers that OEMs supply ship with the catalog file that Microsoft provides the vendor when the driver passes HCL testing. If you look under the Catroot directory, you'll see two files with the root name sysmast, and a subdirectory with a long name composed of letters and numbers. Sysmast is the master index of catalog files, and the subdirectory contains Win2K's built-in catalog files. Looking into the subdirectory reveals catalog files for different Win2K components. For example, fp.cat is the catalog of signatures for FrontPage's application files. Nt5.cat and nt5inf.cat store the signatures for Win2K system files.
You can install device drivers in Win2K in several ways. The most common way is for Win2K to attempt to install a device driver automatically when the Win2K Plug and Play (PnP) subsystem detects a new device. The user-mode Plug and Play Manager (UMPNPMGR), which \%systemroot%\system32\umpnp mgr.dll implements, waits for the PnP subsystem in the kernel to notify it that the subsystem has detected a new device. When you add a new device, UMPNPMGR locates the device driver's installation information file (INF). The INF is located either under \%systemroot%\INF, for drivers that the Win2K CD-ROM includes, or on the device driver's installation media (a 3.5" diskette or CD-ROM), for OEM drivers. INF files carry the .inf extension and are text files with somewhat complex instructions—including which files to copy from where to where, and what Registry settings to enable— that Win2K follows to install device drivers or software applications. Another way you can install a device driver is to use the Hardware Installation Wizard (HIW), implemented in \%systemroot%system32\newdev.dll. HIW follows steps similar to those UMPNPMGR takes to locate a driver's INF file.
UMPNPMGR and the HIW use services that the Setup API DLL (SETUPAPI—\%systemroot%\system32\setupapi.dll) implements to read in a driver's INF file. SETUPAPI processes instructions for installing a device driver file and checks the HKEY_LOCAL_MACHINE\ SOFTWARE\Microsoft\Driver Signing\Policy Registry value. If this value doesn't exist, SETUPAPI checks HKEY_CURRENT_USER\Software\Microsoft\Driver Signing\Policy. You set these values through the Driver Signing Options dialog box. When you direct the dialog to apply a setting as the administrative default, the dialog sets the Policy value under HKEY_LOCAL_MACHINE; otherwise, the dialog sets the value under HKEY_CURRENT_USER. UMPNPMGR checks the value under HKEY_LOCAL_ MACHINE first; if the value is set, the global policy overrides whatever individual administrators or users configure for their driver-signing policy. The 0 value directs UMPNPMGR to install unsigned drivers, a 1 value directs SETUPAPI to display a warning dialog box that asks a user for permission to install unsigned drivers, and a 2 value directs SETUPAPI not to install unsigned drivers.
If the driver-signing policy dictates that SETUPAPI must check for a signature, SETUPAPI locates the catalog file that corresponds to the driver. Then, SETUPAPI uses the cryptographic services that the CryptoAPI provides to generate a hash for the driver file and decrypts the driver's signature using VeriSign's public key. (For more information about Win2K's CryptoAPI function, see "Inside Encrypting File System, Part 1," June 1999, and "Inside Encrypting File System, Part 2," July 1999.) If the hash that the CryptoAPI generates from the driver file doesn't match the hash that SETUPAPI obtained from the driver's catalog file, or if the driver doesn't have a catalog file, SETUPAPI either asks the user whether driver installation should proceed or causes the installation to fail.
Windows File Protection
When Microsoft polled customers during Win2K's development about what problems caused system instability in NT 4.0 installations, a familiar response was "DLL hell." Many applications include versions of important system DLLs to ensure that the application will execute properly regardless of which versions a system has installed. For example, many applications that developers write to Microsoft Foundation Classes (MFC) C++ object library ship with a copy of mfc42.dll. Microsoft has released several versions of mfc42.dll, and some versions are incompatible with applications that expect a specific version. The DLL version problem even extends to core system DLLs, which some misbehaving applications try to replace.
Win2K introduces Windows File Protection (WFP), which is named System File Protector in Win2K versions earlier than and including Win2K beta 3. WFP acts as a watchdog over most Win2K system files, including DLLs, driver files, font files, INF files, and executable files. When WFP detects a change to one of the files it oversees, WFP updates the changed or removed file with a fresh copy of the original.
When the system starts the Windows Logon subsystem (Winlogon—\%systemroot%\ system32\winlogon.exe) during the boot process, Winlogon loads System File Checker(SFC—\%systemroot%\ system32\sfc.dll), the WFP DLL. SFC exports several functions for Winlogon's use, including SfcInitProt, an initialization function. SfcInitProt first reads SFC Registry settings, all of which are located under HKEY_LOCAL_ MACHINE\SOFTWARE\Microsoft\ Windows NT\CurrentVersion\ Winlogon. The first Registry value SFC reads is SFCDisable. If the SFCDisable value is not set to 0 and a kernel debugger (e.g., WinDbg) is active, then SFC deactivates WFP.
Next, SFC reads the SFCScan value. If the SFCScan value is 1, SFC performs an initial consistency check of the system files after the system finishes initializing. An SFCScan value of 2 directs SFC to perform an initial scan and reset the SFCScan value to 0. The default SFCScan value of 0 directs SFC to protect system files, but not to perform a scan. Win2K provides a command-line tool, sfc.exe, that you can use to manipulate the SFCScan value.
At this point, SFC reads the SfcDllCacheDir Registry value. Then, the last value SFC reads is SFCQuota, a DWORD value. This value specifies in megabytes the maximum amount of file data that SFC will monitor. All the values are optional; that is, if the values don't exist in the Registry, SFC acts as if the values are set to 0, except for the SFCQuota value. If this value doesn't exist, SFC interprets it as -1. The -1 value designates unlimited data for SFCQuota.
After reading the SFC Registry settings, SfcInitProt invokes the function SfcInitializeDllLists. SfcInitializeDllLists proceeds through SFC's internal list of system files that SFC will protect and, if NTFS formats the system drive, verifies that strict security settings apply to the directories in which the files reside. SFC protects about 3000 system files. (You can see a list of the files SFC protects by running sfc.dll through the Strings utility posted at http://www.sysinternals.com /misc.htm.) Figure 1 shows a sample list of directories that contain files that SFC watches. Not every system installs with all the files in SFC's comprehensive list; therefore, the number of files that SFC actually protects on a system might be fewer than 3000. All the files that SFC protects have backup versions stored in \%systemroot%\system32\dllcache, unless the system defines SfcDllCacheDir. Microsoft intended Win2K corporate installations to use SfcDllCacheDir when storing backup files for multiple computers in a common location. SFC treats the value of SfcDllCacheDir, which is a string, as the path to its backup files, and the path can specify a Uniform Naming Convention (UNC) path to a directory on a shared network drive. You can configure SfcDllCacheDir in an unattended installation script's unattended.txt file. However, if SfcDllCacheDir specifies a directory on a network share, the share must grant authenticated users read access before SFC can access the backup files. When SFC replaces a modified system file, SFC first attempts to find a fresh copy of the modified or removed system file in the Dllcache directory.
After SfcInitializeDllLists completes, SfcInitProt calls the SfcBuildDirectoryWatchList function. SfcBuildDirectoryWatchList opens each directory that contains files that SFC watches and keeps the directories open so that SFC can perform change-notification functions on them. Win2K lets applications request system notification of modifications to files that reside within directories that the applications specify. Without this capability, applications would have to periodically check every file in a directory to detect changes. You see the benefits of change-notification when you open a Windows Explorer window, then in a command-prompt window delete or rename a file in the directory you're viewing. Windows Explorer automatically updates itself to reflect the change you made to the directory.
If the SFCScan Registry value specifies that SFC should do so, SFC's next initialization step is to execute an initial verification of the system files. SFCInitProt calls SfcScanProtectedDlls for the verification. SfcScanProtectedDlls loops through the list of protected files that SfcInitializeDllLists compiled and calls SfcValidateDLL for each file. SfcValidateDLL checks the integrity of system files. SFC also uses SfcValidateDLL when SFC detects changes to a system file after the system initializes.
When the optional initial scan of protected files completes, SFC launches its watchdog thread. This thread waits for change-notifications on the directories containing SFC-protected files. When Win2K tells the watchdog thread that an application has modified one or more files the thread is watching, the thread invokes SfcValidateDLL for each file, and the function refreshes each file with an unmodified copy.
SfcValidateDLL in turn invokes the function SfcGetValidationData for modified files. After determining a modified file's version information, SfcGetValidationData uses SfcValidateFileSignature to verify that Microsoft digitally signed the file and that the file's backup file in Dllcache also passes signature verification. The Win2K CD-ROM includes all the files that WFP protects and that Microsoft therefore signs. SfcValidateFileSignature uses several functions from the CryptoAPI, including one function that calculates a hash from a file. After obtaining the file hash, SfcValidateFileSignature uses another CryptoAPI to obtain a reference to the catalog file that contains the hashed file's digital signature.
After SfcValidateFileSignature acquires the file's hash and catalog file, SfcValidateFileSignature invokes WinVerifyTrust, Win2K's digital-signature-verification core function. WinVerify- Trust obtains the file's hash from the catalog after decrypting the catalog's hash with VeriSign's public key. Then, WinVerifyTrust compares the hashes. If the hashes match, WinVerifyTrust reports the file as a signed file. If the file is corrupt, modified, or nonexistent, WinVerifyTrust returns an error, and SfcValidateFileSignature signals that signature verification failed.
Because SfcValidateDLL verifies the signatures of both the file and the backup file that SFC is watching, SfcValidateDLL knows whether an application has modified either file. If a backup file fails verification, SFC must update the backup file before using it to replace the file that the system is using. SFC checks the Registry value HKEY_LOCAL_MACHINE\ SOFTWARE\Microsoft\Windows NT\CurrentVersion\ SourcePath for the location of the Win2K setup files that the user relied on to install Win2K onto the computer. SFC gets a new backup copy from the setup media, but if no media are present (e.g., if the Win2K CD-ROM isn't in the CD-ROM drive), SFC prompts the user to supply the media. If SFC still can't locate a copy of the backup file, or if the user cancels the dialog box that asks the user to insert the media, SFC doesn't update the file and displays the dialog box that Screen 2 shows. SFC uses the Setup API, which \%systemroot%\system32\setupapi.dll exports, to locate and copy files from the installation media.
After SfcValidateDLL ensures that the backup file in Dllcache is up-to-date or copies a fresh backup file from the Win2K installation media, SFC updates the modified system file with the backup version. SFC writes an entry to the System event log that records which system file underwent modification.
In some cases, applications need to install new versions of files that WFP protects, and Win2K must provide a way for them to do so. For example, hotfixes, service packs, an upgrade installation of Win2K, and the Win2K Update facility update system files. Because these programs update only files with versions that Microsoft signs, the programs also update or add catalog files with new file signatures for those files. The programs can then copy the updates over the existing versions. WFP detects these changes but determines that the files are trusted, because WFP matches the signed hashes it obtains from the update file with the hashes in the updated catalog files. At the same time, WFP knows that the update-file hashes differ from the hashes it obtained in its most recent scan; WFP therefore updates Dllcache with the new files. After the update programs have made their changes, a system reboot is necessary so that every component on the system will use the new file versions. No way exists to get an application to use a new system file without shutting down the application and restarting it.
With the protection facility that WFP provides to Win2K systems, you should rarely run into DLL problems. Be aware that WFP is not bulletproof protection of system files, however. Because SFC has a limited buffer for capturing changes, a large number of changes to a directory will cause the buffer to overflow and SFC to drop changes. If you delete all the system files in your \%systemroot%\system32 directory, WFP won't update all the system files that changed as a result, because WFP will be unaware that you deleted many of the files. In this case, you must force WFP to scan the system files by running the SFC command line utility and specifying the /scannow option, or use the repair options that the Win2K installation CD-ROM provides to refresh the system files.
Three Angles of Attack
Microsoft has launched a three-angled attack on reliability problems in Win2K. The first angle of attack provides tools for addressing reliability problems; I discussed these tools in Part 1. This month, I covered the second angle, Win2K's attempts to prevent reliability problems by keeping systems populated with Microsoft-approved system files and drivers. Next month, I'll conclude this three-part series by describing the last angle: developer tools that help developers implement more robust device drivers and help systems administrators pinpoint problematic drivers.