Re: Modify infos of numerous files
Posted: Thu Jun 07, 2018 8:22 am
Kcc, i send you a private msg.
I' m working to find a solution, but it will take time.
I' m working to find a solution, but it will take time.
http://www.purebasic.com
https://www.purebasic.fr/english/
Code: Select all
;// Patcheur pour la resource #RT_RCDATA de fichiers exe/dll (format PE)
;// Codé par denis pour KCC
;//
;// Le code patche la resource d'un fichier exe/dll (format PE)
;// en ajoutant des données en RC_DATA
;// L'identifiant utilisée est de type alphanumérique
;// Le code ne vérifie pas si les données existent en RC_DATA pour l'identifiant alphanumérique
;// L'identifiant utilisée est de type alphanumérique, #KCC_id = "KwaiChangCaine"
;// La langue utilisée pour les données écrites est #LANG_FRENCH, #SUBLANG_FRENCH
;// la multi-sélection de fichiers est possible
;//
;// A compiler en Unicode! et utiliser le debugger
;// Patcher for #RT_RCDATA resource of exe/dll files (PE format)
;// Coded by denis for KCC
;//
;// The code patches resource of an exe/dll file (PE file format)
;// by adding data in RC_DATA
;// The identifier used is an alphanumeric one
;// The code does not check if RC_DATA exists for the alphanumeric identifier
;// The identifier used is alphanumeric, #KCC_id = "KwaiChangCaine
;// The language used for written data is #LANG_FRENCH, #SUBLANG_FRENCH
;// multiple file selection is possible
;//
;// Compile only in Unicode! and use the debugger
EnableExplicit
;- 100 -------- Constantes/Constants
;// valeur retournée en cas d'erreur/returned value in case of failure
#Return_Error = #False
;// valeur retournée en cas de succès/returned value if successful
#Return_No_Error = #True
;// identifiant de la resource en RC_DATA/RC_DATA resource identifier
#KCC_id = "KwaiChangCaine"
;// identifiant système de la resource RC_DATA/RC_DATA resource system identifier
#RT_RCDATA = 10
;-
;- 300 -------- Structure
Structure File
;// Nom du fichier/File name
FileName.s
;// résultat de l'opération de patchage:
;// #True, le patch est Ok, #False, le patchage n'est pas correct ou absent
;// result of patching operation:
;// #True, Patch is Ok, #False, patching is not correct or absent
NoError.i
EndStructure
;-
;- 500 -------- Macros
Macro MAKEINTRESOURCE(Value)
(Value & $FFFF)
EndMacro
Macro MAKELANGID(primary, sublang)
(((sublang)<<10) | (primary))
EndMacro
;-
;- -- 2000 -------- Procedures
Procedure.i Add_MemoryDATA_String(StringToAdd.s, *MemoryToreturn, closeBuffer = #False)
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// FONCTION/FUNCTION: Add_MemoryDATA_String()
;//
;// BUT/PURPOSE: Réallouer de la mémoire pour stocker les chaînes existantes et y ajouter la nouvelle chaîne passée en paramètre
;// Reallocate memory To store existing strings And add the new string passed As parameter To it
;//
;// PARAMETRES/PARAMETERS:
;// StringToAdd.s - la chaîne à ajouter/the string to add
;// *MemoryToreturn - adresse d'une variable en mémoire (variable de type pointeur)
;// la variable recevra l'adresse de la mémoire qui contient les données
;// en cas d'erreur, la variable recevra la valeur #Null
;// address of a variable in memory (pointer type variable)
;// the variable will receive the address of the memory that contains the data
;// in case of failure, the variable will be set to #Null
;// closeBuffer - variable qui prendra une de ces deux valeurs : #True ou #False
;// variable that will take one of these two values: #True or #False
;// #True : on ajoute la chaîne et les variables statiques sont positionnées aux valeurs correctes
;// #True : the string is added and the static variables are set to correct values
;//
;// #False : Il n'y a plus de chaîne à ajouter, les données de la mémoire seront alignées sur 4 octets
;// #False : There is no more string to add, the memory data will be aligned on 4 bytes
;// les variables statiques sont positionnées à #Null
;// static variables are set to #Null
;//
;// RETOURNE/RETURN: en cas de succès, l'adresse mémoire ou sont stockées les chaînes
;// if successful, the memory address where the strings are stored
;// #Return_Error en cas d'erreur/#Return_Error in case of failure
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// mémorise le nombre d'octets nécessaire pour stocker la chaîne en mémoire (format Unicode)
;// le caractère #NULL de fin de chaîne n'est pas pris en compte
;// memorizes the number of bytes needed to store in memory the string (Unicode format)
;// the #NULL character of end string is not taken into account
Protected SizeOfString
;// mémorise le nombre d'octets écrits par la fonction PokeS(), non compris le caractère #NULL de fin de chaîne
;// memorizes the number of bytes written by the function PokeS() function, not including the #Null character of end string
Protected NumberOfBytesWritten
;// pointeur temporaire pour réallouer de la mémoire
;// temporary pointer to reallocate memory
Protected *NewMemoryID
;// pointeur qui conserve l'adresse de la mémoire à chaque appel de la procedure
;// pointer that keeps the memory address each time the procedure is called
Static *memory
;// mémorise la position du pointeur lorsque la chaine est écrite, pointe le caractère après le 0 de fin de chaine
;// (offset = offset + NumberOfBytesWritten + 2) - la valeur est mémorisé pour chaque appel de la procedure
;// memorizes the pointer position when the string is written, points the character after the 0 of end string
;// (offset = offset + NumberOfBytesWritten + 2) - the value is kept for each procedure call
Static offset
;// mémorise la taille courante du buffer utilisée pour réallouer correctement la mémoire
;// la valeur est mémorisé pour chaque appel de la procedure
;// stores the current size of the buffer used to reallocate the memory correctly
;// the value is kept For each Procedure call
Static BufferSize
Select closeBuffer
Case #True
;// on aligne les données, ensuite plus aucune opération sur le buffer !
;// Data are aligned, so no more operations on the buffer!
If BufferSize % 4
BufferSize + 2
EndIf
*NewMemoryID = ReAllocateMemory(*memory, BufferSize)
If *NewMemoryID = #Return_Error
If *memory
FreeMemory(*memory)
*memory = #Null
EndIf
offset = #Null
BufferSize = #Null
PokeI(*MemoryToreturn, #Null)
ProcedureReturn #Return_Error
EndIf
*memory = #Null
BufferSize = #Null
offset = #Null
PokeI(*MemoryToreturn, *NewMemoryID)
ProcedureReturn #Return_No_Error
Default
;// test le pointeur/check pointer
If *MemoryToreturn = #Null
BufferSize = #Null
offset = #Null
If *memory
FreeMemory(*memory)
*memory = #Null
EndIf
ProcedureReturn #Return_Error
EndIf
;// on ajoute la chaîne/add the string
If StringToAdd = ""
BufferSize = #Null
offset = #Null
If *memory
FreeMemory(*memory)
*memory = #Null
EndIf
PokeI(*MemoryToreturn, #Null)
ProcedureReturn #Return_Error
EndIf
SizeOfString = StringByteLength(StringToAdd)
*NewMemoryID = ReAllocateMemory(*memory, BufferSize + SizeOfString + 2)
If *NewMemoryID = #Return_Error
If *memory
FreeMemory(*memory)
*memory = #Null
EndIf
offset = #Null
BufferSize = #Null
PokeI(*MemoryToreturn, #Null)
ProcedureReturn #Return_Error
EndIf
BufferSize = MemorySize(*NewMemoryID)
*memory = *NewMemoryID
;// copie la chaine dans le tampon/copies the string into the buffer
NumberOfBytesWritten = PokeS(*memory + offset, StringToAdd, -1, #PB_Unicode)
;// on contrôle que l'on a bien écrit la bonne taille de chaîne/check that the correct string size has been written
Select NumberOfBytesWritten
Case SizeOfString
;// c'est Ok/it's Ok
offset = offset + NumberOfBytesWritten + 2
PokeI(*MemoryToreturn, *memory)
ProcedureReturn #Return_No_Error
Default
FreeMemory(*memory)
*memory = #Null
BufferSize = #Null
offset = #Null
PokeI(*MemoryToreturn, #Null)
ProcedureReturn #Return_Error
EndSelect
EndSelect
EndProcedure
Procedure.i Create_MemoryDATA(List MyStringsListe.s())
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// FONCTION/FUNCTION: Create_MemoryDATA()
;//
;// BUT/PURPOSE: Créer les données RC_DATA en mémoire/Create RC_DATA data in memory
;//
;// PARAMETRE/PARAMETER:
;// MyStringsListe.s() - Liste chainée à remplir avec les chaînes pour écriture du tampon
;// linked list to fill up with strings, to write them into the buffer
;//
;// RETOURNE/RETURN: en cas de succès, l'adresse mémoire de l'ensemble des données à écrire
;// if successful, the memory address of all data to be written
;// #Return_Error en cas d'erreur/#Return_Error in case of failure
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// mémorise les données/stores data
Protected *memory
;// chaine courante lue en datasection/current string read in datasection
Protected StringRead.s = ""
;// chargement de la liste/load the list
ClearList(MyStringsListe())
Restore Texte
Read.s StringRead
While StringRead <> "End_Of_KCC_Section"
Select AddElement(MyStringsListe())
Case #Null
MessageRequester("Erreur/Error","Impossible d'allouer de la mémoire pour la liste chaînée" +
Chr(10)+Chr(10)+ "Unable to allocate memory for linked list")
End
Default
Select StringRead
Case ""
MessageRequester("Erreur/Error","Impossible d'ajouter une chaîne vide à la liste" +
Chr(10)+ "le programme va se terminer" +
Chr(10)+Chr(10)+ "Unable to add an empty string to the list"+
Chr(10)+ "Program aborted")
End
Default
MyStringsListe() = StringRead
EndSelect
EndSelect
Read.s StringRead
Wend
;// Ajouter au buffer mémoire chaque chaîne de la liste/Add each string from the list to memory buffer
ForEach MyStringsListe()
If Add_MemoryDATA_String(MyStringsListe(), @*Memory) = #Return_Error
ProcedureReturn #Return_Error
EndIf
Next
;// alignement des données, ensuite on n'écrit plus dans le buffer!
;// Data are aligned, so no more operations on the buffer!
If Add_MemoryDATA_String("", @*Memory, #True) = #Return_Error
ProcedureReturn #Return_Error
EndIf
ProcedureReturn *memory
EndProcedure
Procedure Write_RCDATA_Resource(List Files.File(), id.s, *pt_Data_Block, SiezOf_Data_Block)
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// FONCTION/FUNCTION: Write_RCDATA_Resource()
;//
;// BUT/PURPOSE: Ecrire les données RC_DATA/Write RC_DATA datas
;//
;// PARAMETRES/PARAMETERS:
;// Files.File() - Liste chaînée des fichiers à patcher/Linked list of files to patch
;// Files()\FileName :
;// contient le nom complet du fichier/contains the full file name
;// Files()\NoError :
;// recevra une des valeurs suivantes (résultat de l'opération de patchage):
;// will receive one of the following values (result of patching operation):
;// #True : le patch est Ok/Patch is Ok
;// #False : le patchage n'est pas correct ou absent/patching operation is not correct
;// id.s - identifiant de la ressource RC_DATA/RC_DATA resource identifier
;// ici la constante définie #KCC_id/here the defined constant #KCC_id
;// *pt_Data_Block - pointeur sur la zone mémoire des données à écrire/pointer to the memory area of datas to write
;// SiezOf_Data_Block - taille mémoire des données à écrire/memory size of datas to write
;//
;// RETOURNE/RETURN: Rien/Nothing
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// handle de l'API BeginUpdateResource_()/handle from the BeginUpdateResource_() API
Protected BeginUpdateResource
;// attributs du fichier avant de les modifier/file attributes before modifying them
Protected FileAttributes
;// par sécurité/for safety
If *pt_Data_Block = #Null Or (SiezOf_Data_Block <= 0) Or ListSize(Files()) = 0
ProcedureReturn #Return_Error
EndIf
ForEach Files()
;// on lit les attributs du fichier avant modifs/read file attributes before changes
FileAttributes = GetFileAttributes(Files()\FileName)
;// on modifie les attributs du fichier avant de le patcher/modify the file attributes before patching it
SetFileAttributes(Files()\FileName, #PB_FileSystem_Normal)
;// Retrouve le handle qui sera utilisé par la fonction UpdateResource/Find the handle that will be used by the UpdateResource function
BeginUpdateResource = BeginUpdateResource_(Files()\FileName, #False)
Select BeginUpdateResource
Case #Null
Files()\NoError = #False
Default
;// ajoute, supprime ou remplace les resources passées en paramètre
Select UpdateResource_(BeginUpdateResource, #RT_RCDATA, @id, MAKEINTRESOURCE(MAKELANGID(#LANG_FRENCH, #SUBLANG_FRENCH)), *pt_Data_Block, SiezOf_Data_Block)
Case #Return_Error
EndUpdateResource_(BeginUpdateResource, #True)
Files()\NoError = #False
Default
;// Valide les modifications de la resource/Validates resource changes
Select EndUpdateResource_(BeginUpdateResource, #False)
Case #Return_Error
EndUpdateResource_(BeginUpdateResource, #True)
Files()\NoError = #False
Default
Files()\NoError = #True
EndSelect
EndSelect
EndSelect
;// on repositionne les attributs initiaux du fichier/repositions initial attributes of the file
If FileAttributes <> -1
SetFileAttributes(Files()\FileName, FileAttributes)
EndIf
Next
EndProcedure
Procedure SelectFileToProcess(List FilesToRead.File())
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// FONCTION/FUNCTION: SelectFileToProcess()
;//
;// BUT/PURPOSE: Ouvre la fenêtre de sélection des fichiers
;// Ajoute des éléments à la liste chaînée pour y stocker les noms de fichier
;// Opens the file selection window
;// Adds elements to the linked list to store file names
;//
;// PARAMETRE/PARAMETER:
;// FilesToRead - liste chaînée qui contiendra la liste des fichiers à traiter
;// linked list that will contain the list of files to process
;//
;// RETOURNE/RETURN: Rien/Nothing
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// Nom du fichier/File name
Protected File$ = ""
ClearList(FilesToRead.File())
File$ = OpenFileRequester("Open File", "", "Version (exe,dll)|*.exe;*.dll|all files (*.*)|*.*", 0, #PB_Requester_MultiSelection)
While File$
Select AddElement(FilesToRead())
Case #Null
MessageRequester("Erreur/Error","Impossible d'allouer de la mémoire pour la liste chaînée" +
Chr(10)+ "le programme va se terminer" +
Chr(10)+Chr(10)+ "Unable to allocate memory for linked list"+
Chr(10)+ "Program aborted")
End
Default
FilesToRead()\FileName = File$
EndSelect
File$ = NextSelectedFileName()
Wend
EndProcedure
;-
Procedure programme()
;// Nom du fichier/File name
Protected File$ = ""
;// pointeur qui recevra l'adresse du bloc mémoire/pointer that will receive the address of memory area
Protected *memory
;// Liste chainée qui contient les chaines à écrire en resource/Linked list that contains strings to write into resource
Protected NewList MyStringsListe.s()
;// Liste chainée qui contient la liste des fichier à modifier/Linked list that contains the listing of files to modify
Protected NewList Files.File()
;// compteur d'erreur/error counter
Protected NB_Error
;// creation de la liste des fichiers/creation of the list files
SelectFileToProcess(Files())
;// création de la mémoire contenant les chaînes/creates the memory containing the strings
;// création de la mémoire contenant les chaînes/creates the memory containing the strings
If ListSize(Files())
*memory = Create_MemoryDATA(MyStringsListe())
If *memory
;// écrit la ressource/ writes the resource
Write_RCDATA_Resource(Files(), #KCC_id, *memory, MemorySize(*memory))
Else
MessageRequester("Erreur/Error","Impossible de créer la zone mémoire" +
Chr(10)+Chr(10)+ "Unable to create memory area")
Debug "Erreur/Error:"
Debug "Impossible de créer la zone mémoire"
Debug "Unable to create memory area"
EndIf
;// affiche les résultats/displays results
ForEach Files()
Select Files()\NoError
Case #False
Debug "Fichier/File : " + Files()\FileName + Chr(10) + Space(20)+ "Erreur sur le fichier/File error"
NB_Error + 1
EndSelect
Next
If NB_Error = 0
MessageRequester("Info","Tous les fichiers ont été modifiés" + Chr(10)+"All files have been changed", #PB_MessageRequester_Info)
EndIf
;// libère la mémoire/frees the memory
If *memory
FreeMemory(*memory)
EndIf
Else
MessageRequester("Erreur/Error","Pas de fichier à traiter" +
Chr(10)+Chr(10)+ "No file to process")
EndIf
EndProcedure
DataSection
Texte:
Data.s "Zone Kcc!"
Data.s "Version :"
Data.s "3.00"
Data.s "Action :"
Data.s "Delete"
Data.s "Date :"
Data.s "March 2010"
Data.s "Summer Time :"
Data.s "06h57 PM"
Data.s "End_Of_KCC_Section"
EndDataSection
programme()
EndCode: Select all
;// Lecteur pour la resource #RT_RCDATA de fichiers exe/dll (format PE)
;// Codé par denis pour KCC
;//
;// Le code lit le contenu du patch "KwaiChangCaine" de la resources d'un fichier exe/dll (format PE)
;// Le contenu est copié dans un buffer mémoire pour y être lu
;// L'identifiant utilisée est de type alphanumérique, #KCC_id = "KwaiChangCaine"
;// La langue utilisée pour lire les données est #LANG_FRENCH, #SUBLANG_FRENCH
;// la multi-sélection de fichiers est possible
;//
;// A compiler en Unicode! et utiliser le debugger
;// Reader for resource #RT_RCDATA of exe/dll files (PE format)
;// Coded by denis for KCC
;//
;// The code reads the content of the "KwaiChangCaine" patch from the resource of an exe/dll files (PE format)
;// Content is copied to a memory buffer to be read
;// The identifier used is an alphanumeric one, #KCC_id = "KwaiChangCaine"
;// The language used for this item is #LANG_FRENCH, #SUBLANG_FRENCH
;// multiple file selection is possible
;//
;// Compile only in Unicode! and use the debugger
EnableExplicit
;- 100 -------- Constantes
;// Utilisé pour charger un fichier exe/dll (format PE) en lecture seule (accès au fichier restraint)
;// Used to load an exe/dll file (PE format) to read-only operations (restricted file access)
#LOAD_LIBRARY_AS_DATAFILE = 2
#LOAD_LIBRARY_AS_IMAGE_RESOURCE = $00000020
;// valeur retournée en cas d'erreur/returned value in case of failure
#Return_Error = #False
;// valeur retournée en cas de succès/returned value if successful
#Return_No_Error = #True
;// valeur retournée lorsque la resource est absente/returned value when resource is lacking
#Return_No_KCC_Resource = -1
;// valeur retournée lorsque le fichier n'existe pas/returned value when the file does not exist
#Return_File_No_Found = -2
;// valeur retournée lorsque un pointeur est nul/returned value when a pointer is null
#Return_Pointer_Null = -3
;// valeur retournée lorsqu'il est impossible de charger un fichier/returned value when a file can not be loaded
#Return_Unable_to_load_File = -4
;// valeur retournée lorsqu'il est impossible d'allouer de la mémoire/returned value when unable to allocate memory
#Return_Unable_to_Allocate_Memory = -5
;// identifiant de la resource en RC_DATA/RC_DATA resource identifier
#KCC_id = "KwaiChangCaine"
;// identifiant système de la resource RC_DATA/RC_DATA resource system identifier
#RT_RCDATA = 10
;-
;- 300 -------- Structure
Structure File
;// Nom du fichier/File name
FileName.s
;// résultat de l'opération de patchage:
;// #True, le patch est Ok, #False, le patchage n'est pas correct ou absent
;// result of patching operation:
;// #True, Patch is Ok, #False, patching is not correct or absent
NoError.i
EndStructure
;-
;- 500 -------- Macros
Macro MAKEINTRESOURCE(Value)
(Value & $FFFF)
EndMacro
Macro MAKELANGID(primary, sublang)
(((sublang)<<10) | (primary))
EndMacro
;-
;- -- 2000 -------- Procedures
Procedure.i LoadDatasFromResource(File.s, *pt_FilesToRead_NoError, id.s, *memoryToreturn)
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// FONCTION/FUNCTION: LoadDatasFromResource()
;//
;// BUT/PURPOSE: Créer une zone mémoire pour y copier le bloc de données de la resource si elle existe
;// Create a memory area to copy the resource data block if exists
;//
;// PARAMETRES/PARAMETERS:
;// File.s - Nom du fichier exe/dll avec chemin/exe/dll file name with path
;// *pt_FilesToRead_NoError - adresse d'une variable en mémoire (integer) qui recevra le code d'erreur pour le fichier courant
;// address of a variable in memory (integer) that will receive the error code for the current file
;// id.s - identifiant de la ressource RC_DATA/RC_DATA resource identifier
;// ici la constante définie #KCC_id/here the defined constant #KCC_id
;// *memoryToreturn - adresse d'une variable en mémoire (variable de type pointeur)
;// la variable recevra l'adresse de la mémoire qui contient les données
;// en cas d'erreur, la variable recevra la valeur #Null
;// address of a variable in memory (pointer type variable)
;// the variable will receive the address of the memory that contains the data
;// in case of failure, the variable will be set to #Null
;//
;// RETOURNE/RETURN: en cas de succès, l'adresse mémoire ou sont stockées les chaînes
;// Le fichier n'est plus utilisé ni chargé après cette opération
;// #Return_Error en cas d'erreur
;// if successful, the memory address where the strings are stored
;// The file is no longer used Or loaded after this operation
;// #Return_Error in case of failure
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// handle du fichier (PE)/handle of the file (PE)
Protected hModule
;// handle du bloc d'informations de la resource/handle of the resource information block
Protected Find_Resource
;// handle du bloc mémoire d'informations des données de la ressource/handle of the resource data information memory block
Protected LoadResource_RT_RCDATA
;// taille des données de la ressource RT_RCDATA/RT_RCDATA resource data size
Protected SizeofResource
;// pointeur sur le premier octet de la ressource RT_RCDATA/pointer to the first byte of the RT_RCDATA resource
Protected *LockResource
;// pointeur qui mémorise l'adresse du buffer mémoire/pointer that memorizes the memory buffer address
Protected *memory
;// test le pointeur/check pointer
If *memoryToreturn = #Null
PokeI(*pt_FilesToRead_NoError, #Return_Pointer_Null)
ProcedureReturn #Return_Error
EndIf
;// test le fichier/check file
If File = ""
PokeI(*pt_FilesToRead_NoError, #Return_File_No_Found)
PokeI(*memoryToreturn, #Null)
ProcedureReturn #Return_Error
EndIf
;// Charge le module spécifié dans l'espace d'adressage du processus appelant. Le module spécifié peut provoquer le chargement d'autres modules
;// Loads the specified module into the address space of the calling process. The specified module may cause other modules to be loaded
hModule = LoadLibraryEx_(File, 0, #LOAD_LIBRARY_AS_DATAFILE|#LOAD_LIBRARY_AS_IMAGE_RESOURCE)
If hModule = #Null
PokeI(*pt_FilesToRead_NoError, #Return_Unable_to_load_File)
PokeI(*memoryToreturn, #Null)
ProcedureReturn #Return_Error
EndIf
;// Détermine l'emplacement de la ressource avec le type, le nom et la langue spécifiés dans le module spécifié
;// Determines the location of the resource with the specified type, name, and language in the specified module
Find_Resource = FindResourceEx_(hModule, MAKEINTRESOURCE(#RT_RCDATA), id, MAKELANGID(#LANG_FRENCH, #SUBLANG_FRENCH))
If Find_Resource = #Return_Error
PokeI(*pt_FilesToRead_NoError, #Return_No_KCC_Resource)
PokeI(*memoryToreturn, #Null)
FreeLibrary_(hModule)
ProcedureReturn #Return_Error
EndIf
;// Récupère un handle qui peut être utilisé pour obtenir un pointeur vers le premier octet de la ressource spécifiée en mémoire
;// Retrieves a handle that can be used To obtain a pointer To the first byte of the specified resource in memory
LoadResource_RT_RCDATA = LoadResource_(hModule, Find_Resource)
If LoadResource_RT_RCDATA = #Return_Error
PokeI(*pt_FilesToRead_NoError, #Return_No_KCC_Resource)
PokeI(*memoryToreturn, #Null)
FreeLibrary_(hModule)
ProcedureReturn #Return_Error
EndIf
;// Récupère un pointeur sur la ressource spécifiée en mémoire
;// Retrieves a pointer To the specified resource in memory
*LockResource = LockResource_(LoadResource_RT_RCDATA)
If *LockResource = #Return_Error
PokeI(*pt_FilesToRead_NoError, #Return_No_KCC_Resource)
PokeI(*memoryToreturn, #Null)
FreeLibrary_(hModule)
ProcedureReturn #Return_Error
EndIf
;// Récupère la taille, en octets, de la ressource spécifiée
;// Retrieves the size, in bytes, of the specified resource
SizeofResource = SizeofResource_(hModule, Find_Resource)
If SizeofResource = 0
PokeI(*pt_FilesToRead_NoError, #Return_No_KCC_Resource)
PokeI(*memoryToreturn, #Null)
FreeLibrary_(hModule)
ProcedureReturn #Return_Error
EndIf
;// alloue la mémoire pour charger les données de la resource du fichier
;// Allocate memory to load data from the file's resource
*memory = AllocateMemory(SizeofResource)
If *memory = #Return_Error
PokeI(*pt_FilesToRead_NoError, #Return_Unable_to_Allocate_Memory)
PokeI(*memoryToreturn, #Null)
FreeLibrary_(hModule)
ProcedureReturn #Return_Error
EndIf
;// copie des données en mémoire
;// copy data into memory
CopyMemory(*LockResource, *memory, SizeofResource)
FreeLibrary_(hModule)
PokeI(*pt_FilesToRead_NoError, #True)
;// retourne l'adresse mémoire des données via *memoryToreturn
;// returns the memory address of the data via * MemoryToreturn
PokeI(*memoryToreturn, *memory)
ProcedureReturn #Return_No_Error
EndProcedure
Procedure.i ExtractStringFromMemory(List myStringsListe.s(), *pt_FilesToRead_NoError, *pt_memory)
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// FONCTION/FUNCTION: ExtractStringFromMemory()
;//
;// BUT/PURPOSE: Extraire les chaines du buffer et les ajouter à la liste chaînée passée en paramètre
;// Extract the strings from the buffer and add them to the linked list passed as a parameter
;//
;// PARAMETRES/PARAMETERS:
;// myStringsListe() - liste chaînée qui contiendra les chaînes retrouvées
;// Linked List that will contain the strings found
;// *pt_memory - adresse d'une variable en mémoire (variable de type pointeur)
;// la variable doit contenir l'adresse de la mémoire qui contient les données
;// address of a variable in memory (pointer type variable)
;// the variable must contain the address of the memory that contains the data
;//
;// RETOURNE/RETURN: #Return_No_Error en cas de succès/#Return_No_Error if successful
;// #Return_Error en cas d'erreur/#Return_Error in case of failure
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// adresse du buffer mémoire/memory buffer address
Protected *memory
;// taille courante de la mémoire/current memory size
Protected Size
;// pointeur temporaire utilisé pour se déplacer dans le buffer et retrouver les chaînes
;// temporary pointer used to move through the buffer to find the strings
Protected *memory_temp
;// variable de boucle/loop variable
Protected quit
;// test le pointeur/check pointer
If *pt_memory = #Null
PokeI(*pt_FilesToRead_NoError, #Return_Pointer_Null)
ProcedureReturn #Return_Error
EndIf
*memory = PeekI(*pt_memory)
If *memory = #Null
PokeI(*pt_FilesToRead_NoError, #Return_Pointer_Null)
ProcedureReturn #Return_Error
EndIf
;// allocation du pointeur temporaire/temporary pointer allocation
*memory_temp = *memory
Size = MemorySize(*memory)
ClearList(myStringsListe())
While quit = #False
Select AddElement(myStringsListe())
Case #Null
MessageRequester("Erreur/Error","Impossible d'allouer de la mémoire pour la liste chaînée" +
Chr(10)+ "le programme va se terminer" +
Chr(10)+Chr(10)+ "Unable to allocate memory for linked list" +
Chr(10)+ "Program aborted")
End
Default
myStringsListe() = PeekS(*memory_temp, -1, #PB_Unicode)
Select myStringsListe()
Case ""
quit = #True
Default
*memory_temp + StringByteLength(myStringsListe()) + 2
EndSelect
EndSelect
Wend
PokeI(*pt_FilesToRead_NoError, #True)
ProcedureReturn #Return_No_Error
EndProcedure
Procedure.i ExtractResourceString(*pt_Memory, *pt_error, List FilesToRead.File(), List StringsListeToFillUp.s())
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// FONCTION/FUNCTION: ExtractResourceString()
;//
;// BUT/PURPOSE: Boucle sur l'ensemble des fichiers et retrouve la resource pour chaque fichier
;// C'est dans cette fonction qu'il faut ajouter du code pour faire ce qu'il y a à faire
;// Scan all files and finds the resource for each file
;// It is in this function that you have to add code to do what you have to do
;//
;// PARAMETRES/PARAMETERS:
;// *pt_memory - adresse d'une variable en mémoire (variable de type pointeur)
;// la variable doit contenir l'adresse de la mémoire qui contient les données
;// address of a variable in memory (pointer type variable)
;// the variable must contain the address of the memory that contains the data
;// *pt_error - adresse d'une variable en mémoire (variable de type integer) qui recevra le
;// nombre d'erreurs arrivé lors de la lecture de la resource
;// address of a variable in memory (integer variable) that will receive the number
;// of errors that occurred while reading the resource
;// FilesToRead() - liste chaînée qui contient la liste des fichiers à traiter
;// Linked list that contains the list of files to be processed
;// StringsListeToFillUp() - liste chaînée qui contiendra les chaînes retrouvées
;// Linked list that will contain the strings found
;//
;// RETOURNE/RETURN: #Return_No_Error en cas de succès/#Return_No_Error if successful
;// #Return_Error en cas d'erreur/#Return_Error in case of failure
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// pointeur qui mémorise l'adresse du buffer mémoire/pointer that memorizes the memory buffer address
Protected *memory
;// nombre d'erreurs/number of errors
Protected NB_Error
;// positionné si une erreur intervient lors du chargement du fichier courant
Protected FilesToRead_NoError
;// test le pointeur/check pointer
If *pt_Memory = 0 Or *pt_error = 0
ProcedureReturn #Return_Error
EndIf
*memory = PeekI(*pt_Memory)
ForEach FilesToRead()
If *memory
FreeMemory(*memory)
EndIf
*memory = 0
;// on charge les données de la resource dans la mémoire, pour chaque fichier
;// The resource data is loaded into the memory, for each file
Select LoadDatasFromResource(FilesToRead()\FileName, @FilesToRead_NoError, #KCC_id, @*memory)
Case #Return_No_Error
FilesToRead()\NoError = FilesToRead_NoError
;// extrait et charge les chaînes dans la liste chainée passée en paramètre
;// Extracts and loads strings in the linked list passed as a parameter
Select ExtractStringFromMemory(StringsListeToFillUp(), @FilesToRead_NoError, @*memory)
Case #Return_No_Error
FilesToRead()\NoError = FilesToRead_NoError
Default
NB_Error + 1
FilesToRead()\NoError = FilesToRead_NoError
EndSelect
Default
FilesToRead()\NoError = FilesToRead_NoError
EndSelect
;//////////////////////////////////////////////////////////////////////////////////////////
;// ici la liste chaînée StringsListeToFillUp() contient les chaînes de la resource
;// mettre ici le code pour traiter le résultat
;// here the linked list StringsListeToFillUp () contains the resource strings
;// Put here the code to process result
Select FilesToRead()\NoError
;// affiche les résultats/displays results
Case #Return_No_KCC_Resource
;// valeur retournée lorsque la resource est absente/returned value when resource is lacking
NB_Error + 1
Debug "Fichier/File : " + FilesToRead()\FileName + Chr(10) + Space(20)+ "la resource est absente 222/resource is lacking"
Case #Return_File_No_Found
;// valeur retournée lorsque le fichier n'existe pas/returned value when the file does not exist
NB_Error + 1
Debug "Fichier/File : " + FilesToRead()\FileName + Chr(10) + Space(20)+ "le fichier n'existe pas/the file does not exist"
Case #Return_Pointer_Null
;// valeur retournée lorsque un pointeur est nul/returned value when a pointer is null
NB_Error + 1
Debug "Fichier/File : " + FilesToRead()\FileName + Chr(10) + Space(20)+ "un pointeur est nul/a pointer is null"
Case #Return_Unable_to_load_File
;// valeur retournée lorsqu'il est impossible de charger un fichier/returned value when a file can not be loaded
NB_Error + 1
Debug "Fichier/File : " + FilesToRead()\FileName + Chr(10) + Space(20)+ "impossible de charger un fichier/file can not be loaded"
Case #Return_Unable_to_Allocate_Memory
;// valeur retournée lorsqu'il est impossible d'allouer de la mémoire/returned value when unable to allocate memory
NB_Error + 1
Debug "Fichier/File : " + FilesToRead()\FileName + Chr(10) + Space(20)+ "impossible d'allouer de la mémoire/unable to allocate memory"
Case #True
Debug "Fichier/File : " + FilesToRead()\FileName + Chr(10) + " lecture/Reading of KCC resource 111 Ok" + Chr(10)
Debug "resource :"
Debug "----------- :"
ForEach StringsListeToFillUp()
Debug StringsListeToFillUp()
Next
EndSelect
Debug ""
;//////////////////////////////////////////////////////////////////////////////////////////
PokeI(*pt_error, NB_Error)
Next
If NB_Error
ProcedureReturn #Return_Error
Else
ProcedureReturn #Return_No_Error
EndIf
EndProcedure
Procedure SelectFileToProcess(List FilesToRead.File())
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// FONCTION/FUNCTION: SelectFileToProcess()
;//
;// BUT/PURPOSE: Ouvre la fenêtre de sélection des fichiers
;// Ajoute des éléments à la liste chaînée pour y stocker les noms de fichier
;// Opens the file selection window
;// Adds elements to the linked list to store file names
;//
;// PARAMETRE/PARAMETER:
;// FilesToRead - liste chaînée qui contiendra la liste des fichiers à traiter
;// linked list that will contain the list of files to process
;//
;// RETOURNE/RETURN: Rien/Nothing
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// Nom du fichier/File name
Protected file$ = ""
ClearList(FilesToRead.File())
file$ = OpenFileRequester("Open File", "", "Version (exe,dll)|*.exe;*.dll|all files (*.*)|*.*", 0, #PB_Requester_MultiSelection)
While file$
Select AddElement(FilesToRead())
Case #Null
MessageRequester("Erreur/Error","Impossible d'allouer de la mémoire pour la liste chaînée" +
Chr(10)+Chr(10)+ "Unable to allocate memory for linked list")
End
Default
FilesToRead()\FileName = file$
EndSelect
file$ = NextSelectedFileName()
Wend
EndProcedure
Procedure programme()
;// Nom du fichier/Name file
Protected file$ = ""
;// pointeur qui mémorise l'adresse du buffer mémoire/pointer that memorizes the memory buffer address
Protected *memory
;// liste chaînée qui contiendra les chaînes à écrire de la resource
;// Linked list that will contain the strings to write from the resource
Protected NewList myStringsListe.s()
;// Liste chainée qui contient la liste des fichiers à modifier
;// Linked list that contains the files list to change
Protected NewList files.File()
;// nombre d'erreurs/number of errors
Protected NB_Error
;// creation de la liste des fichiers/creation of the list files
SelectFileToProcess(files())
Select ListSize(files())
Case #Null
MessageRequester("Erreur/Error","Pas de fichier à traiter" +
Chr(10)+Chr(10)+ "No file to process")
Default
ExtractResourceString(@*memory, @NB_Error, files(), myStringsListe())
If NB_Error
MessageRequester("Error","Il y a des erreurs" + Chr(10)+"Errors occurred", #PB_MessageRequester_Info)
Else
MessageRequester("Info","Tous les fichiers ont été correctement lus" + Chr(10)+"All files have been correctly readen", #PB_MessageRequester_Info)
EndIf
EndSelect
;// libère la mémoire
If *memory
FreeMemory(*memory)
EndIf
EndProcedure
programme()
EndCode: Select all
;// Cleaner pour la resource #RT_RCDATA de fichiers exe/dll (format PE)
;// Codé par denis pour KCC
;//
;// Le code supprime la resources #KCC_id = "KwaiChangCaine" d'un fichier exe/dll (format PE) si elle existe
;// L'identifiant utilisée est de type alphanumérique, #KCC_id = "KwaiChangCaine"
;// La langue utilisée pour les données écrites est #LANG_FRENCH, #SUBLANG_FRENCH
;// la multi-sélection de fichiers est possible
;// A compiler en Unicode! et utiliser le debugger
;//
;// Cleaner for resource #RT_RCDATA of exe/dll files (PE format)
;// Coded by denis for KCC
;// The code removes the #KCC_id = "KwaiChangCaine" resources from an exe / dll file (PE format) if it exists
;// The identifier used is an alphanumeric one, #KCC_id = "KwaiChangCaine"
;// The language used for this item is #LANG_FRENCH, #SUBLANG_FRENCH
;// multiple file selection is possible
;// Compile only in Unicode! and use the debugger
EnableExplicit
;- 100 -------- Constantes
;// valeur retournée en cas d'erreur/returned value in case of failure
#Return_Error = #False
;// valeur retournée en cas de succès/returned value if successful
#Return_No_Error = #True
;// valeur retournée lorsque la resource est absente/returned value when resource is lacking
#Return_No_KCC_Resource = -1
;// valeur retournée lorsque le fichier n'existe pas/returned value when the file does not exist
#Return_File_No_Found = -2
;// identifiant de la resource en RC_DATA/RC_DATA resource identifier
#KCC_id = "KwaiChangCaine"
;// identifiant système de la resource RC_DATA/RC_DATA resource system identifier
#RT_RCDATA = 10
;-
;- 300 -------- Structure
Structure File
;// Nom du fichier/File name
FileName.s
;// résultat de l'opération de patchage:
;// #True, le patch est Ok, #False, le patchage n'est pas correct ou absent
;// result of patching operation:
;// #True, Patch is Ok, #False, patching is not correct or absent
NoError.i
EndStructure
;-
;- 500 -------- Macros
Macro MAKEINTRESOURCE(Value)
(Value & $FFFF)
EndMacro
Macro MAKELANGID(primary, sublang)
(((sublang)<<10) | (primary))
EndMacro
;-
;- -- 2000 -------- Procedures
Procedure.i Delete_KCC_Resource_FromFile(List File.File(), id.s, *pt_error)
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// FONCTION/FUNCTION: Write_RCDATA_Resource()
;//
;// BUT/PURPOSE: Supprimer les Datas en resource nommées "KwaiChangCaine" (RT_RCDATA)
;// Delete the resource data named "KwaiChangCaine" (RT_RCDATA)
;//
;// PARAMETRES/PARAMETERS:
;// File.File() - liste chaînée qui contiendra la liste des fichiers à traiter
;// linked list that will contain the list of files to process
;// File()\FileName contient le nom complet du fichier
;// File()\NoError recevra une des valeurs suivantes (résultat de l'opération de d'effacement):
;// #True, l'effacement est Ok, #False, l'effacement n'est pas correct ou la resource est absente
;// File()\FileName contains the full file name
;// File()\NoError will receive one of the following values (result of the delete operation):
;// #True, Deleting is Ok
;// #False, Deleting did not take place
;// #Return_No_KCC_Resource, resource is lacking
;// id.s - identifiant de la ressource RC_DATA/RC_DATA resource identifier
;// ici la constante définie #KCC_id/here the defined constant #KCC_id
;// *pt_error - adresse d'une variable en mémoire (variable de type integer) qui recevra le
;// nombre de fichiers en erreurs pour l'opération d'effacement de la resource
;// address of a variable in memory (integer variable) that will receive the number
;// of files in error for the resource deletion operation
;//
;// RETOURNE/RETURN: Retourne #Return_No_Error en cas de succès
;// Retourne #Return_Error en cas d'erreur
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// handle de l'API BeginUpdateResource_()/handle from the BeginUpdateResource_() API
Protected BeginUpdateResource
;// handle du bloc d'informations de la resource/handle of the resource information block
Protected Find_Resource
;// handle du bloc mémoire d'informations des données de la ressource/handle of the resource data information memory block
Protected LoadResource_RT_RCDATA
;// pointeur sur le premier octet de la ressource RT_RCDATA/pointer to the first byte of the RT_RCDATA resource
Protected *LockResource
;// attributs du fichier avant de les modifier/file attributes before modifying them
Protected FileAttributes
;// compteur d'erreur/error counter
Protected NB_Error
;// test le pointeur/check pointer
If *pt_error = 0
ProcedureReturn #Return_Error
EndIf
If ListSize(File()) = 0
ProcedureReturn #Return_Error
EndIf
ForEach File()
Select FileSize(File()\FileName)
Case -1, -2
NB_Error + 1
File()\NoError = #Return_File_No_Found
Default
;// mémorise les attributs du fichier/stores the file attributes
FileAttributes = GetFileAttributes(File()\FileName)
;// on modifie les attributs du fichier afin de le modifier/modifies the file attributes to change it
SetFileAttributes(File()\FileName, #PB_FileSystem_Normal)
;// Retrouve le handle qui sera utilisé par la fonction UpdateResource/Find the handle that will be used by the UpdateResource function
BeginUpdateResource = BeginUpdateResource_(File()\FileName, #False)
Select BeginUpdateResource
Case #Null
NB_Error + 1
Default
;// supprime la resource identifiée par id/delete the resource identified by id
Select UpdateResource_(BeginUpdateResource, #RT_RCDATA, @id, MAKEINTRESOURCE(MAKELANGID(#LANG_FRENCH, #SUBLANG_FRENCH)), #Null, 0)
Case #Return_Error
Select GetLastError_()
Case #ERROR_INVALID_PARAMETER
File()\NoError = #Return_No_KCC_Resource
EndSelect
EndUpdateResource_(BeginUpdateResource, #True)
NB_Error + 1
Default
;// ;// valide les modifications de la resource/validates resource changes
Select EndUpdateResource_(BeginUpdateResource, #False)
Case #Return_Error
EndUpdateResource_(BeginUpdateResource, #True)
NB_Error + 1
Default
File()\NoError = #True
EndSelect
EndSelect
EndSelect
;// on repositionne les attributs initiaux du fichier/repositions initial attributes of the file
If FileAttributes <> -1
SetFileAttributes(File()\FileName, FileAttributes)
EndIf
EndSelect
Next
;// retourne le nombre d'erreur dans la variable/returns the error number in the variable
PokeI(*pt_error, NB_Error)
If NB_Error
ProcedureReturn #Return_Error
Else
ProcedureReturn #Return_No_Error
EndIf
EndProcedure
Procedure SelectFileToProcess(List FilesToRead.File())
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// FONCTION/FUNCTION: SelectFileToProcess()
;//
;// BUT/PURPOSE: Ouvre la fenêtre de sélection des fichiers
;// Ajoute des éléments à la liste chaînée pour y stocker les noms de fichier
;// Opens the file selection window
;// Adds elements to the linked list to store file names
;//
;// PARAMETRE/PARAMETER:
;// FilesToRead - liste chaînée qui contiendra la liste des fichiers à traiter
;// linked list that will contain the list of files to process
;//
;// RETOURNE/RETURN: Rien/Nothing
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// Nom du fichier/File name
Protected File$ = ""
ClearList(FilesToRead.File())
File$ = OpenFileRequester("Open File", "", "Version (exe,dll)|*.exe;*.dll|all files (*.*)|*.*", 0, #PB_Requester_MultiSelection)
While File$
Select AddElement(FilesToRead())
Case #Null
MessageRequester("Erreur/Error","Impossible d'allouer de la mémoire pour la liste chaînée" +
Chr(10)+ "le programme va se terminer" +
Chr(10)+Chr(10)+ "Unable to allocate memory for linked list"+
Chr(10)+ "Program aborted")
End
Default
FilesToRead()\FileName = File$
EndSelect
File$ = NextSelectedFileName()
Wend
EndProcedure
;-
Procedure programme()
;// Nom du fichier
Protected File$ = ""
;// Liste chainée qui contient la liste des fichier à modifier
Protected NewList Files.File()
;// compteur d'erreur
Protected NB_Error
;// creation de la liste des fichiers/creation of the list files
SelectFileToProcess(Files())
Select ListSize(Files())
Case 0
MessageRequester("Erreur/Error","Pas de fichier à traiter" +
Chr(10)+Chr(10)+ "No file to process")
Default
Select Delete_KCC_Resource_FromFile(Files(), #KCC_id, @NB_Error)
Case #Return_Error
Select NB_Error
Case 0
MessageRequester("Error","La valeur du pointeur de la fonction Delete_KCC_Resource_FromFile est nulle"+
Chr(10) + "ou la liste des fichiers est vide" +
Chr(10)+Chr(10)+"The pointer value of function Delete_KCC_Resource_FromFile is nul"+
Chr(10) + "or the file list is empty" , #PB_MessageRequester_Info)
Default
ForEach Files()
Select Files()\NoError
Case #Return_File_No_Found
Debug Files()\FileName
Debug "Fichier non trouvé absente/File no found"
Debug ""
Case #Return_No_KCC_Resource
Debug Files()\FileName
Debug "Resouce absente/resource lacking"
Debug ""
Case #False
Debug Files()\FileName
Debug "impossible de modifier la resource/unable to change the resource"
Debug ""
EndSelect
Next
MessageRequester("Error","Il y a des erreurs" + Chr(10)+"Errors occurred", #PB_MessageRequester_Info)
EndSelect
Default
MessageRequester("Info","Tous les fichiers ont été correctement traités" + Chr(10)+"All files have been properly processed", #PB_MessageRequester_Info)
EndSelect
EndSelect
EndProcedure
programme()
End