//+---------------------------------------------------------------------------- // // 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; }