作者:Eran Yariv 编译:刘峰
这篇文章包含了一些关于COMCTL32.DLL和Unimodem/V TAPI驱动程序的信息。
并讲述了如何通过你的MFC应用程序检测DLL的版本信息。
COMCTL32.DLL versions
该DLL负责Windows使用的所有控制。Windows95首先使用该库,版本号为
4.0.Internet Explorer3.x升级它为4.70.Internet Explorer 4.0的版本为
4.71.
扩展控制(如带检取框的列表视)只在比4.00版以上得到支持。
关于公用控制版本的详细信息可到下列网址获取:
http://www.microsoft.com/msdn/sdk/inetsdk/help/inet1560.htm
UnimodemV
Unimodem是一个通过TAPI使用的标准的Modem驱动程序。modem硬件提供的
驱动程序95%以上仅仅是参数文件.Unimodem的32位驱动程序放在Windows系统目
录中的UMDN32.dll.
最近,微软发布了Voice modems的升级版本,命名为UnimodemV.该版本支持一
些新的特点,如:呼叫者ID,特殊的响铃等.
该升级版可到如下网址下载:
http://www.microsoft.com/kb/articles/Q139/3/83.htm
原有的Unimodem的版本是UMDM32.DLL 4.00。UnimodemV用4.10版本替换了该动态
链接库。
如何发现一个DLL的版本信息呢?
下面类实现了接受DLL版本信息:
Class header file:
/* For some odd reason, Microsoft published a sample code that uses shlwapi.h
(and shlwapi.lib)
to tinker file versions.
This header file could not be found anywhere !!!
Not in Visual C++ 4.2, Visual C++ 5.0 or MSDN versions up to July 97`.
So, I just took out the interesting structures from scraps I found
and re-defined them here.
*/
// Remember: You must link version.lib to the project for this class to work !!
// 切记:为使该类正常工作,你必须将version.lib链接到你的项目中!!
#ifndef _DLL_VERSION_H_
#define _DLL_VERSION_H_
#ifndef DLLVERSIONINFO
typedef struct _DllVersionInfo
{
DWORD cbSize;
DWORD dwMajorVersion;
DWORD dwMinorVersion;
DWORD dwBuildNumber;
DWORD dwPlatformID;
}DLLVERSIONINFO;
#endif
#ifndef DLLGETVERSIONPROC
typedef int (FAR WINAPI *DLLGETVERSIONPROC) (DLLVERSIONINFO *);
#endif
class CDLLVersion
{
typedef enum { WIN_DIR, // Windows directory (e.g.: "C:\Windows\")
SYS_DIR, // Windows system directory (e.g.: "C:\Windows\System")
CUR_DIR, // Current directory (e.g.: ".")
NO_DIR} // No directory (path in file name)
FileLocationType; // Possible ways to add a path prefix to a file
public:
CDLLVersion (LPSTR szDLLFileName) :
m_dwMajor (0),
m_dwMinor (0),
m_dwBuild (0)
{
m_bValid = GetDLLVersion (szDLLFileName, m_dwMajor, m_dwMinor, m_dwBuild);
}
virtual ~CDLLVersion () {};
DWORD GetMajorVersion ()
{
return m_dwMajor;
}
DWORD GetMinorVersion ()
{
return m_dwMinor;
}
DWORD GetBuildNumber ()
{
return m_dwBuild;
}
BOOL IsValid ()
{
return m_bValid;
}
private:
BOOL GetDLLVersion (LPSTR szDLLFileName,
DWORD &dwMajor, DWORD &dwMinor, DWORD &dwBuildNumber);
BOOL CheckFileVersion (LPSTR szFileName, FileLocationType FileLoc,
DWORD &dwMajor, DWORD &dwMinor, DWORD &dwBuildNumber);
BOOL ParseVersionString (LPSTR lpVersion,
DWORD &dwMajor, DWORD &dwMinor, DWORD &dwBuildNumber);
BOOL FixFilePath (char * szFileName, FileLocationType FileLoc);
DWORD m_dwMajor, // Major version number
m_dwMinor, // Minor version number
m_dwBuild; // Build number
BOOL m_bValid; // Is the DLL version information valid ?
};
#endif
这里是实现部分:
#include "DLLVersion.h"
/**********************************************************
Function: GetDLLVersion
Purpose: Retrieves DLL major version, minor version and build numbers
Input: DLL file name
Reference to Major number
Reference to Minor number
Reference to Build number
Output: TRUE only if successful
Remarks: This function first tries to get the DLL version the nice way,
that is, call the DllGetVersion function in the DLL.
If this fails, it tries to located the DLL file in the file system,
read the file information block and retrieve the file version.
****************************************************************************/
BOOL CDLLVersion::GetDLLVersion (LPSTR szDLLFileName,
DWORD &dwMajor, DWORD &dwMinor, DWORD &dwBuildNumber)
{
HINSTANCE hDllInst; // Instance of loaded DLL
char szFileName [_MAX_PATH]; // Temp file name
BOOL bRes = TRUE; // Result
lstrcpy (szFileName, szDLLFileName); // Save a file name copy for the loading
hDllInst = LoadLibrary(TEXT(szFileName)); //load the DLL
if(hDllInst) { // Could successfully load the DLL
DLLGETVERSIONPROC pDllGetVersion;
/*
You must get this function explicitly because earlier versions of the DLL
don't implement this function. That makes the lack of implementation of the
function a version marker in itself.
*/
pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hDllInst,
TEXT("DllGetVersion"));
if(pDllGetVersion) { // DLL supports version retrieval function
DLLVERSIONINFO dvi;
ZeroMemory(&dvi, sizeof(dvi));
dvi.cbSize = sizeof(dvi);
HRESULT hr = (*pDllGetVersion)(&dvi);
if(SUCCEEDED(hr)) { // Finally, the version is at our hands
dwMajor = dvi.dwMajorVersion;
dwMinor = dvi.dwMinorVersion;
dwBuildNumber = dvi.dwBuildNumber;
} else
bRes = FALSE; // Failure
} else // GetProcAddress failed, the DLL cannot tell its version
bRes = FALSE; // Failure
FreeLibrary(hDllInst); // Release DLL
} else
bRes = FALSE; // DLL could not be loaded
if (!bRes) // Cannot read DLL version the nice way
return CheckFileVersion (szFileName, SYS_DIR,
dwMajor, dwMinor, dwBuildNumber); // Try the ugly way
else
return TRUE;
}
/***************************************************************************
Function: CheckFileVersion
Purpose: Check the version information of a given file
Input: File name
File location (Windows dir, System dir, Current dir or none)
Reference to Major number
Reference to Minor number
Reference to Build number
Output: TRUE only if successful
Remarks: Trashes original file name
****************************************************************************/
BOOL CDLLVersion::CheckFileVersion (LPSTR szFileName, FileLocationType FileLoc,
DWORD &dwMajor, DWORD &dwMinor,
DWORD &dwBuildNumber)
{
LPSTR lpVersion; // String pointer to 'version' text
UINT uVersionLen;
DWORD dwVerHnd=0; // An 'ignored' parameter, always '0'
FixFilePath (szFileName, FileLoc); // Add necessary path prefix to file name
DWORD dwVerInfoSize = GetFileVersionInfoSize (szFileName, &dwVerHnd);
if (!dwVerInfoSize) // Cannot reach the DLL file
return FALSE;
LPSTR lpstrVffInfo =
(LPSTR) malloc (dwVerInfoSize); // Alloc memory for file info
if (lpstrVffInfo == NULL)
return FALSE; // Allocation failed
// Try to get the info
if (!GetFileVersionInfo(szFileName, dwVerHnd, dwVerInfoSize, lpstrVffInfo)) {
free (lpstrVffInfo);
return FALSE; // Cannot read the file information -
// wierd, since we could read the information size
}
/* 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
*/
if (!VerQueryValue ( lpstrVffInfo,
(LPSTR) (TEXT("\\StringFileInfo\\040904E4\\FileVersion")),
(LPVOID *)&lpVersion, (UINT *)&uVersionLen)) {
free (lpstrVffInfo);
return FALSE; // Query was unsuccessful
}
// Now we have a string that looks like this :
// "MajorVersion.MinorVersion.BuildNumber", so let's parse it
BOOL bRes = ParseVersionString (lpVersion, dwMajor, dwMinor, dwBuildNumber);
free (lpstrVffInfo);
return bRes;
}
/***************************************************************************
Function: ParseVersionString
Purpose: Parse version information string into 3 different numbers
Input: The version string formatted as "MajorVersion.MinorVersion.BuildNumber"
Reference to Major number
Reference to Minor number
Reference to Build number
Output: TRUE only if successful
Remarks:
****************************************************************************/
BOOL CDLLVersion::ParseVersionString (LPSTR lpVersion,
DWORD &dwMajor, DWORD &dwMinor,
DWORD &dwBuildNumber)
{
// Get first token (Major version number)
LPSTR token = strtok( lpVersion, TEXT (".") );
if (token == NULL) // End of string
return FALSE; // String ended prematurely
dwMajor = atoi (token);
token = strtok (NULL, TEXT (".")); // Get second token (Minor version number)
if (token == NULL) // End of string
return FALSE; // String ended prematurely
dwMinor = atoi (token);
token = strtok (NULL, TEXT (".")); // Get third token (Build number)
if (token == NULL) // End of string
return FALSE; // String ended prematurely
dwBuildNumber = atoi (token);
return TRUE;
}
/***************************************************************************
Function: FixFilePath
Purpose: Adds the correct path string to a file name according
to given file location
Input: Original file name
File location (Windows dir, System dir, Current dir or none)
Output: TRUE only if successful
Remarks: Trashes original file name
****************************************************************************/
BOOL CDLLVersion::FixFilePath (char * szFileName, FileLocationType FileLoc)
{
char szPathStr [_MAX_PATH]; // Holds path prefix
switch (FileLoc) {
case WIN_DIR:
// Get the name of the windows directory
if (GetWindowsDirectory (szPathStr, _MAX_PATH) == 0)
return FALSE; // Cannot get windows directory
break;
case SYS_DIR:
// Get the name of the windows SYSTEM directory
if (GetSystemDirectory (szPathStr, _MAX_PATH) == 0)
return FALSE; // Cannot get system directory
break;
case CUR_DIR:
// Get the name of the current directory
if (GetCurrentDirectory (_MAX_PATH, szPathStr) == 0)
return FALSE; // Cannot get current directory
break;
case NO_DIR:
lstrcpy (szPathStr,"");
break;
default:
return FALSE;
}
lstrcat (szPathStr, _T("\\"));
lstrcat (szPathStr, szFileName);
lstrcpy (szFileName, szPathStr);
return TRUE;
}