;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; FileName: VerInfo3.asm
; Function: Demo the way to get file's version information and language
; Author: Purple Endurer
;
; LOG
; ----------------------------------------------------------------------------------------
; 2006-11-22 Can display in CN
; 2006-11-20 Added comments!
; 2006-09-14 Created!
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
.386
.model flat, stdcall
option casemap: none
include /masm32/ include/windows.inc
include /masm32/ include/kernel32.inc
includelib /masm32/ lib/kernel32.lib
include /masm32/ include/user32.inc
includelib /masm32/ lib/user32.lib
include /masm32/ include/shell32.inc
includelib /masm32/ lib/shell32.lib
include /masm32/ include/comdlg32.inc
includelib /masm32/ lib/comdlg32.lib
include /masm32/ include/version.inc
includelib /masm32/ lib/version.lib
WinMain PROTO : DWORD, : DWORD, : DWORD, : DWORD
ResizeConctrol PROTO
ShowVerInfo PROTO :LPSTR
btnShow_Click PROTO
btnBrowse_Click PROTO
;.const
IDC_BtnBrowse equ 101
IDC_BtnShow equ 103
IDC_EdtFileSpec equ 105
IDC_EdtVerInfo equ 107
c_BufLen EQU MAX_PATH
c_EditFileSpecLeft equ 2
c_EditFileSpecTop equ 5
c_EditFileSpecWidth equ 300
c_EditFileSpecHeight equ 20
c_BtnBrowseTop equ c_EditFileSpecTop
c_BtnBrowseLeft equ (c_EditFileSpecLeft+c_EditFileSpecWidth+10)
c_BtnBrowseWidth equ 70
c_BtnBrowseHeight equ c_EditFileSpecHeight
c_BtnShowTop equ c_EditFileSpecTop
c_BtnShowLeft equ (c_BtnBrowseLeft+c_BtnBrowseWidth+10)
c_BtnShowWidth equ 70
c_BtnShowHeight equ c_BtnBrowseHeight
c_EdtVerInfoLeft equ 2
c_EdtVerInfoTop equ 30
c_EdtVerInfoWidth equ c_BtnShowLeft+c_BtnShowWidth+2
c_EdtVerInfoHeight equ 165
c_WinWidth equ c_EdtVerInfoLeft+c_EdtVerInfoWidth+10
c_WinHeight equ c_EdtVerInfoTop+c_EdtVerInfoHeight+30
m_CatStr MACRO szStr: REQ
invoke SendMessage, g_hEditVerInfo, EM_REPLACESEL, FALSE, ADDR szStr
ENDM
m_GoNextLine MACRO
invoke SendMessage, g_hEditVerInfo, EM_REPLACESEL, FALSE, ADDR g_szCR
ENDM
.data
g_szClsName db "FileVerInfoCls", 0
g_szAppName db "文件版本信息", 0
g_szEditCls db "EDIT", 0
g_szBtnCls db "button", 0
g_szBtnBrowseText db "&B 浏览", 0
g_szBtnShowText db "&S 显示", 0
g_szEnterFileErr db "请先输入文件说明符", 0
g_szFailGetVerSize db "获取文件版本信息大小失败!", 0
g_szFailAllocMem db "申请内存失败!", 0
g_szFailGetVerInfo db "获取文件版本信息失败!", 0
g_szFailFailGetLangPage db "获取语言和代码页失败!", 0
g_szCR db 0dh, 0ah, 0
g_szOp db "properties", 0
g_szPeFileFilter db "*.EXE;*.DLL",0, "*.EXE;*.DLL", 0, 0
.data?
g_hInstance HINSTANCE ?
g_hWndMain HANDLE ?
g_hEditFileSpec HANDLE ?
g_hBtnShow HANDLE ?
g_hBtnBrowse HANDLE ?
g_hEditVerInfo HANDLE ?
g_szFileSpec db c_BufLen dup (?)
g_ofn OPENFILENAME <?>
g_ShlExecInfo SHELLEXECUTEINFO <?>
.code
start:
invoke GetModuleHandle, NULL
mov g_hInstance, eax
invoke WinMain, g_hInstance, NULL, NULL, SW_SHOWDEFAULT
invoke ExitProcess, eax
WinMain proc hInst: DWORD, hPrevInst: DWORD, CmdLine: DWORD, CmdShow: DWORD
LOCAL wc: WNDCLASSEX
LOCAL msg: MSG
LOCAL hwnd: HWND
mov wc.cbSize, SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
mov eax, g_hInstance
mov wc.hInstance, eax
mov wc.hbrBackground, COLOR_APPWORKSPACE
mov wc.lpszMenuName, NULL
mov wc.lpszClassName, OFFSET g_szClsName
invoke LoadIcon, NULL, IDI_APPLICATION
mov wc.hIcon, eax
mov wc.hIconSm, eax
invoke LoadCursor, NULL, IDC_ARROW
mov wc.hCursor, eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx, WS_EX_TOPMOST, ADDR g_szClsName,/
ADDR g_szAppName, WS_OVERLAPPEDWINDOW+WS_VISIBLE,/
CW_USEDEFAULT, CW_USEDEFAULT, c_WinWidth, c_WinHeight,/
NULL, NULL, hInst, NULL
mov hwnd, eax
.while TRUE
invoke GetMessage, ADDR msg, NULL, 0, 0
.BREAK .IF (! eax)
;--- process keystrokes directly in the message loop
.if msg.message == WM_SYSKEYUP
.if msg.wParam == VK_B ; Alt + B
invoke PostMessage, hwnd, WM_COMMAND, IDC_BtnBrowse, BM_CLICK
.elseif msg.wParam == VK_S ; Alt + S
invoke PostMessage, hwnd, WM_COMMAND, IDC_BtnShow, BM_CLICK
.endif
.endif
; ------------------------------------------------
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.endw
mov eax, msg.wParam
ret
WinMain endp
WndProc proc hWnd: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM
LOCAL rect: RECT
LOCAL hdc: DWORD
.if uMsg==WM_CREATE
mov eax, hWnd
mov g_hWndMain, eax
;--- Create file spec editbox
invoke CreateWindowEx, NULL, offset g_szEditCls, NULL,
WS_CHILD+WS_VISIBLE+ES_AUTOHSCROLL+WS_BORDER,/
c_EditFileSpecLeft, c_EditFileSpecTop, c_EditFileSpecWidth, c_EditFileSpecHeight,/
hWnd, IDC_EdtFileSpec, g_hInstance, NULL
mov g_hEditFileSpec, eax
;--- Create browse button
invoke CreateWindowEx, NULL, offset g_szBtnCls, offset g_szBtnBrowseText,/
WS_CHILD+WS_VISIBLE, c_BtnBrowseLeft, c_BtnBrowseTop, c_BtnBrowseWidth, c_BtnBrowseHeight,/
hWnd, IDC_BtnBrowse, g_hInstance, NULL
mov g_hBtnBrowse, eax
;--- Create show button
invoke CreateWindowEx, NULL, offset g_szBtnCls, offset g_szBtnShowText,/
WS_CHILD+WS_VISIBLE, c_BtnShowLeft, c_BtnShowTop, c_BtnShowWidth, c_BtnShowHeight,/
g_hWndMain, IDC_BtnShow, g_hInstance, NULL
mov g_hBtnShow, eax
;--- Create file ver info editbox
invoke CreateWindowEx, NULL, addr g_szEditCls, NULL,/
WS_CHILD+WS_VISIBLE+ES_MULTILINE+WS_HSCROLL+WS_VSCROLL+WS_BORDER,/
c_EdtVerInfoLeft, c_EdtVerInfoTop, c_EdtVerInfoWidth, c_EdtVerInfoHeight,/
g_hWndMain, IDC_EdtVerInfo, g_hInstance, NULL
mov g_hEditVerInfo, eax
;--- Initialize OPENFILENAME structure
invoke RtlZeroMemory, offset g_ofn, sizeof g_ofn
mov g_ofn.lStructSize, sizeof OPENFILENAME
mov eax, g_hInstance
mov g_ofn.hInstance, eax
mov g_ofn.nMaxFile, c_BufLen
mov g_ofn.Flags, OFN_HIDEREADONLY + OFN_FILEMUSTEXIST + OFN_PATHMUSTEXIST + OFN_EXPLORER
mov g_ofn.lpstrFilter, OFFSET g_szPeFileFilter
mov g_ofn.lpstrFile, OFFSET g_szFileSpec
mov eax, g_hWndMain
mov g_ofn.hWndOwner, eax
;--- Initialize SHELLEXECUTEINFO structure
invoke RtlZeroMemory, offset g_ShlExecInfo, sizeof SHELLEXECUTEINFO
mov g_ShlExecInfo.cbSize, sizeof g_ShlExecInfo
mov g_ShlExecInfo.fMask, SEE_MASK_INVOKEIDLIST
mov g_ShlExecInfo.lpVerb, offset g_szOp
mov g_ShlExecInfo.lpFile, offset g_szFileSpec
.elseif uMsg==WM_COMMAND
.IF lParam
mov edx, wParam
mov eax, edx
shr edx, 16
.if dx == BN_CLICKED
.IF ax == IDC_BtnShow
invoke btnShow_Click
.else
invoke btnBrowse_Click
.endif
.ENDIF
.endif
.elseif uMsg==WM_DESTROY
invoke PostQuitMessage, NULL
.elseif uMsg==WM_SIZE
invoke ResizeConctrol
xor eax, eax
jz @F
.else
@@:
invoke DefWindowProc, hWnd, uMsg, wParam, lParam
ret
.endif
xor eax, eax
ret
WndProc endp
btnShow_Click proc
invoke GetWindowText, g_hEditFileSpec, ADDR g_szFileSpec, SIZEOF g_szFileSpec
.IF eax==0
invoke MessageBox, g_hWndMain, OFFSET g_szEnterFileErr, OFFSET g_szAppName, MB_ICONERROR+MB_OK
.ELSE
;--- clear the file ver info box
invoke SendMessage, g_hEditVerInfo, WM_SETTEXT, 0, NULL
invoke ShowVerInfo, OFFSET g_szFileSpec
.if eax > 0
.IF eax==1
mov eax, OFFSET g_szFailGetVerSize
.ELSEIF eax==2
mov eax, OFFSET g_szFailAllocMem
.ELSEIF eax==3
mov eax, OFFSET g_szFailGetVerInfo
.ELSEIF eax==4
mov eax, OFFSET g_szFailFailGetLangPage
.ENDIF
invoke MessageBox, g_hWndMain, eax, OFFSET g_szAppName, MB_ICONERROR+MB_OK
.else
invoke ShellExecuteEx, offset g_ShlExecInfo
.endif
.ENDIF
ret
btnShow_Click endp
btnBrowse_Click proc
invoke GetOpenFileName, ADDR g_ofn
.if eax != 0
invoke SendMessage, g_hEditFileSpec, WM_SETTEXT, 0, OFFSET g_szFileSpec
.endif
ret
btnBrowse_Click endp
ResizeConctrol PROC
LOCAL st_Rect: RECT
invoke GetClientRect, g_hWndMain, ADDR st_Rect
;--- Resize the Show button
mov eax, st_Rect.right
sub eax, 5+c_BtnShowWidth
push eax
invoke MoveWindow, g_hBtnShow, eax, c_BtnShowTop, c_BtnShowWidth, c_BtnShowHeight, TRUE
;--- Resize the Show button
pop eax
sub eax, 5+c_BtnShowWidth
push eax
invoke MoveWindow, g_hBtnBrowse, eax, c_BtnBrowseTop, c_BtnBrowseWidth, c_BtnBrowseHeight, TRUE
;--- Resize the file spec editbox
pop eax
sub eax, 10
invoke MoveWindow, g_hEditFileSpec, c_EditFileSpecLeft, c_EditFileSpecTop, eax, c_EditFileSpecHeight, TRUE
;--- Resize the Ver info editbox
mov eax, st_Rect.right
sub eax, 5
mov edi, st_Rect.bottom
sub edi, 30
invoke MoveWindow, g_hEditVerInfo, c_EdtVerInfoLeft, c_EdtVerInfoTop, eax, edi, TRUE
ret
ResizeConctrol ENDP
;/
; Result:
; eax == 0 sucess
; eax == 1 Fail to get file ver info size
; eax == 2 Fail to alloc global memory
; eax == 3 Fail to get file ver info
; eax == 4 Fail to get the language id and code page
;/
ShowVerInfo PROC lpszFileSpec: LPSTR
LOCAL dwBufSize: DWORD
LOCAL hMem: HANDLE
LOCAL bInfoStr[MAX_PATH]: byte
LOCAL lpszValue: LPSTR
LOCAL bLangCharset[9]: byte
invoke GetFileVersionInfoSize, lpszFileSpec, ADDR dwBufSize
or eax , eax
jnz @F
mov eax, 1
ret
@@:
mov dwBufSize, eax
invoke GlobalAlloc, GMEM_ZEROINIT, eax
cmp eax, NULL
jnz @F
mov eax, 2
ret
@@:
mov hMem, eax
; BOOL GetFileVersionInfo(
; LPTSTR lptstrFilename, // pointer to filename string
; DWORD dwHandle, // ignored
; DWORD dwLen, // size of buffer
; LPVOID lpData // pointer to buffer to receive file-version info.
; );
invoke GetFileVersionInfo, lpszFileSpec, 0, dwBufSize, hMem
or eax, eax
jnz @F
invoke GlobalFree, hMem
mov eax, 3
ret
g_szTranslation db "/VarFileInfo/Translation", 0
@@:
; BOOL VerQueryValue(
; const LPVOID pBlock, // address of buffer for version resource
; LPTSTR lpSubBlock, // address of value to retrieve
; LPVOID *lplpBuffer, // address of buffer for version pointer
; PUINT puLen // address of version-value length buffer
; );
invoke VerQueryValue, hMem, OFFSET g_szTranslation, ADDR lpszValue, ADDR dwBufSize
or eax, eax
jnz @F
invoke GlobalFree, hMem
mov eax, 4
ret
g_szProductName db 'ProductName', 0
g_szProductVersion db 'ProductVersion', 0
g_szFileDescription db 'FileDescription', 0
g_szLegalCopyright db 'LegalCopyright', 0
g_szFileVersion db 'FileVersion', 0
g_szCompanyName db 'CompanyName', 0
g_szLegalTradeMarks db 'LegalTradeMarks', 0
g_szInternalName db 'InternalName', 0
g_szOriginalFileName db 'OriginalFileName', 0
g_szComments db "Comments", 0
g_lpszInfo label dword
dword OFFSET g_szFileVersion
dword OFFSET g_szFileDescription
dword OFFSET g_szLegalCopyright
dword OFFSET g_szComments
dword OFFSET g_szProductVersion
dword OFFSET g_szProductName
dword OFFSET g_szCompanyName
dword OFFSET g_szLegalTradeMarks
dword OFFSET g_szInternalName
dword OFFSET g_szOriginalFileName
c_lpszInfoLen equ ($-g_lpszInfo)/4
c_language_cn equ 1
if c_language_cn eq 1
g_szProductName_cn db '产品名称', 0
g_szProductVersion_cn db '产品版本', 0
g_szFileDescription_cn db '说明', 0
g_szLegalCopyright_cn db '版权', 0
g_szFileVersion_cn db '文件版本', 0
g_szCompanyName_cn db '公司名称', 0
g_szLegalTradeMarks_cn db '合法商标', 0
g_szInternalName_cn db '内部名称', 0
g_szOriginalFileName_cn db '源文件名', 0
g_szComments_cn db "备注", 0
g_lpszInfo_cn label dword
dword OFFSET g_szFileVersion_cn
dword OFFSET g_szFileDescription_cn
dword OFFSET g_szLegalCopyright_cn
dword OFFSET g_szComments_cn
dword OFFSET g_szProductVersion_cn
dword OFFSET g_szProductName_cn
dword OFFSET g_szCompanyName_cn
dword OFFSET g_szLegalTradeMarks_cn
dword OFFSET g_szInternalName_cn
dword OFFSET g_szOriginalFileName_cn
c_lpszInfo_cn_Len equ ($-g_lpszInfo_cn)/4
g_szLang_cn db "语言"
g_szBlkColonBlk db " : ", 0
else
g_szLang db "Langeage"
g_szBlkColonBlk db " : ", 0
endif
g_szPre db 'StringFileInfo/', 0 ;080404B0
g_szInfoFmt db "%s%s/%s", 0
g_szHexFmt db "%08X", 0
@@:
;--- Now, lpszValue is a pointer to four 4 bytes of Hex number,
; first two bytes are language id, and last two bytes are code page.
; However, Lang_Charset_String needs a string of 4 hex digits,
; the first two characters correspond to the language id
; and last two the last two character correspond to the code page id.
if c_language_cn eq 1
m_CatStr g_szLang_cn
else
m_CatStr g_szLang
endif
mov eax, lpszValue
mov eax, [ eax]
push eax
;---Get the description string
; DWORD VerLanguageName(
; DWORD wLang, // Microsoft language identifier
; LPTSTR szLang, // pointer to buffer for language description string
; DWORD nSize // size of buffer
; );
movzx eax, ax
mov dwBufSize, eax
invoke VerLanguageName, dwBufSize, ADDR bInfoStr, MAX_PATH
or eax, eax
jz @F
m_CatStr bInfoStr
@@:
m_GoNextLine
pop eax
;--- Change the order of the language id and code page
rol eax, 16
;--- Convert the language id and code page into a 8 bytes Hex string representation
invoke wsprintf, ADDR bLangCharset, ADDR g_szHexFmt, eax
;--- For example, the language id and code page may look like 040904E4
; Or to pull it all apart:
; 04------ = SUBLANG_ENGLISH_USA
; --09---- = LANG_ENGLISH
; ----04E4 = 1252 = Codepage for Windows:Multilingual
c_showTranslation equ 0
if c_showTranslation eq 1
; --- Show the language id and code page in editbox
m_CatStr g_szTranslation
m_CatStr g_szBlkColonBlk
m_CatStr bLangCharset
m_GoNextLine
endif
xor eax, eax
.while eax < c_lpszInfoLen
push eax
or eax, eax
jz @F
shl eax, 2 ; eax<--eax * 4
@@:
push eax
if c_language_cn eq 1
invoke SendMessage, g_hEditVerInfo, EM_REPLACESEL, FALSE, [ eax+g_lpszInfo_cn]
else
invoke SendMessage, g_hEditVerInfo, EM_REPLACESEL, FALSE, [ eax+g_lpszInfo]
endif
m_CatStr g_szBlkColonBlk
pop eax
invoke wsprintf, ADDR bInfoStr, ADDR g_szInfoFmt, OFFSET g_szPre, ADDR bLangCharset, [ eax+g_lpszInfo]
invoke VerQueryValue, hMem, ADDR bInfoStr, ADDR lpszValue, ADDR dwBufSize
or eax, eax
jz @F
invoke SendMessage, g_hEditVerInfo, EM_REPLACESEL, FALSE, lpszValue
@@:
m_GoNextLine
pop eax
inc eax
.endw
invoke GlobalFree, hMem
xor eax, eax
ret
ShowVerInfo ENDP
end