OSRLogo
OSRLogoOSRLogoOSRLogo x OSR Custom Development Services
OSRLogo
x

Everything Windows Driver Development

x
x
x
GoToHomePage xLoginx
 
 

    Thu, 14 Mar 2019     118020 members

   Login
   Join


 
 
Contents
  Online Dump Analyzer
OSR Dev Blog
The NT Insider
The Basics
File Systems
Downloads
ListServer / Forum
  Express Links
  · The NT Insider Digital Edition - May-June 2016 Now Available!
  · Windows 8.1 Update: VS Express Now Supported
  · HCK Client install on Windows N versions
  · There's a WDFSTRING?
  · When CAN You Call WdfIoQueueP...ously

Being Resourceful! Creating a Proper Version Information Resource

One of our biggest pet peeves is finding a driver installed on a system, written by a 3rdparty that either doesn’t have a Version-Information resource in the image at all, or has one that is blatantly incorrect.  The most common Version-Information resource error that we see is a 3rdparty containing a Microsoft copyright string (!) as a result of not overriding the default values supplied in the WDK.

This article will discuss what a Version-Information is and how to create one for your driver.

What is a Version-Information Resource

A Version-Information (VI) resource is a type of Resource Compiler (RC) object that provides information about the executable image that contains it.   The information within the VI resource typically includes the executable image’s version number, intended operating system, and original filename.   This information is viewed in Windows Explorer as shown in Figure 1, and also may be retrieved programmatically using the Windows Version Information functions.

 

Figure 1—Version Resource as Viewed from Explorer

The VI resource of an executable is defined by a VERSIONINFO block contained within an RC file (a file with the .RC extension) that is compiled along with the other files that are part of the executable.  In the case of a WDK project, the RC file would be declared as an element in the SOURCES=line of a project’s sourcesfile.

For readers unfamiliar with an RC file, it is a resource-definition script file (in text format) that describes the resources used by your executable object.   For applications, these objects can be cursors, icons, bitmaps, dialog boxes, fonts, version-information, strings, or user-definable objects.  For drivers, only the version-information is typically specified in the RC file.

For the purposes of defining a VI resource for a driver, the definitions needed to compile the RC file can be satisfied by including winver.h.   The RC file is compiled with the resource compiler, which generates a compiled resource (.res) file that the linker links into your driver’s executable image.   Figure 2 is a typical example of an OSR created RC file that defines a VERSIONINFO resource.

// Include the necessary resources
//
#include
#include

#ifdef RC_INVOKED

//
// Set up debug information
//
#if DBG
#define VER_DBG VS_FF_DEBUG
#else
#define VER_DBG 0
#endif

// ------- version info -------------------------------------------------------

VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,0
PRODUCTVERSION 1,0,0,0
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS VER_DBG
FILEOS VOS_NT
FILETYPE VFT_DRV
FILESUBTYPE VFT2_DRV_SYSTEM
BEGIN
 BLOCK "StringFileInfo"
 BEGIN
  BLOCK "040904b0"
        BEGIN
  VALUE "Comments", "OSR Driver"
  VALUE "CompanyName", "OSR Open Systems Resources, Inc."
  VALUE "FileDescription", "OSR Driver"
  VALUE "FileVersion", "V1.0.0.0"
  VALUE "InternalName", "A OSR Written Driver"
  VALUE "LegalCopyright", "(C)2011 OSR Open Systems Resources, Inc."
  VALUE "OriginalFilename", "OSRDRV.sys"
  VALUE "ProductName", "OSR Driver"
  VALUE "ProductVersion", "V1.0.0.0"
        END
 END
 BLOCK "VarFileInfo"
 BEGIN
  VALUE "Translation", 0x0409,1200
 END
END
#endif

Figure 2—An Example of a Simple Resource File

As you can see from Figure 2 the VI resource contains a number of elements that describe the executable with which it is associated.  Let us discuss the VERSIONINFO resource in the next section.

One thing that should be mentioned here:  This RC file in Figure 2 that OSR typically uses does notfollow the typical format from the examples that you find in a WDK.  That’s because the OSR resource file is “fully specified” – it’s not built using a set of Microsoft-supplied macros.  Contrast the OSR file in Figure 2 with the typical RC file from the WDK shown in Figure 3.

#include
#include

#define VER_FILETYPE VFT_DRV
#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
#define VER_FILEDESCRIPTION_STR "WDM Driver for Intel 8255x Ethernet Adapters"
#define VER_INTERNALNAME_STR "PCIDRV.sys"
#define VER_ORIGINALFILENAME_STR "PCIDRV.sys"

#define VER_FILEVERSION 1,00,00,0000
#define VER_FILEVERSION_STR "1.00.00.0000"

#undef VER_PRODUCTVERSION
#define VER_PRODUCTVERSION VER_FILEVERSION

#undef VER_PRODUCTVERSION_STR
#define VER_PRODUCTVERSION_STR VER_FILEVERSION_STR

#define VER_LEGALCOPYRIGHT_STR "Copyright (C) 2003 Microsoft Corporation"
#ifdef VER_COMPANYNAME_STR

#undef VER_COMPANYNAME_STR
#define VER_COMPANYNAME_STR "Microsoft Corporation"
#endif

#undef VER_PRODUCTNAME_STR
#define VER_PRODUCTNAME_STR "Microsoft Sample Driver for PCI Device"

#include "common.ver"

PciDrvWMI MOFDATA pcidrv.bmf
 

 

Figure 3—WDK Sample RC File

Notice that the OSR created RC does not include “ntverp.h” or “common.ver”.   Why?  We don’t include these files because they contain Microsoft-specific defaults that will be used if you fail to properly set all the fields in your driver’s VI resource.   These defaults are appropriate for Microsoft developers, but probably not the best choice for others.  Driver writers who use a WDK RC file as a template for their RC file are the ones who typically end up with a VI resource that contains things like the default Microsoft copyright because they forgot to specify a copyright of their own.

Now we’re not saying that using the WDK-provided method is bad.  All we are trying doing is warning you of the consequences of using that method.   Namely, if you’re not careful when you use the WDK-provided method, your RC file you may end up with information in your VI resource that you did not intend to be there.

So, given that, let’s talk about what isin a VERSIONINFO resource.

VI resource

The VI resource that we mention above is defined in the RC file using the VERSIONINFO statement.   The VI resource itself can be defined using one of two following formats:

versionID VERSIONINFO fixed-info { block-statements …}

Or,

versionID VERSIONINFO

fixed-info

BEGIN

block-statement

….

END

Let’s describe the fields used in each of these formats.

versionID

This field is the version resource identifier and must be 1.   As an alternative to specifying 1 in this field, devs often specify VS_VERSION_INFO.The value for VS_VERSION_INFO is defined in the include file “verrsrc.h”, but is referenced in the include file “winver.h” (typically referenced in an RC file).

fixed-info

The fixed-info section of a VI resource contains version information such as the file version and intended operating system.  It is composed of the following statements:

  • FILEVERSIONversion– This statement defines the binary version number of the executable.  It is made up of two 32-bit integers which are broken up into four 16-bit fields.  Given a the statement “FILEVERSION 2,5,6,7” this would produce the integers 0x00020005 and 0x00060007 or the 4 16-bit fields of 0x0002, 0x0005, 0x0006, 0x0007 respectively.
  • PRODUCTVERSIONversion- This statement defines the binary version number of a product associated with the executable.   Its format follows the same format as defined in the FILEVERSIONstatement.   One thing that devs often find confusing is that this version number does not need to match the version number in the DriverVerfield of the driver’s INF file.  In fact, in most cases, these two values are unrelated.  Crazy, I know… but that’s the way it is.
  • FILEFLAGSMASKfileflagsmask– This statement is used to give some information about the state of the executable image associated with this VI.  The state of the image is defined by OR’ing together one or more of the following flags (example: “FILEFLAGS VS_FF_DEBUG | VS_FF_PRERELEASE”):VS_FF_DEBUG – the image contains debugging information or is compiled with debugging features enabled.

VS_FF_PATCHED – This image has been patched and is not identical to the original image containing the same FILEVERSIONnumber.

VS_FF_PRERELEASE – This image is a development version of the image and is not a released product

VS_FF_PRIVATEBUILD – This image was not built using the standard release procedures.  If this flag is set the StringFileInfoblock must contain a PrivateBuildstring.

VS_FF_SPECIALBUILD – This image was built using the standard release procedures but varies from the original image with the same FILEVERSIONnumber.   If this flag is set the StringFileInfoblock must contain a SpecialBuildstring.

VS_FF_FILEFLAGSMASK – this flag is a combination of all preceding values.

  • FILEOSfileos– This statement is used to define the operating system that this image is valid for.  This field is a 32-bit integer that is made up of two 16-bit fields.  The high 16 bits indicate the OS that the image is valid for, while the low 16-bits indicates’ the windowing system.   Most driver writers only care about Windows NT, so the only value that makes sense is (If you care to know what the other values are check out “verrsrc.h”):

VOS_NT – This value indicates that this image was designed for 32-bit windows.  The reader should note that there is no value for 64-bit windows, setting VOS_NT will suffice

  • FILETYPEfiletype–This statement is used to define the type image this VI resource describes.  This field can contain one of a number of values, but as stated above we are driver writers and only care about drivers.   Thus for us, the only value that make sense is:

VFT_DRV – This value indicates that the image contains a device driver.  The FILESUBTYPEvalue described below contains a more specific description of the contained driver.

  • FILESUBTYPEfilesubtype–This statement is used to further refine the driver image that was indicated in the FILETYPEstate.   It can have one of the following values:

VFT2_UNKNOWN – this value indicates the driver type is unknown

VFT2_DRV_COMM – image contains a communications driver

VFT2_DRV_PRINTER – image contains a printer driver

VFT2_DRV_KEYBOARD – image contains a keyboard driver

VFT2_DRV_LANGUAGE – image contains a language driver

VFT2_DRV_DISPLAY – image contains a display driver

VFT2_DRV_MOUSE – image contains a mouse driver

VFT2_DRV_NETWORK – image contains a network driver

VFT2_DRV_SYSTEM – image contains a system driver

VFT2_DRV_INSTALLABLE – image contains an installable driver

VFT2_DRV_SOUND – image contains a sound driver

VFT2_DRV_VERSIONED_PRINTER – image contains a versioned printer driver

The reader should note that any field listed above that is not specified in your RC file, will default to 0.  In addition, if you reexamine Figure 1 you will notice that none of the information from the fixed-infosection is visible via Explorer.   You should keep in mind that the information contained in the VI is really only there for informational purposes, the realinformation about the image is contained within the Portable Executable header (PE Header) of the image itself.

block-statement

The “block-statement” section defines one or more version-information blocks.   The version-information blocks can contain multiple StringFileInfoblocks and accompanying VarFileInfoblocks as defined below.

VarFileInfo Block

VarFileInfodefines a Variable File information block.  This block describes the language and character set used to encode the strings contained within the associated StringFileInfoblock discussed in the next section.   The VarFileInfoblock is defined as follows:

BLOCK “VarFileInfo” {VALUE “Translation”, langID, charsetID ….}

Where:

  • langId – This field contains a language code in hexadecimal format.   All the possible values for this field are contained within the documentation, but an example would be a value like “0x0409” which indicates a language of U.S English.
  • charsetID - This field contains a character set code in hexadecimal format.   All the possible values for this field are contained within the documentation, but an example would be a value like “1200” which indicates a character set of Unicode.

With this “Translation” statement you can specify multiple langId and charsetID pairs which will show the user that that are multiple translations for the VI in the image.  So as an example let’s assume that in our RC file we wanted to have a StringFileInfoinformation block in U.S. English using the Unicode character set. Our VarFileInfoblock would be defined as in Figure 4 below:

BLOCK "VarFileInfo"

BEGIN

VALUE "Translation", 0x409, 1200

END

END

Figure 4—VarFileInfo for U.S. English with Unicode

So now that we’ve indicated the language and character set to be used for our information, we need to create a StringFileInfoblock in U.S. English using Unicode with the appropriate information.   Let us see how it is done in the next section.

StringFileInfo Block

StringFileInfodefines an information block that contains a number of string-name parameters that describe the contained image in human-readable format.   This block describes the language and character set used to encode the strings contained within the block.   The StringFileInfoblock is defined as follows:

BLOCK “StringFileInfo” {BLOCK “lang-charset” {VALUE “string-name”, “value” …}}

Where:

  • lang-charset – this field contains a language and character-set pair.   All the possible values for this field are contained within the documentation, but an example would be a string value like “040904B0” which indicates a language of U.S English (0409) and a character set of Unicode (04B0).
  • string-name –this field contains one or more predefined names that describe the image in human readable format (in the language and character set defined by the lang-charset statement).   The predefined names are:

Comments – a optional comment string

CompanyName – a required string indicating the company that created this image

FileDescription – a required string that contains a string describing the image

FileVersion – a required string that contains the version number of the file in human-readable format, for example “V1.0.3.2” or “A1.0.0.0 RC2”

InternalName – a required string that contains the name of the image, for example “osrdrv.sys”

LegalCopyright – an optional string that contains the copyright notices that apply to this image.  If used, this should contain all copyright notices, legal symbols, copyright dates, and other information that apply.

LegalTrademarks – an optional string that contains all trademarks and registered trademarks that apply to the image.   If used, this should contain all notices, legal symbols, trademark numbers, and other information that apply,

OriginalFileName – a required string that contains the original name of the file.  This allows an application to determine whether the image has been renamed by the user.

PrivateBuild – this string should only be present if the user specified VS_FF_PRIVATEBUILD in the FILEFLAGMASK defined in the fixed-info section.  It should describe something about the private build.

ProductName – This is a required string that describes the name of the product which this image is associated with.

ProductVersion – This is a required string that contains the version number of the product which this image is associated with.  For example, “OSRUSB Learning Kit V2.0.1.0”

SpecialBuild – this string should only be present if the user specified VS_FF_SPECIALBUILD in the FILEFLAGMASK defined in the fixed-info section.  It should describe something about the special build.

It is worth noting that you can add your own string-name fields to this block. Unfortunately you will not be able to see them via Explorer.   To see them you would have to write a program that uses the Win32 Version Information functions to retrieve them.   In addition if you don’t specify a pre-defined name, its information will not be shown via Explorer.

So those are the fields that are contained within a StringFileInfoblock.  Now, as we showed in Figure 4 we defined a VarFileInfoblock that indicated that our StringFileInfoblock is in U.S. English using the Unicode character set.   Therefore we have to have a StringFileInfoblock with a lang-charsetthat corresponds to what we specified in the VarFileInfoblock.   Since we put 0x409 (U.S. English) and 1200 (Unicode)  then the setting for our lang-charsetin our StringFileInfoblock will be “040904b0”, where 0409 corresponds to our specified language and 04b0 corresponds to our specified character set (1200 == 0x04b0). Simple!   Figure 5 below shows the StringFileInfoblock for U.S English in Unicode.

BEGIN

BLOCK "StringFileInfo"

BEGIN

BLOCK "040904b0"

BEGIN

VALUE "Comments",         "OSR Driver"

VALUE "CompanyName",      "OSR Open Systems Resources, Inc."

 

VALUE "FileDescription",  "OSR Driver"

VALUE "FileVersion",      “V1.0.0.0”

VALUE "InternalName",     "A OSR Written Driver"

VALUE "LegalCopyright",   "2011 OSR Open Systems Resources, Inc."

 

VALUE "OriginalFilename", "OSRDRV.sys"

VALUE "ProductName",      "OSR Driver"

VALUE "ProductVersion",   “V1.0.0.0”

END

END

Figure 5—StringFileInfo for U.S. English in Unicode

So as you can see, the VERSIONINFO block can be used to thoroughly describe the image that is embedded in and this allows the user and the developer to quickly identify the software installed on the users’ machine.

Note: RC files and VERSIONINFO resources can be internationalized.  All you need to do is create additional VERSIONINFO resources in your RC file in the languages you require.

Now that we’ve discussed what fields are in a VERSIONINFOresource, let’s talk about creating one for our image.

Creating your own VI Resource

As mentioned earlier, an RC file is just a text script file.   While it can be created with a resource editor, for example within Visual Studio, it can just as well be created by hand using your favorite text editor.   Instead of starting from scratch and writing your RC file from scratch, the easiest thing to do is find an existing RC file with the required information and replace the fields that are important to your driver.     We would suggest you copy the information shown in Figure 2 into your WDK project’s RC file and edit it appropriately.

Now when we say edit it appropriately, what we mean is that you modify the fields listed in Figure 6 with settings that are appropriate for your image (you should note that if you want your Version Information to be visible in multiple languages you are going to be required to have a StringFileInfo/VarFileInfo section for each supported language).

  • FILEVERSION
  • PRODUCTVERSION
  • FILEFLAGSMASK
  • FILETYPE
  • FILESUBTYPE
  • CompanyName
  • FileDescription
  • InternalName
  • LegalCopyRight
  • LegalTradeMarks
  • OriginalFileName
  • ProductName
  • ProductVersion

Figure 6—Modify These Fields as Appropriate

Once you have completed that you need to add the name of the “.RC” file that you created to your sources file.  So in an example “Sources” file, for OSR’s “nothing” driver shown in Figure 7,you can see how we added “nothingver.rc” to the “SOURCES” line.

MAJORCOMP=ntos

MINORCOMP=osr

 

TARGETNAME=nothing

TARGETPATH=obj

TARGETTYPE=DRIVER

 

INCLUDES=$(DDK_INC_PATH)\inc;..\inc

 

SOURCES=nothing.c nothingver.rc


Figure 7—Sample Sources File with .RC File

When we use the WDK “build” utility to compile our nothing driver, it will see the “nothingver.rc” file on the “SOURCES” line in our “SOURCES” file and automatically compile it and link it to the “nothing.sys” file that it builds.

After you have successfully built the driver, make sure that you use Explorer to examine the information that you specified to ensure that all the information you want the user to see is there.  In addition you want to make sure that there is no information present that you did not intend to be there.  Remember that sometimes (depending on how the VI got created) Microsoft supplied information can sneak in, so you have to make sure that you’re supplying all the correct fields.

Summary

With the information contained within this article you can now create and add a comprehensive RC file to your driver without the risk of getting unexpected values in the various fields.  This information will allow your users and support people to immediately know what version of your product and image is being run. Now that is being resourceful!

User Comments
Rate this article and give us feedback. Do you find anything missing? Share your opinion with the community!
Post Your Comment

"Mangled code blocks"
Very good article, but there's a slight yet annoying issue.

Unfortunately, the verbatim code (.RC file excerpts) gets mangled by the browser (angle braces are treated as tag delimeters, ampersands are treated as entity references, etc.)

Is it possible to employ some kind of pre-formatting to make the code blocks HTML-safe?

Rating:
23-Jan-12, Vasya Pupkin


"Conversion to HTML mangled your "include" statements"
Conversion to HTML mangled your "include" statements.

Rating:
18-Jul-11, mike stratoti


Post Your Comments.
Print this article.
Email this article.
bottom nav links