mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
6.0 KiB
217 lines
6.0 KiB
/*** filever.c - Query file version information (Win32-only)
|
|
*
|
|
* Microsoft Confidential
|
|
* Copyright (C) Microsoft Corporation 1993-1994
|
|
* All Rights Reserved.
|
|
*
|
|
* Author:
|
|
* Benjamin W. Slivka
|
|
*
|
|
* History:
|
|
* 07-Jun-1994 bens Split off from fileutil.c
|
|
* 05-Aug-1994 bens Don't complain about GetFileVersionInfoSize failing
|
|
*/
|
|
|
|
#ifndef BIT16
|
|
|
|
//** Get minimal Win32 definitions
|
|
//#define WIN32_LEAN_AND_MEAN
|
|
#include <windows.h>
|
|
#undef ERROR // Override stupid "#define ERROR 0" in wingdi.h
|
|
|
|
#include "types.h"
|
|
#include "asrt.h"
|
|
#include "error.h"
|
|
#include "mem.h"
|
|
#include "message.h"
|
|
|
|
#include "filever.h"
|
|
#include "filever.msg"
|
|
|
|
#include "ttfver.h"
|
|
|
|
|
|
BOOL getVer(void *pBlock,
|
|
char *pszKey,
|
|
void **ppData,
|
|
int *pcbData,
|
|
char *pszFile,
|
|
PERROR perr);
|
|
|
|
|
|
/*** getFileVerAndLang - Use VER.DLL API to get file version and language
|
|
*
|
|
* NOTE: See fileutil.h for entry/exit conditions.
|
|
*/
|
|
BOOL getFileVerAndLang(char *pszFile,
|
|
ULONG *pverMS,
|
|
ULONG *pverLS,
|
|
char **ppszVersion,
|
|
char **ppszLang,
|
|
PERROR perr)
|
|
{
|
|
char ach[256];
|
|
char achName[256];
|
|
int cb;
|
|
DWORD cbFFI;
|
|
DWORD cbFVI;
|
|
DWORD cbLang;
|
|
DWORD dwLangPrimary;
|
|
DWORD dwTTFVersion;
|
|
DWORD handle;
|
|
VS_FIXEDFILEINFO *pFFI;
|
|
char *pbFVI;
|
|
char *psz;
|
|
DWORD *pdwLang;
|
|
int rc;
|
|
|
|
//** Get size of file version info
|
|
cbFVI = GetFileVersionInfoSize(pszFile, &handle);
|
|
if (cbFVI == 0) {
|
|
//** Doesn't have file version info, try for TrueType version info
|
|
if (FGetTTFVersion(pszFile, &dwTTFVersion)) {
|
|
*pverMS = dwTTFVersion;
|
|
*pverLS = 0; //** What ACME setup wants
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
//** Allow common error exit point
|
|
*ppszVersion = NULL;
|
|
*ppszLang = NULL;
|
|
|
|
//** Allocate buffer for info
|
|
if (!(pbFVI = MemAlloc(cbFVI))) {
|
|
ErrSet(perr,pszFILERR_OOM_VER_BUF,"%s",pszFile);
|
|
goto error;
|
|
}
|
|
|
|
//** Get the info
|
|
if (!GetFileVersionInfo(pszFile,handle,cbFVI,pbFVI)) {
|
|
rc = GetLastError();
|
|
ErrSet(perr,pszFILERR_GFVI_FAILED,"%d%s",rc,pszFile);
|
|
goto error;
|
|
}
|
|
|
|
//** Return version numbers
|
|
if (getVer(pbFVI,"\\",&pFFI,&cbFFI,pszFile,perr)) {
|
|
*pverMS = pFFI->dwFileVersionMS;
|
|
*pverLS = pFFI->dwFileVersionLS;
|
|
}
|
|
|
|
//** Get language info
|
|
if (getVer(pbFVI,"\\VarFileInfo\\Translation",&pdwLang,&cbLang,pszFile,perr)) {
|
|
dwLangPrimary = *pdwLang;
|
|
//** Format first language codes
|
|
sprintf(ach,"%d",LOWORD(dwLangPrimary));
|
|
|
|
//** Format any additional language codes
|
|
for (pdwLang++;
|
|
cbLang > sizeof(DWORD);
|
|
cbLang -= sizeof(DWORD), pdwLang++) {
|
|
sprintf(ach+sizeof(ach)," %d",LOWORD(*pdwLang));
|
|
}
|
|
|
|
//** Make copy to return to caller
|
|
if (!(*ppszLang = MemStrDup(ach))) {
|
|
ErrSet(perr,pszFILERR_OOM_DUP_LANG,"%s",pszFile);
|
|
goto error;
|
|
}
|
|
|
|
//** Get version *string*
|
|
//BUGBUG 25-May-1994 bens Win32 SDK is unclear about which halfs of the dword
|
|
// the Lang and CharSet occupy, so try both!
|
|
//** HI/LO is the defacto order used by Windows 3.x files
|
|
sprintf(achName,"\\StringFileInfo\\%04x%04x\\FileVersion",
|
|
HIWORD(dwLangPrimary),
|
|
LOWORD(dwLangPrimary));
|
|
if (!getVer(pbFVI,achName,&psz,&cb,pszFile,perr)) {
|
|
//** Try alternate order!
|
|
sprintf(achName,"\\StringFileInfo\\%04x%04x\\FileVersion",
|
|
LOWORD(dwLangPrimary),
|
|
HIWORD(dwLangPrimary));
|
|
getVer(pbFVI,achName,&psz,&cb,pszFile,perr);
|
|
}
|
|
|
|
//** Duplicate and return string, if we got one
|
|
if (psz) {
|
|
if (!(*ppszVersion = MemStrDup(psz))) {
|
|
ErrSet(perr,pszFILERR_OOM_DUP_VER,"%s",pszFile);
|
|
goto error;
|
|
}
|
|
}
|
|
}
|
|
|
|
//** Free buffer
|
|
MemFree(pbFVI);
|
|
|
|
//** Success
|
|
return TRUE;
|
|
|
|
//** Failure
|
|
error:
|
|
//** NOTE: Don't free *ppszVersion and *ppszLang in case caller wants
|
|
// to use them.
|
|
if (pbFVI) {
|
|
MemFree(pbFVI);
|
|
}
|
|
return FALSE;
|
|
} /* getFileVerAndLang() */
|
|
|
|
|
|
/*** getVer - Get particular piece of EXE version information
|
|
*
|
|
* Entry:
|
|
* pBlock - Block filled in by GetFileVersionInfo
|
|
* pszKey - String to pass to VerQueryValue
|
|
* ppData - Pointer to variable to receive pointer to requested
|
|
* data insided pBlock.
|
|
* pcbData - Pointer to variable to receive length of requested
|
|
* data.
|
|
* pszFile - File being examined (for error messages)
|
|
* perr - ERROR structure
|
|
*
|
|
* Exit-Success:
|
|
* Returns TRUE; *ppData and *pcbData filled in.
|
|
*
|
|
* Exit-Failure:
|
|
* Returns FALSE; Could not get requested data
|
|
*/
|
|
BOOL getVer(void *pBlock,
|
|
char *pszKey,
|
|
void **ppData,
|
|
int *pcbData,
|
|
char *pszFile,
|
|
PERROR perr)
|
|
{
|
|
int rc;
|
|
|
|
if (!VerQueryValue(pBlock,pszKey,ppData,pcbData)) {
|
|
rc = GetLastError();
|
|
switch (rc) {
|
|
|
|
case NO_ERROR:
|
|
case ERROR_RESOURCE_DATA_NOT_FOUND:
|
|
case ERROR_RESOURCE_TYPE_NOT_FOUND:
|
|
//** Skip the error message
|
|
break;
|
|
|
|
default:
|
|
ErrSet(perr,pszFILERR_VER_QUERY_VALUE,"%d%s%s",rc,pszKey,pszFile);
|
|
}
|
|
*ppData = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
//** See if version info was there
|
|
if (*pcbData == 0) {
|
|
ErrSet(perr,pszFILERR_VER_KEY_MISSING,"%s%s",pszKey,pszFile);
|
|
*ppData = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
//** Success
|
|
return TRUE;
|
|
} /* getVer() */
|
|
|
|
#endif // !BIT16
|