159 lines
4.6 KiB
C++
159 lines
4.6 KiB
C++
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// File: getmodulever.cpp
|
||
|
//
|
||
|
// Module: CMSETUP.LIB, CMUTIL.DLL
|
||
|
//
|
||
|
// Synopsis: Implementation of the GetModuleVersionAndLCID function.
|
||
|
//
|
||
|
// Copyright (c) 1998-2001 Microsoft Corporation
|
||
|
//
|
||
|
// Author: quintinb Created Header 08/19/99
|
||
|
//
|
||
|
//+----------------------------------------------------------------------------
|
||
|
|
||
|
#include "cmutil.h"
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Function: GetModuleVersionAndLCID
|
||
|
//
|
||
|
// Synopsis: Gets the version information and LCID from the specified module
|
||
|
//
|
||
|
// Arguments: LPTSTR pszFile - Full path to the file to get the version number of
|
||
|
// LPDWORD pdwVersion - version number (Hiword Major, Loword Minor)
|
||
|
// LPDWORD pdwBuild - build number (Hiword Major, Loword Minor)
|
||
|
// LPDWORD pdwLCID - returns the Locale ID that the module was localized too
|
||
|
//
|
||
|
// Returns: HRESULT -- S_OK if successful, an error code otherwise
|
||
|
//
|
||
|
// History: quintinb -- Code borrowed from Yoshifumi "Vogue" Inoue
|
||
|
// from (private\admin\wsh\host\verutil.cpp).
|
||
|
// Rewritten to match our coding style. 9/14/98
|
||
|
// 17-Oct-2000 SumitC cleanup, fixed leaks, moved to common\source
|
||
|
//
|
||
|
// Notes: There are 2 versions of this function, which take ANSI and Unicode
|
||
|
// versions of the pszFile argument.
|
||
|
//
|
||
|
//+----------------------------------------------------------------------------
|
||
|
HRESULT GetModuleVersionAndLCID (LPSTR pszFile, LPDWORD pdwVersion, LPDWORD pdwBuild, LPDWORD pdwLCID)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
HANDLE hHeap = NULL;
|
||
|
LPVOID pData = NULL;
|
||
|
DWORD dwHandle;
|
||
|
DWORD dwLen;
|
||
|
|
||
|
if ((NULL == pdwVersion) || (NULL == pdwBuild) || (NULL == pdwLCID) ||
|
||
|
(NULL == pszFile) || (TEXT('\0') == pszFile))
|
||
|
{
|
||
|
hr = E_POINTER;
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
*pdwVersion = 0;
|
||
|
*pdwBuild = 0;
|
||
|
*pdwLCID = 0;
|
||
|
|
||
|
dwLen = GetFileVersionInfoSizeA(pszFile, &dwHandle);
|
||
|
if (0 == dwLen)
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
hHeap = GetProcessHeap();
|
||
|
if (NULL == hHeap)
|
||
|
{
|
||
|
hr = E_POINTER;
|
||
|
CMASSERTMSG(FALSE, TEXT("GetModuleVersionAndLCID -- couldn't get a handle to the process heap."));
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
pData = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwLen);
|
||
|
|
||
|
if (!pData)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
CMASSERTMSG(FALSE, TEXT("GetModuleVersionAndLCID -- couldn't alloc on the process heap."));
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
if (!GetFileVersionInfoA(pszFile, dwHandle, dwLen, pData))
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
VS_FIXEDFILEINFO* pVerInfo;
|
||
|
LPVOID pInfo;
|
||
|
UINT nLen;
|
||
|
|
||
|
if (!VerQueryValueA(pData, "\\", &pInfo, &nLen))
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
pVerInfo = (VS_FIXEDFILEINFO*) pInfo;
|
||
|
|
||
|
*pdwVersion = pVerInfo->dwProductVersionMS;
|
||
|
*pdwBuild = pVerInfo->dwProductVersionLS;
|
||
|
|
||
|
//
|
||
|
// Now get the language the binary was compiled for
|
||
|
//
|
||
|
typedef struct _LANGANDCODEPAGE
|
||
|
{
|
||
|
WORD wLanguage;
|
||
|
WORD wCodePage;
|
||
|
} LangAndCodePage;
|
||
|
|
||
|
nLen = 0;
|
||
|
LangAndCodePage* pTranslate = NULL;
|
||
|
|
||
|
if (!VerQueryValueA(pData, "\\VarFileInfo\\Translation", (PVOID*)&pTranslate, &nLen))
|
||
|
{
|
||
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
||
|
goto Cleanup;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Let's assert that we only got one LangAndCodePage struct back. We technically
|
||
|
// could get more than one back but we certainly aren't expecting more than one. If we
|
||
|
// get more than one, use the first one as the language of the dll.
|
||
|
//
|
||
|
MYDBGASSERT(1 == (nLen/sizeof(LangAndCodePage)));
|
||
|
|
||
|
if ((nLen/sizeof(LangAndCodePage)) >= 1)
|
||
|
{
|
||
|
*pdwLCID = pTranslate[0].wLanguage;
|
||
|
}
|
||
|
|
||
|
Cleanup:
|
||
|
if (hHeap)
|
||
|
{
|
||
|
HeapFree(hHeap, 0, pData);
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
// This is the Unicode version of GetModuleVersionAndLCID (the first arg is LPWSTR)
|
||
|
// and it just calls the Ansi version above.
|
||
|
//+----------------------------------------------------------------------------
|
||
|
HRESULT GetModuleVersionAndLCID (LPWSTR pszFile, LPDWORD pdwVersion, LPDWORD pdwBuild, LPDWORD pdwLCID)
|
||
|
{
|
||
|
CHAR pszAnsiFileName[MAX_PATH + 1];
|
||
|
|
||
|
if (WideCharToMultiByte(CP_ACP, 0, pszFile, -1, pszAnsiFileName, MAX_PATH, NULL, NULL))
|
||
|
{
|
||
|
return GetModuleVersionAndLCID(pszAnsiFileName, pdwVersion, pdwBuild, pdwLCID);
|
||
|
}
|
||
|
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
|