|
|
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
version.c
Abstract:
Implements calls to version APIs.
Author:
Calin Negreanu (calinn) 20-Jan-1999
Revision History:
<alias> <date> <comments>
--*/
#include "utils.h"
#include "version.h"
static PCTSTR g_DefaultTranslations[] = { TEXT("04090000"), TEXT("040904E4"), TEXT("040904B0"), NULL };
BOOL ShCreateVersionStruct ( OUT PVERSION_STRUCT VersionStruct, IN PCTSTR FileSpec )
/*++
Routine Description:
ShCreateVersionStruct is called to load a version structure from a file and to obtain the fixed version stamp info that is language-independent.
The caller must call ShDestroyVersionStruct after the VersionStruct is no longer needed.
Arguments:
VersionStruct - Receives the version stamp info to be used by other functions in this module
FileSpec - Specifies the file to obtain version info from
Return Value:
TRUE if the routine was able to get version info, or FALSE if an error occurred.
--*/
{ ZeroMemory (VersionStruct, sizeof (VERSION_STRUCT)); VersionStruct->FileSpec = FileSpec;
//
// Allocate enough memory for the version stamp
//
VersionStruct->Size = GetFileVersionInfoSize ( (PTSTR) FileSpec, &VersionStruct->Handle ); if (!VersionStruct->Size) { return FALSE; }
VersionStruct->VersionBuffer = HeapAlloc (GetProcessHeap (), 0, VersionStruct->Size);
if (!VersionStruct->VersionBuffer) { return FALSE; }
VersionStruct->StringBuffer = HeapAlloc (GetProcessHeap (), 0, VersionStruct->Size);
if (!VersionStruct->StringBuffer) { return FALSE; }
//
// Now get the version info from the file
//
if (!GetFileVersionInfo ( (PTSTR) FileSpec, VersionStruct->Handle, VersionStruct->Size, VersionStruct->VersionBuffer )) { ShDestroyVersionStruct (VersionStruct); return FALSE; }
//
// Extract the fixed info
//
VerQueryValue ( VersionStruct->VersionBuffer, TEXT("\\"), &VersionStruct->FixedInfo, &VersionStruct->FixedInfoSize );
return TRUE; }
VOID ShDestroyVersionStruct ( IN PVERSION_STRUCT VersionStruct )
/*++
Routine Description:
ShDestroyVersionStruct cleans up all memory allocated by the routines in this module.
Arguments:
VersionStruct - Specifies the structure to clean up
Return Value:
none
--*/
{ if (VersionStruct->VersionBuffer) { HeapFree (GetProcessHeap (), 0, VersionStruct->VersionBuffer); } if (VersionStruct->StringBuffer) { HeapFree (GetProcessHeap (), 0, VersionStruct->StringBuffer); }
ZeroMemory (VersionStruct, sizeof (VERSION_STRUCT)); }
ULONGLONG ShVerGetFileVer ( IN PVERSION_STRUCT VersionStruct ) { ULONGLONG result = 0; if (VersionStruct->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) { *((PDWORD) (&result)) = VersionStruct->FixedInfo->dwFileVersionLS; *(((PDWORD) (&result)) + 1) = VersionStruct->FixedInfo->dwFileVersionMS; } return result; }
ULONGLONG ShVerGetProductVer ( IN PVERSION_STRUCT VersionStruct ) { ULONGLONG result = 0; if (VersionStruct->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) { *((PDWORD) (&result)) = VersionStruct->FixedInfo->dwProductVersionLS; *(((PDWORD) (&result)) + 1) = VersionStruct->FixedInfo->dwProductVersionMS; } return result; }
DWORD ShVerGetFileDateLo ( IN PVERSION_STRUCT VersionStruct ) { if (VersionStruct->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) { return VersionStruct->FixedInfo->dwFileDateLS; } return 0; }
DWORD ShVerGetFileDateHi ( IN PVERSION_STRUCT VersionStruct ) { if (VersionStruct->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) { return VersionStruct->FixedInfo->dwFileDateMS; } return 0; }
DWORD ShVerGetFileVerOs ( IN PVERSION_STRUCT VersionStruct ) { if (VersionStruct->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) { return VersionStruct->FixedInfo->dwFileOS; } return 0; }
DWORD ShVerGetFileVerType ( IN PVERSION_STRUCT VersionStruct ) { if (VersionStruct->FixedInfoSize >= sizeof (VS_FIXEDFILEINFO)) { return VersionStruct->FixedInfo->dwFileType; } return 0; }
PCTSTR pShEnumVersionValueCommon ( IN OUT PVERSION_STRUCT VersionStruct );
PCTSTR pShEnumNextVersionTranslation ( IN OUT PVERSION_STRUCT VersionStruct );
PCTSTR pShEnumFirstVersionTranslation ( IN OUT PVERSION_STRUCT VersionStruct ) { UINT ArraySize;
if (!VerQueryValue ( VersionStruct->VersionBuffer, TEXT("\\VarFileInfo\\Translation"), &VersionStruct->Translations, &ArraySize )) { //
// No translations are available
//
ArraySize = 0; }
//
// Return a pointer to the first translation
//
VersionStruct->CurrentDefaultTranslation = 0; VersionStruct->MaxTranslations = ArraySize / sizeof (TRANSLATION); VersionStruct->CurrentTranslation = 0;
return pShEnumNextVersionTranslation (VersionStruct); }
BOOL pShIsDefaultTranslation ( IN PCTSTR TranslationStr ) { INT i;
for (i = 0 ; g_DefaultTranslations[i] ; i++) { if (lstrcmpi (TranslationStr, g_DefaultTranslations[i]) == 0) { return TRUE; } } return FALSE; }
PCTSTR pShEnumNextVersionTranslation ( IN OUT PVERSION_STRUCT VersionStruct ) { PTRANSLATION Translation;
if (g_DefaultTranslations[VersionStruct->CurrentDefaultTranslation]) {
lstrcpy (VersionStruct->TranslationStr, g_DefaultTranslations[VersionStruct->CurrentDefaultTranslation]); VersionStruct->CurrentDefaultTranslation++;
} else {
do { if (VersionStruct->CurrentTranslation == VersionStruct->MaxTranslations) { return NULL; }
Translation = &VersionStruct->Translations[VersionStruct->CurrentTranslation];
wsprintf ( VersionStruct->TranslationStr, TEXT("%04x%04x"), Translation->CodePage, Translation->Language );
VersionStruct->CurrentTranslation++;
} while (pShIsDefaultTranslation (VersionStruct->TranslationStr)); }
return VersionStruct->TranslationStr; }
PCTSTR pShEnumNextVersionValue ( IN OUT PVERSION_STRUCT VersionStruct ) { PCTSTR rc = NULL;
do { if (!pShEnumNextVersionTranslation (VersionStruct)) { break; }
rc = pShEnumVersionValueCommon (VersionStruct);
} while (!rc);
return rc; }
PCTSTR pShEnumFirstVersionValue ( IN OUT PVERSION_STRUCT VersionStruct, IN PCTSTR VersionField ) { PCTSTR rc;
if (!pShEnumFirstVersionTranslation (VersionStruct)) { return NULL; }
VersionStruct->VersionField = VersionField;
rc = pShEnumVersionValueCommon (VersionStruct);
if (!rc) { rc = pShEnumNextVersionValue (VersionStruct); }
return rc; }
PCTSTR pShEnumVersionValueCommon ( IN OUT PVERSION_STRUCT VersionStruct ) { PTSTR Text; UINT StringLen; PBYTE String; PCTSTR Result = NULL;
//
// Prepare sub block for VerQueryValue API
//
Text = HeapAlloc (GetProcessHeap (), 0, (18 + lstrlen (VersionStruct->TranslationStr) + lstrlen (VersionStruct->VersionField)) * sizeof (TCHAR));
if (!Text) { return NULL; }
wsprintf ( Text, TEXT("\\StringFileInfo\\%s\\%s"), VersionStruct->TranslationStr, VersionStruct->VersionField );
__try { //
// Get the value from the version stamp
//
if (!VerQueryValue ( VersionStruct->VersionBuffer, Text, &String, &StringLen )) { //
// No value is available
//
return NULL; } CopyMemory (VersionStruct->StringBuffer, String, StringLen * sizeof (TCHAR)); VersionStruct->StringBuffer [StringLen * sizeof (TCHAR)] = 0; Result = (PTSTR) VersionStruct->StringBuffer;
} __finally { HeapFree (GetProcessHeap (), 0, Text); }
return Result; }
BOOL ShGlobalVersionCheck ( IN PVERSION_STRUCT VersionData, IN PCTSTR NameToCheck, IN PCTSTR ValueToCheck ) { PCTSTR CurrentStr; BOOL result = FALSE;
CurrentStr = pShEnumFirstVersionValue (VersionData, NameToCheck); while (CurrentStr) { if (ShIsPatternMatch (ValueToCheck, CurrentStr)) { result = TRUE; break; } CurrentStr = pShEnumNextVersionValue (VersionData); } return result; }
|