Win32汇编--使用资源—版本信息资源
有时应用程序需要确保自己运行时使用某一特定版本的DLL,以便确保可以使用某些函数。检测版本是通过API函数查询定义于资源中的版本信息来完成的,如果资源中没有定义版本,那么就无法知道一个文件的版本究竟是多少。
版本信息是以VERSIONINFO类型的资源保存在应用程序中的,里面可以定义的信息包括文件的版本号、创建单位和语种等。版本信息的定义是可选的,一个程序可以不定义版本信息资源,如果定义了的话,也不一定要定义全部信息项目。
如果一个文件定义有版本信息资源,那么在文件的属性页(在文件图标上按鼠标右键,在弹出的菜单上选择)上就会有一个“版本”页面。
1、版本信息资源的定义
//Version.rc
1 VERSIONINFO
FILEVERSION 1,2,3,4
PRODUCTVERSION 2,3,4,5
FILEOS VOS_WINDOWS32
FILETYPE VFT_APP
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "VerFileInfo"
BEGIN
VALUE "Translation", 0x804, 0x4b0
END
BLOCK "StringFileInfo"
BEGIN
BLOCK "080404b0"
BEGIN
VALUE "Comments", "Here is Comments\0"
VALUE "CompanyName", "Here is CompanyName\0"
VALUE "FileDescription", "Here is FileDescription\0"
VALUE "FileVersion", "1,0,0,1\0"
VALUE "InternalName", "Here is InternalName\0"
VALUE "LegalCopyright", "Here is LegalCopyright\0"
VALUE "LegalTrademarks", "Here is LegalTrademarks\0"
VALUE "OriginalFilename", "Here is OriginalFilename\0"
VALUE "PrivateBuild", "Here is PrivateBuild\0"
VALUE "ProductName", "Here is ProductName\0"
VALUE "ProductVersion", "1,0,0,1\0"
VALUE "SpecialBuild", "Here is SpecialBuild\0"
END
END
END
这些定义语句的含义。首先,版本信息定义的语句格式是:
版本信息资源ID VERSIONINFO
固定属性
BEGIN
块声明定义
……
END
版本信息资源ID的取值必须为1,如果不为1则属性页上的“版本”信息是无法显示出来的。(怪异!)
可以定义的固定属性有:
l FILEVERSION——定义文件版本号,可以定义4个16位版本号xx.xx.xx.xx。
l PRODUCTVERSION——定义产品版本号,可以定义4个16位版本号xx.xx.xx.xx。
l FILELAGSMASK——指定FILELAGS属性中哪些位有效。
l FILELAGS——文件标志,是一些标志位的组合:VS_FF_PATCHED,VS_FF_DEBUG,VS_FF_PRIVATEBUILD,VS_FF_INFOINFERRED,VS_FF_PRERELEASE和VS_FF_SPECI_ALBUILD。
l FILEOS——定义适用的操作系统,可以定义为VOS_UNKNOWN,VOS_DOS,VOS_NT,VOS_WINDOWS16,VOS_WINDOWS32,VOS_DOS_WINDOWS16,VOS_DOW_WINDOWS32或VOS_NT_WINDOW32。
l FILETYPE——定义文件的子类型。当文件类型是VFT_DRV(驱动程序)的时候,这里可以是VFT2_UNKNOWN,VFT2_DRV_COMM,VFT2_DRV_PRINTER,VFT2_DRV_KEYBOARD,VFT2_DRV_LANGUAGE,VFT2_DRV_DISPLAY,VFT2_DRV_MOUSE,VFT2_DRV_NETWORK,VFT2_DRV_SYSTEM,VFT2_DRV_INSTALLABLE或VFT2_DRV_SOUND;当文件类型是VFT_FONT(字体)的时候,这里可以是VFT2_UNKNOWN,VFT2_FONT_RASTER,VFT2_FONT_VECTOR或VFT2_FONT_TRUETYPE。
当固定属性定义完成以后,需要定义一些块声明,块声明有两种:变量型的信息块和字符串类型的信息块,变量类型的信息块定义如下:
BLOCK “VerFileInfo”
BEGIN
VALUE “Translation”, 语言ID, 字符集ID
……
END
语言ID的常用值有0x0404(繁体中文)、0x0409(美国英语)和0x0804(简体中文),字符集ID的常用值有0(7位ASCII)、950(台湾GB5)和1200(Unicode)。一般使用0x804,0x4b0来定义,也就是简体中文和Unicode(0x4b0=1200)。其他还有很多取值,可以查看Rc.exe的帮助文件。
变量类型信息块用来表示VERSIONINFO资源中定义有哪些语言和字符集的字符串类型信息块。如上例中有一句VALUE “Translation”, 0x804, 0x4b0表示对应有一个名为“080404b0”的字符串类型的信息块。
字符串信息块的定义语句为:
BLOCK “StringFileInfo”
BEGIN
BLOCK “语言集”
BEGIN
VALUE “字符串名称”, “字符串”
……
END
END
语言集就是变量类型中定义的,其名称一定要是将语言ID和字符集ID组合成一个8位的16进制的格式,以上例文件来说明,当变量类型的信息块中定义0x804, 0x4b0时,语言集名称就是“080404b0”,在语言集块的定义中,还可以定义多条字符串型的版本信息,这些版本信息的字符串名有12种,如下表所示:
版本信息字符串类型
字符串名称
|
属性页位置
|
说明
|
Comments
|
备注
|
有关程序的附加说明信息
|
CompanyName
|
公司
|
开发产品的公司
|
FileDescription
|
描述
|
有关文件的简单描述
|
FileVersion
|
文件版本
|
如1.50、5.0.RC2等字符串型的版本信息
|
InternalName
|
内部名称
|
|
LegalCopyright
|
版权
|
文件的所有版权信息
|
LegalTrademarks
|
合法商标
|
文件的所有注册商标信息
|
OriginalFilename
|
源文件名
|
原始文件名,从这里可以得知文件是否被改名
|
PrivateBuild
|
个人用内部版本说明
|
作者私人信息
|
ProductName
|
产品名称
|
文件所属的产品名称
|
ProductVersion
|
产品版本
|
文件所属的产品的版本号
|
SpecialBuild
|
特殊内部版本说明
|
特殊说明
|
定义版本信息字符串的时候要注意,所有的字符串必须是以NULL结尾的串,所以要在字符串尾加上\0。
Demo:给exe添加版本信息
//VersionInfo.rc
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#include <resource.h>
#include <Version.h>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define ICO_MAIN 0x1000 //图标
ICO_MAIN ICON "Main.ico"
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
1 VERSIONINFO
FILEVERSION 1,2,3,4
PRODUCTVERSION 2,3,4,5
FILEOS VOS_WINDOWS32
FILETYPE VFT_APP
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x804, 0x4b0
END
BLOCK "StringFileInfo"
BEGIN
BLOCK "080404b0"
BEGIN
VALUE "Comments", "Here is Comments\0"
VALUE "CompanyName", "Here is CompanyName\0"
VALUE "FileDescription", "Here is FileDescription\0"
VALUE "FileVersion", "1,0,0,1\0"
VALUE "InternalName", "Here is InternalName\0"
VALUE "LegalCopyright", "Here is LegalCopyright\0"
VALUE "LegalTrademarks", "Here is LegalTrademarks\0"
VALUE "OriginalFilename", "Here is OriginalFilename\0"
VALUE "PrivateBuild", "Here is PrivateBuild\0"
VALUE "ProductName", "Here is ProductName\0"
VALUE "ProductVersion", "1,0,0,1\0"
VALUE "SpecialBuild", "Here is SpecialBuild\0"
END
END
END
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//Version.h
/******************************************
* VersionInfo Resource include file
* by LuoYunBin
******************************************/
#define VS_VERSION_INFO 1
#define VS_USER_DEFINED 100
#define VS_FFI_SIGNATURE 0x0FEEF04BD
#define VS_FFI_STRUCVERSION 0x10000
#define VS_FFI_FILEFLAGSMASK 0x3F
#define VS_FF_DEBUG 1
#define VS_FF_PRERELEASE 2
#define VS_FF_PATCHED 4
#define VS_FF_PRIVATEBUILD 8
#define VS_FF_INFOINFERRED 0x10
#define VS_FF_SPECIALBUILD 0x20
#define VOS_UNKNOWN 0
#define VOS_DOS 0x10000
#define VOS_OS216 0x20000
#define VOS_OS232 0x30000
#define VOS_NT 0x40000
#define VOS_BASE 0
#define VOS_WINDOWS16 1
#define VOS_PM16 2
#define VOS_PM32 3
#define VOS_WINDOWS32 4
#define VOS_DOS_WINDOWS16 0x10001
#define VOS_DOS_WINDOWS32 0x10004
#define VOS_OS216_PM16 0x20002
#define VOS_OS232_PM32 0x30003
#define VOS_NT_WINDOWS32 0x40004
#define VFT_UNKNOWN 0
#define VFT_APP 1
#define VFT_DLL 2
#define VFT_DRV 3
#define VFT_FONT 4
#define VFT_VXD 5
#define VFT_STATIC_LIB 7
#define VFT2_UNKNOWN 0
#define VFT2_DRV_PRINTER 1
#define VFT2_DRV_KEYBOARD 2
#define VFT2_DRV_LANGUAGE 3
#define VFT2_DRV_DISPLAY 4
#define VFT2_DRV_MOUSE 5
#define VFT2_DRV_NETWORK 6
#define VFT2_DRV_SYSTEM 7
#define VFT2_DRV_INSTALLABLE 8
#define VFT2_DRV_SOUND 9
#define VFT2_DRV_COMM 0x0A
#define VFT2_DRV_INPUTMETHOD 0x0B
#define VFT2_FONT_RASTER 1
#define VFT2_FONT_VECTOR 2
#define VFT2_FONT_TRUETYPE 3
//VersionInfo.asm
.386
.model flat, stdcall
option casemap :none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.const
szTitle db '提示...',0
szMessage db '请用鼠标右键单击本文件,再看看“属性”菜单项中的“版本”页!',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
invoke MessageBox,NULL,addr szMessage,addr szTitle,MB_OK or MB_ICONEXCLAMATION
invoke ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start
2、在程序中检测版本信息
Win32 API中有3个版本信息函数:GetFileVersionSize,GetFileVersionInfo和VerQueryValue,它们驻留在VERSION.DLL文件中,如果在源程序中使用它们,注意要加上include Version.inc以及includelib Version.lib语句。
用这3个函数获取版本信息的方法是:
首先调用GetFileVersionInfoSize函数检测文件中有没有版本信息资源:
invoke GetFileVersionInfoSize, addr szFile, NULL
其中szFile是要检测的PE文件名字符串,该函数的返回值是版本信息资源的长度,如果返回0,则表示文件不是PE文件或没有定义版本信息资源。
如果检测到文件中有版本信息资源,那么可以将版本信息资源读取到一缓冲区中,缓冲区的长度必须足够容纳上一步返回的资源长度,方法是:
invoke GetFileVersionInfo, addr szFile, NULL, sizeof dbVerInfo, addr dbVerInfo
其中dbVerInfo为一个足够大的缓冲区。该函数会把整个版本信息资源拷贝到这个缓冲区中。
拷贝到缓冲区中的信息有它自己的格式,必须用VerQueryValue去“解码”,解码固定属性的方法是:
invoke VerQueryValue, addr dbVerInfo, addr szRoot, addr lpBuffer, addr dwLen
第一个参数指向前一步返回的版本信息资源数据,第二个参数指向一个字符串:“\”,第三和第四个参数指向dw类型的变量lpBuffer和dwLen,返回到lpBuffer中的是指向一个VS_FIXEDFILEINFO结构的指针,这个结构中有定义的固定属性的内容。
如果要获取字符串类型信息块中的版本信息,那就比较复杂一点了,必须首先知道语言集的名称,所以先要获取版本信息资源中变量类型信息块的内容,方法是:
invoke VerQueryValue, addr dbVerInfo, addr szVarInfo, add lpBuffer, addr dwLen
mov eax, lpBuffer
mov eax, [eax]
ror eax, 16
szVarInfo是一个字符串:“\VarFileInfo\Translation”,这时函数在lpBuffer中返回语言集变量指针的指针,所以要先mov eax, lpBuffer,再用eax作指针用mov eax,[eax]得到语言集变量。语言集变量的高16位是字符集ID,低16位是语言ID,可以使用ror eax, 16来调换高低位,以我们的例子为例,现在eax中的值就是080404b0h了!
接下来就可以获取字符串版本信息了,先将语言集的值通过vsprintf函数转换成“080404b0”的形式,然后拼装成“\StringFileInfo\080404b0\字符串名称”形式的字符串,中间的“字符串名称”可以是上表中的12种名称之一,最后调用下面的语句(假定拼装好的字符串地址为szString)。
invoke VerQueryValue, addr dbVerInfo, addr szString, addr lpBuffer, addr dwLen
执行后lpBuffer中会得到一个指针,指向版本信息字符串定义的内容,这就是我们最后需要的东西!重复这个步骤可以得到所有12种字符串版本信息。
Demo:获得版本信息
//ShowVersionInfo.rc
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#include <resource.h>
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define ICO_MAIN 0x1000 //图标
#define DLG_MAIN 1
#define IDC_INFO 101
#define IDC_FILE 102
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN ICON "Main.ico"
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
DLG_MAIN DIALOG 138, 123, 231, 139
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "查看PE文件版本信息"
FONT 9, "宋体"
{
EDITTEXT IDC_INFO, 5, 5, 220, 110, ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | WS_BORDER | WS_VSCROLL | WS_TABSTOP
LTEXT "", IDC_FILE, 5, 123, 165, 8
DEFPUSHBUTTON "选择文件(&B)", IDOK, 175, 120, 50, 14
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// ShowVersionInfo.asm
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; ShowVersionInfo.asm
; 显示PE文件资源中版本信息的例子
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.386
.model flat, stdcall
option casemap :none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Include 文件定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
include Version.inc
includelib Version.lib
include comctl32.inc
includelib comctl32.lib
include comdlg32.inc
includelib comdlg32.lib
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Equ 等值定义
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
ICO_MAIN equ 1000h
DLG_MAIN equ 1
IDC_INFO equ 101
IDC_FILE equ 102
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 数据段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.data?
hInstance dd ?
szBuffer db 4096 dup(?)
.const
szPeFileExt db 'PE文件',0,'*.exe;*.dll;*.scr;*.drv',0,0
szError db '文件中没有包含版本信息!',0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 代码段
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.code
include GetVersionInfo.inc
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_ProcDlgMain proc uses ebx edi esi hWnd, wMsg, wParam, lParam
local @szBuffer[MAX_PATH]:byte
local @stOpenFileName:OPENFILENAME
mov eax,wMsg
.if eax == WM_CLOSE
invoke EndDialog, hWnd, NULL
.elseif eax == WM_INITDIALOG
;*******************************************************************
; 设置标题栏图标
;*******************************************************************
invoke LoadIcon, hInstance, ICO_MAIN
invoke SendMessage, hWnd, WM_SETICON, ICON_BIG, eax
.elseif eax == WM_COMMAND
mov eax, wParam
.if ax == IDOK
;*******************************************************************
; 打开一个选择文件的对话框
;*******************************************************************
invoke RtlZeroMemory, addr @stOpenFileName, sizeof OPENFILENAME
invoke RtlZeroMemory, addr @szBuffer, sizeof @szBuffer
mov @stOpenFileName.lStructSize, SIZEOF @stOpenFileName
mov @stOpenFileName.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST
push hWnd
pop @stOpenFileName.hwndOwner
mov @stOpenFileName.lpstrFilter, offset szPeFileExt
lea eax, @szBuffer
mov @stOpenFileName.lpstrFile, eax
mov @stOpenFileName.nMaxFile, MAX_PATH
invoke GetOpenFileName, addr @stOpenFileName
.if eax
;*******************************************************************
; 获取版本信息并显示出来
;*******************************************************************
invoke _GetVersionInfo, addr @szBuffer, addr szBuffer
.if eax
invoke SetDlgItemText, hWnd, IDC_FILE, addr @szBuffer
invoke SetDlgItemText, hWnd, IDC_INFO, addr szBuffer
.else
invoke MessageBox, hWnd, addr szError, NULL, MB_OK or MB_ICONHAND
.endif
.endif
.endif
;*******************************************************************
.else
mov eax, FALSE
ret
.endif
mov eax, TRUE
ret
_ProcDlgMain endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
invoke InitCommonControls
invoke GetModuleHandle, NULL
mov hInstance, eax
invoke DialogBoxParam, hInstance, DLG_MAIN, NULL, offset _ProcDlgMain, NULL
invoke ExitProcess, NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
end start
// GetVersionInfo.inc
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; Sample code for < Win32ASM Programming >
; by 罗云彬, http://asm.yeah.net
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; GetVersionInfo.inc
; 用来获取 PE 文件资源中版本信息的子程序
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 通过 include 语句包含到其它源程序中使用
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
.const
szRoot db '\',0
szVarInfo db '\VarFileInfo\Translation',0
szStrInfoFmt db '\StringFileInfo\%08x\',0
szArrow db ' --> ',0
szReturn db 0dh,0ah,0
szFixFileInfo db '固定版本信息属性:',0dh,0ah
db 'FileVersion: %d.%d.%d.%d',0dh,0ah
db 'ProductVersion: %d.%d.%d.%d',0dh,0ah
db 'FileOS: %08x',0dh,0ah
db 'FileType: %08x',0dh,0ah,0dh,0ah
db '字符串版本属性:',0dh,0ah,0
;********************************************************************
szStr1 db 'Comments',0
szStr2 db 'CompanyName',0
szStr3 db 'FileDescription',0
szStr4 db 'FileVersion',0
szStr5 db 'InternalName',0
szStr6 db 'LegalCopyright',0
szStr7 db 'LegalTrademarks',0
szStr8 db 'OriginalFilename',0
szStr9 db 'PrivateBuild',0
szStr10 db 'ProductName',0
szStr11 db 'ProductVersion',0
szStr12 db 'SpecialBuild',0
;********************************************************************
lpStr1 dd szStr1
lpStr2 dd szStr2
lpStr3 dd szStr3
lpStr4 dd szStr4
lpStr5 dd szStr5
lpStr6 dd szStr6
lpStr7 dd szStr7
lpStr8 dd szStr8
lpStr9 dd szStr9
lpStr10 dd szStr10
lpStr11 dd szStr11
lpStr12 dd szStr12
.code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 获取文件版本信息
; 入口参数:文件名,返回信息缓冲区
; 返回参数:TRUE = 成功,FALSE = 失败
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
_GetVersionInfo proc _lpFileName,_lpBuffer
local @dbVerInfo[4096]:byte
local @szStringInfo[128]:byte
local @szString[128]:byte
local @lpBuffer,@dwLen
local @dwVer1,@dwVer2,@dwVer3,@dwVer4
local @dwVer5,@dwVer6,@dwVer7,@dwVer8
pushad
invoke GetFileVersionInfoSize,_lpFileName,NULL
.if !eax
popad
xor eax,eax
ret
.endif
invoke GetFileVersionInfo,_lpFileName,NULL,sizeof @dbVerInfo,addr @dbVerInfo
;********************************************************************
; 获取固定属性
;********************************************************************
invoke VerQueryValue,addr @dbVerInfo,addr szRoot,addr @lpBuffer,addr @dwLen
mov esi,@lpBuffer
assume esi:ptr VS_FIXEDFILEINFO
;********************************************************************
; 计算版本号
;********************************************************************
mov eax,[esi].dwFileVersionMS
movzx ecx,ax
mov @dwVer2,ecx
shr eax,16
mov @dwVer1,eax
mov eax,[esi].dwFileVersionLS
movzx ecx,ax
mov @dwVer4,ecx
shr eax,16
mov @dwVer3,eax
mov eax,[esi].dwProductVersionMS
movzx ecx,ax
mov @dwVer6,ecx
shr eax,16
mov @dwVer5,eax
mov eax,[esi].dwProductVersionLS
movzx ecx,ax
mov @dwVer8,ecx
shr eax,16
mov @dwVer7,eax
invoke wsprintf,_lpBuffer,addr szFixFileInfo,\
@dwVer1,@dwVer2,@dwVer3,@dwVer4,\
@dwVer5,@dwVer6,@dwVer7,@dwVer8,\
[esi].dwFileOS,[esi].dwFileType
assume esi:nothing
;********************************************************************
; 获取语言集
;********************************************************************
invoke VerQueryValue,addr @dbVerInfo,addr szVarInfo,addr @lpBuffer,addr @dwLen
mov eax,@lpBuffer
mov eax,[eax]
ror eax,16
invoke wsprintf,addr @szStringInfo,addr szStrInfoFmt,eax
;********************************************************************
; 获取字符串版本信息
;********************************************************************
mov ebx,offset lpStr1
.while ebx <= offset lpStr12
invoke lstrcpy,addr @szString,addr @szStringInfo
mov eax,[ebx]
invoke lstrcat,addr @szString,eax
mov eax,[ebx]
invoke lstrcat,_lpBuffer,eax
invoke lstrcat,_lpBuffer,addr szArrow ;加上 -->
invoke VerQueryValue,addr @dbVerInfo,addr @szString,addr @lpBuffer,addr @dwLen
.if eax
invoke lstrcat,_lpBuffer,@lpBuffer ;加上获得的版本信息
.endif
invoke lstrcat,_lpBuffer,addr szReturn ;加上回车
add ebx,4
.endw
popad
mov eax,TRUE
ret
_GetVersionInfo endp
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>