dcsimg
Results 1 to 6 of 6
  1. #1

    Thread Starter
    Junior Member
    Join Date
    Jul 2008
    Posts
    27

    Resolved [RESOLVED] EnumResourceLanguages from a DLL

    I would like to be able to perform a Count of available Language entries against STRINGTABLES from within a DLL, and also obtain the Locale IDs.
    There will be a single DLL file that would contain several different Language translations, like in the attached screenshot.
    Attachment 154307
    I thought I had read that it is possible to do using the EnumResourceLanguages API call, however I cannot figure out how to call this and obtain the desired results. Maybe this is not what this function does.

    Here is the Declare:
    Private Declare Function EnumResourceLanguages Lib "kernel32" Alias "EnumResourceLanguagesA" (ByVal hModule As Long, ByVal lpType As String, ByVal lpName As String, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long

    FYI....I am using the DLL to read strings by passing the Id values.

  2. #2
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    17,273

    Re: EnumResourceLanguages from a DLL

    Your attachment is a dead link. The enumeration DLLs do not read strings, it can identify which LCIDs are used by the DLL's string table. Then you'd have to use the resource APIs to read & parse the strings yourself: FindResourceEx being the workhorse.

    Note: air-code follows. apologize in advance for any typos.

    The process if enumerating languages goes a bit like this: focusing on the string tables

    1. Start your enumeration with EnumResourceNames. Note 6 below = RT_STRING
    Code:
    Private Sub Command1_Click()
    
       Dim colLCID As Collection, hModule As Long, c As Long
    
       ' Use LoadLibraryEx to get the DLL into your process and return hModule
       Set colLCID = New Collection
       EnumResourceNames hModule, 6, AddressOf EnumResourceNamesProc, colLCID
       ' Use FreeLibrary to remove DLL from process now or at some later point
    
       ' now colLCID has the list of string table languages
       ' note: the collection can contain the same LCID multiple times. 
       ' enumeration occurs once per RT_STRING block within the DLL
       For c = 1 To colLCID.Count: Debug.Print colLCID.Item(c): Next
    
    End Sub
    2. Call the EnumResourceLanguages from the EnumResNameProc within your module
    Code:
    Public Function EnumResourceNamesProc(ByVal hModule As Long, ByVal lpszType As Long, ByVal lpszName As Long, lParam As Collection) As Long
    
        EnumResourceNamesProc = EnumResourceLanguages(hModule, lpszType, lpszName, AddressOf EnumResLangProc, lParam)
    
    End Function
    
    Private Function EnumResLangProc(ByVal hModule As Long, ByVal lpszType As Long, ByVal lpszName As Long, ByVal wIDLanguage As Integer, lParam As Collection) As Long
    
        lParam.Add lpszName & "," & wIDLanguage   ' collect block ID & language ID, comma delimited
        EnumResLangProc = 1  ' continue enumeration
    
    End Function
    Use these unicode APIs
    Code:
    Public Declare Function EnumResourceNames Lib "kernel32" Alias "EnumResourceNamesW" (ByVal hModule As Long, ByVal lpType As Long, ByVal lpEnumFunc As Long, ByRef lParam As Any) As Long
    
    Public Declare Function EnumResourceLanguages Lib "kernel32" Alias "EnumResourceLanguagesW" (ByVal hModule As Long, ByVal lpType As Long, ByVal lpName As Long, ByVal lpEnumFunc As Long, ByRef lParam As Any) As Long
    Last edited by LaVolpe; Dec 6th, 2017 at 08:02 AM. Reason: tested sample code for typos
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  3. #3
    Frenzied Member
    Join Date
    Jun 2015
    Posts
    1,967

    Re: EnumResourceLanguages from a DLL

    Loading a language specific resource string

    http://www.vbforums.com/showthread.p...FindResourceEx
    Imagine what it would be like to set breakpoints in, or step through subclassing code;
    and then being able to hit stop/end/debug or continue, without crashing the IDE.

    VB6.tlb | Bulletproof Subclassing in the IDE (no thunks/assembly/DEP issues)

  4. #4
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    17,273

    Re: EnumResourceLanguages from a DLL

    Just for grins.... This should create a valid .res file that you can actually view in VB's resource editor. The res file will only contain string tables.

    Code:
    Private Sub Command1_Click()
    
        Dim hModule As Long, hFile As Long
        Dim sDLL As String, sResPath As String
        Const RT_STRING As Long = 6
    
        sDll = "c:\windows\system32\user32.dll"  ' change as desired
        sResPath = [supply valid res destination folder, no trailing backslash]    
    
        hModule = LoadLibraryEx(StrPtr(sDLL), 0&, LOAD_LIBRARY_AS_DATAFILE)
        If hModule = 0& Then 
            MsgBox "Failed to load the selected DLL"
            Exit Sub
        End If
        
        hFile = FreeFile()
        Open sResPath & "\Strings(" & Mid(sDLL, InStrRev(sDLL, "\") + 1) & ").res" For Binary As #hFile
        ' write the required static 32-byte header block
        Put #hFile, 1, 0&   ' null data length
        Put #hFile, , 32& ' header size
        Put #hFile, , &HFFFF&: Put #hFile, , &HFFFF& ' 0 ResType, 0 ResID
        Put #hFile, , 0@: Put hFile, , 0@
        
        EnumResourceNames hModule, RT_STRING, AddressOf EnumResNamesProc, hFile
        FreeLibrary hModule
        Close #hFile
    End Sub
    In a module:
    Code:
    Public Declare Function LoadLibraryEx Lib "kernel32" Alias "LoadLibraryExW" (ByVal lpLibFileName As Long, ByVal hFile As Long, ByVal dwFlags As Long) As Long
    Public Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
    Private Declare Function FindResourceEx Lib "kernel32" Alias "FindResourceExW" (ByVal hModule As Long, ByVal lpType As Long, ByVal lpName As Long, ByVal wLanguage As Integer) As Long
    Private Declare Function LoadResource Lib "kernel32" (ByVal hInstance As Long, ByVal hResInfo As Long) As Long
    Private Declare Function LockResource Lib "kernel32" (ByVal hResData As Long) As Long
    Private Declare Function SizeofResource Lib "kernel32" (ByVal hInstance As Long, ByVal hResInfo As Long) As Long
    Private Declare Function EnumResourceLanguages Lib "kernel32" Alias "EnumResourceLanguagesW" (ByVal hModule As Long, ByVal lpType As Long, ByVal lpName As Long, ByVal lpEnumFunc As Long, ByRef lParam As Any) As Long
    Public Declare Function EnumResourceNames Lib "kernel32" Alias "EnumResourceNamesW" (ByVal hModule As Long, ByVal lpType As Long, ByVal lpEnumFunc As Long, ByRef lParam As Any) As Long
    Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal length As Long)
    Public Const LOAD_LIBRARY_AS_DATAFILE = 2
    
    Public Function EnumResNamesProc(ByVal hModule As Long, ByVal lpszType As Long, ByVal lpszName As Long, ByRef lParam As Long) As Long
    
        EnumResNamesProc = EnumResourceLanguages(hModule, lpszType, lpszName, AddressOf EnumResLangProc, lParam)
    
    End Function
    
    Private Function EnumResLangProc(ByVal hModule As Long, ByVal lpszType As Long, ByVal lpszName As Long, ByVal wIDLanguage As Integer, ByRef lParam As Long) As Long
    
        Dim lSize As Long, lValue As Long, bData() As Byte
        Dim hRes As Long, hGlobal As Long, hPtr As Long
        
        Debug.Assert (lpszType = 6& And (lpszName And &HFFFF0000) = 0&)
        ' ^^ for testing; ensure RT_STRING is being passed and the ID is numeric, not string
        
        hRes = FindResourceEx(hModule, lpszType, lpszName, wIDLanguage)
        If hRes Then
            hGlobal = LoadResource(hModule, hRes)
            If hGlobal Then
                hPtr = LockResource(hGlobal)
                If hPtr Then
                    lSize = SizeofResource(hModule, hRes)
                    Put #lParam, , lSize                        ' write size of resource
                    Put #lParam, , 32&                          ' write header size
                    Put #lParam, , &H6FFFF                      ' write RT_STRING
                    If (lpszName And &H8000&) Then              ' write the block ID
                        lValue = (lpszName And &H7FFF&) * &H10000 Or &H8000FFFF
                    Else
                        lValue = (lpszName * &H10000) Or &HFFFF&
                    End If
                    Put #lParam, , lValue
                    Put #lParam, , 0&: Put #lParam, , 0         ' write DataVersion & MemFlags
                    Put #lParam, , wIDLanguage                  ' write LCID
                    Put #lParam, , 0@                           ' write version & characteristics
                    lValue = (lSize + 3&) And Not 3&
                    ReDim bData(0 To lValue - 1&)               ' DWord align data
                    CopyMemory bData(0), ByVal hPtr, lSize
                    Put #lParam, , bData()
                End If
            End If
        End If
        EnumResLangProc = 1&
    
    End Function
    Edited: Strings in other than system's LCID may not display correctly in VB's resource editor.

    Example of User32.dll
    Name:  strings.jpg
Views: 41
Size:  58.3 KB
    Last edited by LaVolpe; Dec 6th, 2017 at 01:25 PM. Reason: oops, needed to make an API Public vs Private
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  5. #5

    Thread Starter
    Junior Member
    Join Date
    Jul 2008
    Posts
    27

    Re: EnumResourceLanguages from a DLL

    Thanks LaVolpe. I have tested your first method and it works great. I will be able to use this structure to code up something that I can use.
    Thanks DEXWERX I already have your great code snippet to obtain the Strings, that is all working fine.

  6. #6
    Junior Member
    Join Date
    Jun 2016
    Posts
    28

    Re: [RESOLVED] EnumResourceLanguages from a DLL

    how can I get "ES_en" or "En_en" from all id.
    or I have to make a table with all the id and string of each number.
    a greeting

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width


×
We have made updates to our Privacy Policy to reflect the implementation of the General Data Protection Regulation.