[11-22]MASM32编程获取文件语言、版本信息v3

来源:互联网 发布:淘宝分销招募书 编辑:程序博客网 时间:2024/05/18 03:28
;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; 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 flatstdcall
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, FALSEADDR szStr
ENDM

m_GoNextLine MACRO
    invoke SendMessage, g_hEditVerInfo, EM_REPLACESEL, FALSEADDR 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 eaxedx
            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 eaxeax
        jz @F
    .else
@@:
        invoke DefWindowProc, hWnd, uMsg, wParam, lParam        
        ret
    .endif
    xor eaxeax
    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 eaxOFFSET g_szFailGetVerSize
            .ELSEIF eax==2 
                mov eaxOFFSET g_szFailAllocMem
            .ELSEIF eax==3
                mov eaxOFFSET g_szFailGetVerInfo
            .ELSEIF eax==4
                mov eaxOFFSET g_szFailFailGetLangPage
            .ENDIF
            invoke MessageBox, g_hWndMain, eaxOFFSET 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, eaxediTRUE

    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 eaxeax
    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 eaxeax
    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 eaxax
    mov dwBufSize, eax
    invoke VerLanguageName, dwBufSize, ADDR bInfoStr, MAX_PATH
    or eaxeax
    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 eaxeax
    .while eax < c_lpszInfoLen
        push eax
        or eaxeax
        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 eaxeax
        jz @F
        invoke SendMessage, g_hEditVerInfo, EM_REPLACESEL, FALSE, lpszValue
    @@:
        m_GoNextLine
        pop eax
        inc eax
    .endw
    invoke GlobalFree, hMem
    xor eaxeax
    ret
ShowVerInfo ENDP


end start