Novell is now a part of Micro Focus

Implementing a Utility for Searching Windows Executable Files on NetWare

Articles and Tips: article

K.S. Venkatram
Net Solutions Support
Novell, Inc.
kvenkatram@novell.com

01 Sep 2002


One ubiquitous requirement for network administrators is the ability to obtain a software inventory of applications and files stored on NetWare servers. A useful tool to boost manageability in this area would be a utility that lets you search files for specified text or text patterns. A major challenge in developing such a utility is overcoming limitations in searching binary executable files for vendor and version information. This AppNote describes the creation of a simple WINVER.NLM utility that extracts this type of information from files that conform to Microsoft's Portable Executable (PE) format.


Topics

application development, software inventory, WINVER.NLM utility

Products

NetWare SDK

Audience

application developers

Level

intermediate

Prerequisite Skills

familiarity with C and NLM programming

Operating System

NetWare 5.x and 6.0

Tools

none

Sample Code

yes

Introduction

Considering the popularity of Microsoft products in today's computing environments, it is not uncommon to find a number of Microsoft applications on NetWare servers. When it comes time to produce an inventory listing of applications installed on each server, however, many network administrators resort to a labor-intensive manual process of listing all executable files and then hunting through each vendor's documentation to find the exact product name, version, and so on. Most agree it would be much easier if there were a program or utility that could extract this information programmatically.

Like most software applications, Windows executables embed some version information into their respective binary files. Microsoft's Resource Editor supports the embedding of vendor name, product name, product version, copyright, and file version in Windows .EXE and .DLL files. Similarly, linkers for NetWare Loadable Module (NLM) programs support the association of some file version and copyright information with the respective NLM file. Yet despite the existence of vendor/version information in binary files, it is not an easy task to retrieve this information programmatically-especially for cross-platform files.

The purpose of this AppNote is to remove some of the obstacles to interpreting the file format of Windows executable (.EXE and .DLL) files. Specifically, it outlines the Portable Executable (PE) file format Microsoft has developed for Windows 16- and 32-bit application executables and demonstrates how to extract the desired information in a simple NetWare-based utility named WINVER.NLM. After describing the utility's operation and showing some sample output, it addresses some marketability issues for incorporating similar functionality in commercial or in-house software development.

Programming Considerations

Microsoft's PE file specification supports proprietary Win32 SDK APIs that can be used in Windows applications to retrieve version information. However, Windows files stored on a NetWare server are cross-platform in nature to any NetWare application, and Microsoft's proprietary SDK does not provide APIs to run explicitly on the NetWare operating system. This rules out the use of the Microsoft APIs to read version information from a Windows file within a NetWare application.

Fortunately for NLM developers, the same thing is achievable using regular ANSI C APIs for memory and file I/O. The WINVER utility described in this AppNote was written in the C language and implemented as an NLM. The pattern searching is done using embedded version information in .EXE and .DLL files. The details necessary to accomplish this were obtained from official Microsoft documentation on the PE file format.

Overview of the Portable Executable Format

Microsoft's Portable Executable (PE) file format was originally designed to be a standard executable format for use on all Windows operating systems on all supported processors. As such, it is used by all Win32-based operating systems, including Windows NT/2000, Windows 9x, and even Win32s. It is termed "portable" because implementations of Windows NT on all supported platforms such as Intel 386 or later and compatible processors, MIPS, and Alpha use the same executable format. The PE format was recently updated to support 64-bit Windows as well.

Note: The PE file format is an extension of the Common Object File Format (COFF) developed for VAX VMS and UNIX environments.

The following table shows the overall layout of a PE file to give you an overview of the various components. The table should be read from the bottom up.


PE File Components
Comments

Unmapped data

Remaining sections, COFF information, and rest of layout

.reloc section

Section holding table of base relocations for the loader

.edata section

Section containing information about the exported functions and data

.idata section

Section containing information about imported functions and data

.rsrc section

Resources section containing raw resource data such as icons, bitmaps, and dialogs

.CRT section

Initialized data section

.bss section

Uninitialized static and global variables section

.data section

Initialized data section

.text section

Default section for code

Section Table

Contains an array of IMAGE_SECTION_HEADERS

Data Directory <IMAGE_OPTIONAL_HEADER>

Part of IMAGE_NT_HEADERS

IMAGE_FILE_HEADER

Part of IMAGE_NT_HEADERS

PE Header

Part of IMAGE_NT_HEADERS

MS-DOS Header

Start or Offset 0

The following sections briefly describe the PE file components we are most interested in-namely, the PE Header, the Section Table, and the Resources (.rsrc) section. A detailed explanation of every PE file component is beyond the scope of this AppNote. Readers who desire more information should consult the references listed at the end of this AppNote.

PE Header

The PE Header is the primary location where specifics of the PE file are stored. It contains information such as the Signature field, the location and size of code and data areas, and the resource data itself. The header also includes details as to what operating system and CPU the executable file is intended to be used with.

In writing WINVER.NLM it was necessary to devise an approach to traverse this header. Some of the data structures to be used in the implementation can be found in Microsoft's Win32 SDK header file (WINNT.H).

Section Table

Between the PE Header and the raw data for the executable's image section lies the Section Table. This is an array of IMAGE_SECTION_HEADER structures. The number of elements in the array is identified by the member IMAGE_NT_ HEADERS -> IMAGE_FILE_HEADER -> Number of sections.

Note: The sections in the image are sorted by their starting address instead of by name.

The following code snippet illustrates the traversal of the Section Table.

// Search for the .rsrc section while ( !res.bResFound && ( res.nSecIndex < res.FileHeader.NumberOfSections ) ) { memset ((void *) &res.sectionHeader, 0, sizeof( res.sectionHeader ) ) ; res.lBytes = read ( res.hFile, &res.sectionHeader, sizeof( res.sectionHeader ) ) ; if ( res.lBytes != sizeof( res.sectionHeader ) ) { #ifdef DEBUG ConsolePrintf ( "(DEBUG) Winver.nlm: Unable to read version information as an internal error occurred in reading section %u from file %s.\n", res.nSecIndex, res.szFile ) ; #endif goto ERROR_FILE ; } #ifdef DEBUG ConsolePrintf ( "(DEBUG) Winver.nlm: %s resource information, found Section %s.\n", res.szFile, res.sectionHeader.Name ) ; \#endif if ( !strcmp ( ".rsrc", (char *)res.sectionHeader.Name ) ) { res.bResFound = TRUE ; break ; } res.nSecIndex++ ; } ERROR_FILE : .

Resources Section

The Resources (.rsrc) section of the PE file contains the resources we are interested in. The typical resources for a Windows application are menus, dialogs, icons, string tables, and version information. Each of these resources has its own individual format. To retrieve information about a resource, you must successfully navigate the resource directory hierarchy, which consists of a master (root) directory and subdirectories, much like the file system on a hard disk. The subdirectories contain subdirectories of their own, within which the resource data is stored.

In the PE file, the root directory and all subdirectories are of type IMAGE_ RESOURCE_DIRECTORY. Following the IMAGE_RESOURCE_DIREC- TORY structure is an array of IMAGE_RESOURCE_DIRECTORY_ ENTRY structures. A directory entry can point to either another subdirectory (another IMAGE_RESOURCE_DIRECTORY) or to an IMAGE_RESOURCE_DATA_ ENTRY. The resource data entries describe the resource data embedded in the file, including the embedded version resource information we are interested in.

Running WINVER.NLM

WINVER.NLM is a simple NetWare command-line utility that takes as input a Windows file name and returns the version information embedded in it. This AppNote does not describe the intricacies involved in actually searching specific NetWare volumes or paths for Windows files matching input search clauses, due to the lengthy nature of such a discussion.

The WINVER.NLM utility can be downloaded from Novell's Cool Solutions Web site at http://www.novell.com/coolsolutions/tools/1404.html. The utility can be run on servers running NetWare 5.x or 6.0.

To get online help information about the command-line options for WINVER.NLM, switch to the NetWare system console and type "WINVER /?". The following table lists the options the user can choose from.


Option
Usage

/f

Used to specify the name (with full NetWare path) of the Windows executable file to be parsed by WINVER.NLM

/m

Used to specify the nature of pattern matching to be applied; possible values are "equals" and "contains" (the default of "equals" is applied when no /m option is specified)

/c

Used to specify the name of the company or vendor being searched for

/p

Used to specify the name of the product/application being searched for

/v

Used to specify the version of the product/application being searched for

/s

Used to specify the volume or directory path to scan for Windows .EXE or .DLL files. All .EXE or .DLL files in this path will be searched for version information and reported if matches are found.

Note: The /f option is the only mandatory option for WINVER; the remaining options can be used in any combination along with /f. If the pattern string that is to be searched for contains spaces, you must enclose the string within angle brackets ("<" and ">").

Sample Usage and Output Results

Following are several examples of WINVER commands and the results displayed upon successful completion of each command. The directory structure and application files used in the examples are listed below:

SYS:\WINAPPS SAMPLE.EXE SYS:\WINAPPS\APPS_1 SAMPLE.DLL SYS:\WINAPPS\APPS_2 SAMPLIB.DLL

Example 1. WINVER /f sys:\winapps\SAMPLE.EXE

********************************************************************** Windows File Name: SAMPLE.EXE, Path: sys:\winapps Windows version found: Company name: SAMPLE Corporation Product name: SAMPLE Application Product version: 1.0 Copyright: Copyright @ **********************************************************************

Example 2. WINVER /f sys:\winapps\SAMPLE.EXE /m contains /c SAMPLE

********************************************************************** Windows File Name: SAMPLE.EXE, Path: sys:\winapps Pattern used: SAMPLE Pattern match: contains Windows version found: Company name: SAMPLE Corporation Product name: SAMPLE Application Product version: 1.0 Copyright: Copyright @ **********************************************************************

Example 3. WINVER /f sys:\winapps\SAMPLE.EXE /p <SAMPLE Application>

********************************************************************** Windows File Name: SAMPLE.EXE, Path: sys:\winapps Pattern used: SAMPLE Application Pattern match: equals Windows version found: Company name: SAMPLE Corporation Product name: SAMPLE Application Product version: 1.0 Copyright: Copyright @ **********************************************************************

Example 4. WINVER /f sys:\winapps\SAMPLE.EXE /v 1.0

********************************************************************** Windows File Name: SAMPLE.EXE, Path: sys:\winapps Pattern used: 1.0 Pattern match: equals Windows version found: Company name: SAMPLE Corporation Product name: SAMPLE Application Product version: 1.0 Copyright: Copyright @ **********************************************************************

Example 5. WINVER /s sys: /m contains /c SAMPLE

********************************************************************** Windows File Name: SAMPLE.EXE, Path: sys:\ Windows version found: Pattern match: contains Company name: SAMPLE Corporation Product name: SAMPLE Application Product version: 1.0 Copyright: Copyright @ ********************************************************************** ********************************************************************** Windows File Name: SAMPLE.EXE, Path: sys:\winapps Windows version found: Pattern match: contains Company name: SAMPLE Corporation Product name: SAMPLE Application Product version: 1.0 Copyright: Copyright @ ********************************************************************** ********************************************************************** Windows File Name: SAMPLE.DLL, Path: sys:\winapps\apps_1 Windows version found: Pattern match: contains Company name: SAMPLE Corporation Product name: SAMPLE Dynamic Link Library Product version: 1.0 Copyright: Copyright @ ********************************************************************** ********************************************************************** Windows File Name: SAMPLIB.DLL, Path: sys:\winapps\apps_2 Windows version found: Pattern match: contains Company name: ABC & SAMPLE Corporation Product name: ABC Dynamic Link Library Product version: 1.0 Copyright: Copyright @ **********************************************************************

Marketability Issues

In general terms, the market that exists for this kind of cross-platform pattern- based search functionality encompasses storage administration, licensing, and content management solutions for Windows applications on NetWare servers. At present, these areas are still evolving. Hopefully the information provided in this AppNote and the sample WINVER.NLM utility will help spark the necessary innovation to meet manageability expectations in future development efforts. For now, here are some ideas to get your creative juices flowing.

Readers familiar with Novell Licensing Services (NLS) may recall that when using the NetWare Administrator (NWAdmin) utility to create a license certificate for a Windows application, you had to manually enter the vendor name, product name, and product version associated with the application. The WINVER utility demonstrated in this AppNote could help automate or simplify this task.

Another possibility that deserves mention is the potential of integrating such functionality into a browser-based management tool. The output of the WINVER utility need not remain local to a server; it could also be split into packets and redirected across the network to a remote management tool such as the NetWare 6 Remote Manager utility.

For interested readers, the ZENworks for Servers 3 Inventory product showcases the retrieval of version information from Windows .EXE files on NetWare servers to report enhanced software inventory. For more information, see the product Web site at http://www.novell.com/products/zenworks/servers.

Conclusion

This AppNote has introduced WINVER.NLM, a NetWare-based utility for obtaining vendor and version information that is contained within Windows executable files stored on NetWare servers. Developers of software applications are encouraged to embed version information into their applications, as well as publish documentation and accompanying APIs, to assist in efforts to simplify the process of locating version information and thereby easing the overall task of application management/inventory.

Additional References

For additional information about the Portable Executable (PE) file format and other concepts discussed in this AppNote, refer to the following resources:

  • "An In-Depth Look into the Win32 Portable Executable File Format, Parts 1 and 2" by Matt Pietrek, MSDN Magazine, February and March 2002 issues, available online at http://msdn.microsoft.com/msdnmag.

  • PEDUMP and DLGDUMP utilities (with source code) available from Microsoft's developer site at http://msdn.microsoft.com. Additional information and alternate download sources can be found at Matt Pietrek's Web site at http://www.wheaty.net.

  • Windows 95 System Programming Secrets by Matt Pietrek (Although this book is out-of-print, I list it here because it was the main reference I consulted in constructing WINVER.NLM without the use of the Win32 SDK. If you can find a used copy somewhere, I highly recommend this book.)

* Originally published in Novell AppNotes


Disclaimer

The origin of this information may be internal or external to Novell. While Novell makes all reasonable efforts to verify this information, Novell does not make explicit or implied claims to its validity.

© Copyright Micro Focus or one of its affiliates