BOOL GetFileVersion( const char *szFileName, DWORD &dwMajor, DWORD &dwMinor, DWORD &dwBuildNumber)
{
static BOOL (FAR WINAPI *MyGetFileVersionInfoSize)( LPTSTR, LPDWORD );
static BOOL (FAR WINAPI *MyGetFileVersionInfo)( LPTSTR, DWORD, DWORD, LPVOID );
static BOOL (FAR WINAPI *MyVerQueryValue)( const LPVOID, LPTSTR, LPVOID *, PUINT );
HINSTANCE hVersionLib;
// Rückgabewerte auf Dummies setzen
dwMajor = 0;
dwMinor = 0;
dwBuildNumber = 0;
// damit wir die VERSION.LIB nicht zum Projekt linken müssen
hVersionLib = LoadLibrary( "version.dll" );
if ( hVersionLib == NULL )
{
return FALSE;
}
MyGetFileVersionInfoSize = (int (_stdcall *)(char *,unsigned long *))GetProcAddress( hVersionLib, "GetFileVersionInfoSizeA" );
if ( MyGetFileVersionInfoSize == NULL )
{
FreeLibrary( hVersionLib );
return FALSE;
}
MyGetFileVersionInfo = (int (_stdcall *)( LPTSTR, DWORD, DWORD, LPVOID ))GetProcAddress( hVersionLib, "GetFileVersionInfoA" );
if ( MyGetFileVersionInfo == NULL )
{
FreeLibrary( hVersionLib );
return FALSE;
}
MyVerQueryValue= (int (_stdcall *)( const LPVOID, LPTSTR, LPVOID *, PUINT ))GetProcAddress( hVersionLib, "VerQueryValueA" );
if ( MyVerQueryValue == NULL )
{
FreeLibrary( hVersionLib );
return FALSE;
}
LPSTR lpVersion;
UINT uVersionLen;
DWORD dwVerHnd = 0, // An 'ignored' parameter, always '0'
dwVerInfoSize = MyGetFileVersionInfoSize ( (char*)szFileName, &dwVerHnd );
if ( !dwVerInfoSize )
{
// die Größe für das File-Info-Struct konnte nicht festgestellt werden
FreeLibrary( hVersionLib );
return FALSE;
}
// Speicher für File-Info-Struct belegen
LPSTR lpstrVffInfo = (LPSTR)malloc( dwVerInfoSize );
if ( lpstrVffInfo == NULL )
{
FreeLibrary( hVersionLib );
return FALSE;
}
// Info anfordern
if ( !MyGetFileVersionInfo( (char*)szFileName, dwVerHnd, dwVerInfoSize, lpstrVffInfo ) )
{
free( lpstrVffInfo );
FreeLibrary( hVersionLib );
return FALSE;
}
/* The below 'hex' value looks a little confusing, but
essentially what it is, is the hexidecimal representation
of a couple different values that represent the language
and character set that we are wanting string values for.
040904E4 is a very common one, because it means:
US English, Windows MultiLingual characterset
Or to pull it all apart:
04------ = SUBLANG_ENGLISH_USA
--09---- = LANG_ENGLISH
----04E4 = 1252 = Codepage for Windows:Multilingual*/
static char fileVersion[256];
LPVOID version = NULL;
DWORD langD;
BOOL retVal;
sprintf( fileVersion, "\\VarFileInfo\\Translation" );
retVal = MyVerQueryValue( lpstrVffInfo, fileVersion, &version, (UINT*)&uVersionLen );
if ( ( retVal )
&& ( uVersionLen == 4 ) )
{
memcpy( &langD, version, 4 );
sprintf( fileVersion, "\\StringFileInfo\\%02X%02X%02X%02X\\FileVersion",
( langD & 0xff00 ) >> 8,
langD & 0xff,
( langD & 0xff000000 ) >> 24,
( langD & 0xff0000 ) >> 16 );
}
else
{
sprintf( fileVersion, "\\StringFileInfo\\%04X04B0\\FileVersion", GetUserDefaultLangID() );
}
if ( !MyVerQueryValue( lpstrVffInfo, fileVersion, (LPVOID *)&lpVersion, (UINT *)&uVersionLen ) )
{
free( lpstrVffInfo );
FreeLibrary( hVersionLib );
return FALSE;
}
// Now we have a string that looks like this :
// "MajorVersion.MinorVersion.BuildNumber", so let's parse it
FreeLibrary( hVersionLib );
// Get first token (Major version number)
LPSTR token = strtok( lpVersion, TEXT ( "." ) );
if ( token == NULL )
{
free( lpstrVffInfo );
return TRUE;
}
dwMajor = atoi( token );
token = strtok( NULL, TEXT( "." ) );
if ( token == NULL )
{
free( lpstrVffInfo );
return TRUE;
}
dwMinor = atoi( token );
token = strtok( NULL, TEXT( "." ) );
if ( token == NULL )
{
free( lpstrVffInfo );
return TRUE;
}
dwBuildNumber = atoi( token );
free( lpstrVffInfo );
return TRUE;
}