Ce code sert à modifier une ressource String d'apres son ID dans une dll ou tout executable win32.
les chaines de caracteres sont stockées par groupes de 16 chaines correspondant à 16 IDs
la structure est la suivante
Textlenght as integer
textUnicode as string
et ainsi de suite jusqu'a avoir 16 * 2 octets + la longueur des textes
NOUVELLE VERSION : avec possibilité de lister les chaines, d'en ajouter,d'en supprimer et d'en modifer :))
Source / Exemple :
'met à jour des ressources d'un executable compilé
Private Declare Function BeginUpdateResource Lib "kernel32" Alias "BeginUpdateResourceA" (ByVal pstrFileName As String, ByVal bDeleteExistingResources As Long) As Long
'met à jour une ressource d'un executable compilé
Private Declare Function UpdateResource Lib "kernel32" Alias "UpdateResourceA" (ByVal hUpdate As Long, ByVal lpType As Long, ByVal lpName As Long, ByVal wLanguage As Integer, lpData As Any, ByVal cbData As Long) As Long
'fini la mise à jour des ressources d'un executable compilé
Private Declare Function EndUpdateResource Lib "kernel32" Alias "EndUpdateResourceA" (ByVal hUpdate As Long, ByVal fDiscard As Long) As Long
'charge un executable ou dll
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibstrFileName As String) As Long
'trouve le handle de la ressource demandée
Private Declare Function FindResourceEx Lib "kernel32" Alias "FindResourceExA" (ByVal hModule As Long, ByVal lpType As Long, ByVal lpName As Long, ByVal wLanguage As Long) As Long
'charge la ressource en mémoire
Private Declare Function LoadResource Lib "kernel32" (ByVal hInstance As Long, ByVal hResourceInfo As Long) As Long
'renvoie un pointeur vers la ressource en mémoire
Private Declare Function LockResource Lib "kernel32" (ByVal hResourceData As Long) As Long
'renvoie la taille de la ressource en mémoire
Private Declare Function SizeofResource Lib "kernel32" (ByVal hInstance As Long, ByVal hResourceInfo As Long) As Long
'libère une dll ou un exe chargé
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
'copie une zone de mémoire dans une autre
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
'une entrée d'une table de chaînes
Public Type StringTable
ID As Long
Texte As String
End Type
'===============================================================================
'les resource string d'un exe sont groupés par 16. ainsi par exemple le groupe 7
'contiendra les ID de 96 à 111
'pour trouver le groupe on utilise la formule :
'groupe = int(ID / 16) + 1 (le groupe 0 n'existe pas)
'===============================================================================
'strFileName = nom du fichier à modifier
'ID = identifiant de la ressource string (ex:101)
'strTexte = Texte à mettre à cet ID
'LangID = identifiant de la langue de l'ID (FR=1036)
Public Sub StringResourceModify(strFileName As String, ID As Integer, ByVal strTexte As String, LangID As Long)
Dim ret As Long 'valeur renvoyée
Dim hResource As Long 'handle du fichier en écriture
Dim X As Long 'compteur
Dim iGroup As Integer 'groupe
Dim hObject As Long 'handle de l'objet ressource
Dim hResourceData As Long
Dim lpResourceData As Long
Dim cbResource As Long 'taille de la ressource
Dim hModule As Long 'handle du fichier en lecture
Dim lpData() As Byte 'buffer de donnée
Dim lpReadData() As Byte 'buffer de lecture
Dim cbTexte As Integer
If ID < 1 Then Exit Sub
'on calcule le groupe de strings
iGroup = Int(ID / 16&) + 1
'on ouvre le fichier
hModule = LoadLibrary(strFileName)
'on cherche s'il y a deja des données dans le groupe iGroup
hObject = FindResourceEx(hModule, 6&, iGroup, LangID)
'on charge les éventuelles données
hResourceData = LoadResource(hModule, hObject)
'on vérouille la mémoire qui contient l'éventuelle groupe iGroup
lpResourceData = LockResource(hResourceData)
'on cherche la taille de la ressource iGroup
cbResource = SizeofResource(hModule, hObject)
If cbResource <= 32 Or hObject = 0 Then
'pas de ressource ayant ce nom (numéro de groupe)
' vu que l'on enregistre q'un seul strTexte sur 16
'il y a 15 * 2 octets pour les tailles des 15 chaines vides
'+ 2 octets pour la taille du strTexte que l'on enregistre
'+ longueur du strTexte * 2 octets pour le strTexte Unicode (un caractère suivi d'un chr(0))
cbResource = 32& + Len(strTexte) * 2&
'on redimensionne le tableau qui va contenir les données
ReDim lpData(cbResource - 1)
'on copie la longueur du strTexte à l'emplacement 2 * le nombre d'enregistrements avants l'ID
cbTexte = Len(strTexte)
CopyMemory lpData(2& * (ID - (iGroup - 1) * 16&)), cbTexte, 2&
'si le strTexte est different de ""
If Len(strTexte) Then
'on le copie 2 octets plus loin que l'emplacement précédent
CopyMemory lpData(2& + 2& * (ID - (iGroup - 1) * 16&)), ByVal StrPtr(strTexte), Len(strTexte) * 2
End If
Else
'une ressource iGroup est contenu dans le fichier
'nous n'allons modifier que le strTexte qui nous intéresse
'on prépare pour cela un buffer qui va contenir les données déjà présentes
ReDim lpReadData(cbResource - 1)
'on copie les donnée de l'emplacement mémoire que l'on a vérouillé avant
CopyMemory lpReadData(0), ByVal lpResourceData, cbResource
Dim countX As Long 'un compteur
Dim CHECKLNG As Integer 'la longueur des strings
'on copie toutes les données contenues dans les ids < à notre ID
For X = 0 To (ID - (iGroup - 1) * 16&) - 1
CopyMemory CHECKLNG, lpReadData(countX), 2&
countX = countX + 2 + CHECKLNG * 2
Next
'on copie la longueur du strTexte à remplacer
CopyMemory CHECKLNG, lpReadData(countX), 2&
'on redimensionne le tableau qui va contenir les données modifiées
ReDim lpData(countX + 2 + Len(strTexte) * 2 + (cbResource - (countX + 2 + CHECKLNG * 2)) - 1)
'on copie les données qui précédent notre ID
CopyMemory lpData(0), lpReadData(0), countX
'on copie la longueur de notre strTexte
cbTexte = Len(strTexte)
CopyMemory lpData(countX), cbTexte, 2&
'si notre strTexte <> ""
If Len(strTexte) Then
'on le copie 2 octets + loin
CopyMemory lpData(countX + 2), ByVal StrPtr(strTexte), Len(strTexte) * 2
End If
'on copie le reste des données lues
If (cbResource - (countX + 2 + CHECKLNG * 2)) > 0 Then
CopyMemory lpData(countX + 2 + Len(strTexte) * 2), lpReadData(countX + 2 + CHECKLNG * 2), (cbResource - (countX + 2 + CHECKLNG * 2))
End If
End If
'on ferme le fichier
FreeLibrary hModule
'on ouvre le fichier en écriture dans lequel on va modifier un strTexte
hResource = BeginUpdateResource(strFileName, ByVal 0&) 'byval 0& : on ne supprime pas les resources du fichier
'on modifie la ressource iGroup
ret = UpdateResource(hResource, 6&, CLng(iGroup), CInt(LangID), lpData(0), UBound(lpData) + 1)
'on modifie le fichier
ret = EndUpdateResource(hResource, ByVal 0&)
End Sub
'===============================================================================
'les resource string d'un exe sont groupés par 16. ainsi par exemple le groupe 7
'contiendra les ID de 96 à 111
'pour trouver le groupe on utilise la formule :
'groupe = int(ID / 16) + 1 (le groupe 0 n'existe pas)
'===============================================================================
'strFileName = nom du fichier à modifier
'LangID = identifiant de la langue de l'ID (FR=1036)
Public Function StringResourceList(strFileName As String, LangID As Long) As StringTable()
Dim ret As Long 'valeur renvoyée
Dim hResource As Long 'handle du fichier en écriture
Dim X As Long 'compteur
Dim iGroup As Integer 'groupe
Dim hObject As Long 'handle de l'objet ressource
Dim hResourceData As Long
Dim lpResourceData As Long
Dim cbResource As Long 'taille de la ressource
Dim hModule As Long 'handle du fichier en lecture
Dim lpData() As Byte 'buffer de donnée
Dim lpReadData() As Byte 'buffer de lecture
Dim Out() As StringTable
Dim countX As Long 'un compteur
Dim CHECKLNG As Integer 'la longueur des strings
Dim temp As String 'un buffer
ReDim Out(0)
'on ouvre le fichier
hModule = LoadLibrary(strFileName)
'on parcours le 4096 groupes (ID 1 à 65535) possibles
For iGroup = 1 To 4096
'on cherche s'il y a des données dans le groupe iGroup
hObject = FindResourceEx(hModule, 6&, iGroup, LangID)
'on charge les éventuelles données
hResourceData = LoadResource(hModule, hObject)
'on vérouille la mémoire qui contient l'éventuelle groupe iGroup
lpResourceData = LockResource(hResourceData)
'on cherche la taille de la ressource iGroup
cbResource = SizeofResource(hModule, hObject)
'on vérifie si la taille est correcte
If cbResource >= 31 And hObject <> 0 Then
'une ressource iGroup est contenu dans le fichier
'on prépare un buffer qui va contenir les données présentes
ReDim lpReadData(cbResource - 1)
'on copie les donnée de l'emplacement mémoire que l'on a vérouillé avant
CopyMemory lpReadData(0), ByVal lpResourceData, cbResource
'on mets les variables à zéros
countX = 0
X = 0
'on lit les données
Do While countX < UBound(lpReadData)
'on copie la taille de la chaine qui suit
CopyMemory CHECKLNG, lpReadData(countX), 2&
'on ajoute 2 à la position actuelle pour etre soit au début de la chaine soit à la taille suivante
countX = countX + 2
'si la chaine n'est pas nulle
If CHECKLNG Then
'on ajoute un item au tableau
ReDim Preserve Out(UBound(Out) + 1)
'on mets l'ID dans ID
Out(UBound(Out)).ID = (iGroup - 1) * 16& + X
'on prépare un buffer pour la chaine
temp = Space(CHECKLNG * 2)
'on copie la chaine
CopyMemory ByVal StrPtr(temp), lpReadData(countX), CHECKLNG * 2
'on enregistre la chaine dans le tableau
Out(UBound(Out)).Texte = temp
'on se place au début de la chaine suivante
countX = countX + CHECKLNG * 2
End If
'on passe à la chaine suivante
X = X + 1
Loop
End If
Next
'on ferme le fichier
FreeLibrary hModule
'on renvoie le tableau
StringResourceList = Out
End Function
Conclusion :
n'hésitez pas à mettre des commentaires :)
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.