HOWTO: Retrieve Language and Code Page id Using VerQueryValue

Last reviewed: July 15, 1997
Article ID: Q160042
4.00 WINDOWS | WINDOWS NT kbusage kbhowto

The information in this article applies to:

  • Standard, Professional, and Enterprise Editions of Microsoft Visual Basic, 32-bit only for Windows,, version 4.0

SUMMARY

Using the VerQueryValue API, the language identifier and the character set identifier can be retrieved from the version-information resource within a file. You can concatenate these two identifiers to form a hexadecimal string and pass the string to another VerQueryValue call to retrieve the following version information: CompanyName, FileDescription, FileVersion, InternalName, LegalCopyright, OriginalFileName, ProductName, and ProductVersion.

This article presents a Visual Basic 4.0 32-bit sample application that retrieves the language identifier, the character set identifier, and the information mentioned above for the Windows system file, gdi32.dll.

This article also supplements the following Microsoft Knowledge Base article that extracts a VS_FIXEDFILEINFO structure from a file's version- information resource:

   ARTICLE-ID: Q139491
   TITLE     : How To Use Functions in VERSION.DLL - A 32-bit Sample App

MORE INFORMATION

Step-by-Step Example

  1. Start Visual Basic. If it is already running, choose New Project from the File menu. Form1 is created by default.

  2. Add a CommandButton, Command1, to Form1.

  3. Add a ListBox, List1, to Form1.

  4. Add a module, Module1, to the project. Copy and paste the following code to Module1:

    Declare Function GetFileVersionInfo Lib "Version.dll" Alias _
       "GetFileVersionInfoA" (ByVal lptstrFilename As String, ByVal _
       dwhandle As Long, ByVal dwlen As Long, lpData As Any) As Long
    Declare Function GetFileVersionInfoSize Lib "Version.dll" Alias _
       "GetFileVersionInfoSizeA" (ByVal lptstrFilename As String, _
       lpdwHandle As Long) As Long
    Declare Function VerQueryValue Lib "Version.dll" Alias _
       "VerQueryValueA" (pBlock As Any, ByVal lpSubBlock As String, _
       lplpBuffer As Any, puLen As Long) As Long
    Declare Function GetSystemDirectory Lib "kernel32" Alias _
       "GetSystemDirectoryA" (ByVal Path As String, ByVal cbBytes As _
       Long) As Long
    Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
        dest As Any, ByVal Source As Long, ByVal Length As Long)
    Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" ( _
        ByVal lpString1 As String, ByVal lpString2 As Long) As Long
    
    

  5. Copy and paste the following code to the code window of Form1:

Option Explicit

Private Sub Command1_Click()
   Dim Buffer As String
   Dim rc As Long
   Dim FullFileName As String
   '*** We will check the FileDescription of the gdi32.dll****
   Buffer = String(255, 0)
   rc = GetSystemDirectory(Buffer, Len(Buffer))
   Buffer = LCase$(Mid$(Buffer, 1, InStr(Buffer, Chr(0)) - 1))
   FullFileName = Buffer & "\gdi32.dll"

   Dim lBufferLen As Long, lDummy As Long
   '*** Get size ****
   lBufferLen = GetFileVersionInfoSize(FullFileName, lDummy)
   If lBufferLen < 1 Then
      MsgBox "No Version Info available!"
      Exit Sub
   End If

   Dim sBuffer()  As Byte
   ReDim sBuffer(lBufferLen)
   rc = GetFileVersionInfo(FullFileName, 0&, lBufferLen, _
        sBuffer(0))
   If rc = 0 Then
      MsgBox "GetFileVersionInfo failed."
      Exit Sub
   End If

   Dim lVerPointer As Long

   rc = VerQueryValue(sBuffer(0), "\VarFileInfo\Translation", _
        lVerPointer, lBufferLen)
   If rc = 0 Then
      MsgBox "VerQueryValue failed."
      Exit Sub
   End If
   'lVerPointer 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.

   Dim bytebuffer(255) As Byte
   MoveMemory bytebuffer(0), lVerPointer, lBufferLen
   Dim Lang_Charset_String As String
   Dim HexNumber As Long

    HexNumber = bytebuffer(2) + bytebuffer(3) * &H100 + _
        bytebuffer(0) * &H10000 + bytebuffer(1) * &H1000000
    Lang_Charset_String = Hex(HexNumber)
    'now we change the order of the language id and code page
    'and convert it into a string representation.
    'For example, it may look like 040904E4
    'Or to pull it all apart:
    '04------        = SUBLANG_ENGLISH_USA
    '--09----        = LANG_ENGLISH
    ' ----04E4 = 1252 = Codepage for Windows:Multilingual
    Do While Len(Lang_Charset_String) < 8
        Lang_Charset_String = "0" & Lang_Charset_String
    Loop

    List1.Clear
    Dim strVersionInfo(7) As String
    strVersionInfo(0) = "CompanyName"
    strVersionInfo(1) = "FileDescription"
    strVersionInfo(2) = "FileVersion"
    strVersionInfo(3) = "InternalName"
    strVersionInfo(4) = "LegalCopyright"
    strVersionInfo(5) = "OriginalFileName"
    strVersionInfo(6) = "ProductName"
    strVersionInfo(7) = "ProductVersion"
    Dim i As Integer
    Dim strTemp As String
    For i = 0 To 7
        Buffer = String(255, 0)
        strTemp = "\StringFileInfo\" & Lang_Charset_String _
        & "\" & strVersionInfo(i)
        rc = VerQueryValue(sBuffer(0), strTemp, _
        lVerPointer, lBufferLen)
        If rc = 0 Then
            MsgBox "VerQueryValue failed at" & i
        Exit Sub
        End If

        lstrcpy Buffer, lVerPointer
        Buffer = Mid$(Buffer, 1, InStr(Buffer, Chr(0)) - 1)
        List1.AddItem strVersionInfo(i) & ": " & Buffer
    Next i
End Sub

(c) Microsoft Corporation 1996, All Rights Reserved. Contributions by Wei Hua, Microsoft Corporation


KBCategory: kbusage kbhowto
KBSubcategory: APrgWindow
Additional reference words: 4.00 vb4win vb432 kbstream
Keywords : APrgWindow vb432 VB4WIN kbhowto
Version : 4.0
Platform : NT WINDOWS


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: July 15, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.