VerCheck: Discovering Component Version Numbers by John Graham-Cumming


Figure 2: 

vbdb32.dll
vbar2232.dll
ctl3d32.dll
dbgrid32.ocx
  .
  .
  .
version.dll
msjint32.dll
msjter32.dll
msjt3032.dll
vbajet32.dll
wsock32.dll
\Program Files\Common Files\Microsoft Shared\DAO\dao3032.dll


Figure 3

"vbdb32.dll","4.00.2908"
"vbar2232.dll","2.0.5924"
"ctl3d32.dll","2.31.000"
"dbgrid32.ocx","5.00.3714"
"dblist32.ocx","5.00.3714"
   .
   .
   .
"version.dll","4.00.950"
"msjint32.dll","3.000.2712"
"msjter32.dll","3.000.2712"
"msjt3032.dll","3.000.2809"
"vbajet32.dll","5.0.7122"
"wsock32.dll","4.00.950"
"\Program Files\Common Files\Microsoft Shared\DAO\dao3032.dll","3.000.2627"
     
Listing One
#include "stdio.h"              // We indicate progress with printf
#include "windows.h"            // Needed for standard Windows definition
#include "winver.h"             // Needed for the version checking API

// Input and output files with defaults in case the user does not specify any
char sourceFile[      MAX_PATH ] = "VERCHECK.LST";
char destinationFile[ MAX_PATH ] = "VERCHECK.CSV";

/*---------------------------------------------------------------------------
| procedure: printHelp
| purpose:   Prints program help
---------------------------------------------------------------------------*/
void printHelp( void )
{
        printf( "Usage - vercheck [ ]\n" );
        printf( "                   Source LST file\n" );
        printf( "              Destination CSV file\n" );
}
/*---------------------------------------------------------------------------
| procedure: parceCL
| purpose:   Parses the command line for information
---------------------------------------------------------------------------*/
BOOL parseCL( int argc, char * argv[] )
{
        // Check to see if there are any parameters, if any is /? then
        // we will print help and return FALSE, otherwise read the file names
        if ( argc == 2 )
        {
                strlwr( argv[1] );
                if ( strcmp( argv[1], "/?" ) == 0 )
                {
                        printHelp();
                        return FALSE;
                }
        }
        if ( argc == 3 ) 
        {
                strlwr( argv[1] );
                strlwr( argv[2] );
                strcpy( sourceFile,     argv[1] );
                strcpy( destinationFile, argv[2] );
        }
        return TRUE;
}
/*---------------------------------------------------------------------------
| procedure: main
| purpose:   This is where the program begins...
---------------------------------------------------------------------------*/
void main( int argc, char * argv[] )
{
  FILE * versionLST;      // File handle for the list of files
  // Print the banner
  printf( "\nVersion Check v1.0\n\n" );
  // Check parameters and return if /?
  if ( !parseCL( argc, argv ) )
     return;      
  // Check for the file VERCHECK.LST which we use to work out what
  // we are version checking
  versionLST = fopen( sourceFile, "r" );
  // If the file is open then create the output file
  if ( versionLST )
  {
     FILE * versionOUT;   // File handle for the output file
     // Create the output file
     versionOUT = fopen( destinationFile, "w" );
     if ( versionOUT )
     {
       // Parse LST file and read version number of each file mentioned
       while ( !feof( versionLST ) )
       {
          // The file that we are going to check
          char versionFILE[ MAX_PATH ];
          // Get the file name to be version checked
          if ( fgets( versionFILE, MAX_PATH, versionLST ) )
          {
            LPVOID version;     // Storage for the version resource
            DWORD  versionSIZE; // The size of the version structure
            DWORD  dummy;
            DWORD  c;
            // Tidy up the line
            c = strlen( versionFILE );
            if ( c > 3 ) 
            {
               versionFILE[ c - 1 ] = '\0';
               printf( "Reading version of %s\n", versionFILE );
               // Get the size of the files version information
               versionSIZE = GetFileVersionInfoSize( versionFILE, &dummy );
               if ( versionSIZE > 0 ) 
               {
                  // Create space to receive the version number
                  version = malloc( versionSIZE );

                  if ( version )
                  {
                     DWORD  versionLENGTH;  // Length of actual version
                     LPVOID versionINFO;    // Version string
                     DWORD  languageLENGTH; // Length of actual version
                     LPWORD languageINFO;   // Version string

                     // Now read the version number of the file
                     if (GetFileVersionInfo(versionFILE,0,versionSIZE,version))
                     {
                        // Get actual version information
                        if (VerQueryValue(version,
                                "\\VarFileInfo\\Translation",
                                &languageINFO,&languageLENGTH) !=0)
                        {
                          char versionSTRING[ MAX_PATH ];
                          // Create string to retrieve resource, first 
                          // entry in language table is used
                          sprintf(versionSTRING,
                              "\\StringFileInfo\\%4.4X%4.4X\\FileVersion",
                              languageINFO[0],languageINFO[1]);
                          if (VerQueryValue(version,versionSTRING,
                              &versionINFO, &versionLENGTH) != 0)
                             fprintf(versionOUT,"\"%s\",\"%s\"\n",
                                             versionFILE,versionINFO);
                          else
                             fprintf(versionOUT,"\"%s\",
                                   \"Failed (file version)\"\n",versionFILE);
                        }
                        else
                           fprintf(versionOUT,"\"%s\",
                                   \"Failed (language)\"\n",versionFILE);
                     }
                     else 
                        fprintf(versionOUT, 
                                "\"%s\",\"Failed (version)\"\n",versionFILE);
                     free( version );
                  }
                  else
                     printf( "Failed to allocate memory\n" );
               }
               else
               {
           printf("Failed to get version information for %s\n", versionFILE);
           fprintf(versionOUT,"\"%s\",\"Not found\"\n", versionFILE );
               }
            }
            else
               break;
          }
       }
       fclose( versionOUT );
     }
     else
        printf( "Failed to create output file %s\n", destinationFile );

     fclose( versionLST );
  }
  else
     printf( "Failed to find %s\n", sourceFile );
}





4


