Je suis 90% d'accord avec Patrick88, les 10% c'est parce que je ne sais pas à quoi correspond la zone enregistrement.
Je met
toujours toujours les procedures avant d'écrire le code de la boucle.
Je rajoute que je met la datasection complètement à la fin.
J'ai pris l'habitude de commenter presque chaque ligne de code, ça ne prend que peut de temps et c'est pratique si on revient dessus plusieurs mois plus tard. Lorsqu'un truc me parait important , j'ajoute des lignes de commentaire pour expliquer.
aujourd'hui j'évite d'imbriquer des if dans des if dans des if dans des if ... car sur de grands codes, on s'y perd et si une erreur intervient, c'est pas toujours simple à retrouver.
Je vous met une procedure extraite du code sur lequel je travaille, beaucoup de tests et de procedureReturn, mais c'est simple, clair et ça marche bien.
Je ne dis pas que c'est la meilleure manière mais elle me convient et a l'avantage à mes yeux de clarifier le code.
J'utilise un décalage de 5 espaces, ça améliore la lecture.
Code:
Procedure.i IS_Format_NE(hModule)
;///////////////////////////////////////////////////////////////////////////////////////////////////
;//
;// FONCTION: IS_Format_NE()
;//
;// BUT: tester une partie du header du fichier en mémoire pour déterminer si ce fichier
;// est un fichier 16 bits (format NE - Windows 3.x)
;//
;// PARAMS: hModule - pointeur sur le premier octet de la mémoire allouée pour charger le fichier icl
;//
;// RETOURNE: #True si le fichier est au format NE
;// #Return_Error (= #Fasle) si le fichier n'est pas au format NE
;//
;// UTILISATION : Typiquement, on l'utilise immédiatement après avoir chargé le fichier en mémoire
;// Plusieurs fonctions utilisent une partie de ce code mais sans en faire les tests car
;// ils ont été faits dans cette procedure
;//
;///////////////////////////////////////////////////////////////////////////////////////////////////
;// mémorise l'adresse du contenu de la ressource, à partir du début du fichier modifié dans chaque boucle
Protected *Memory_Add_temp
;// memorise la dernière adresse valide du fichier en mémoire pour vérifier le non dépassement
Protected *LastMemoryAdress
;// mémorise l'offset de la zone NE depuis le début du fichier (pas l'adresse, l'offset depuis le début du fichier)
Protected Offset_NE_Header
;// mémorise l'offset de la Resource Table (pas l'adresse, l'offset depuis le début du fichier)
Protected Offset__Resource_Table
;// mémorise le coefficient de mutiplication de l'offset permettant de multiplier les valeurs virtuelles pour obtenir les valeurs réeelles
Protected rscAlignShift
;// on teste si le pointeur est nul, on stoppe si null
If hModule = #Null
SetError_Code(#Error_Code_Pointeur_Null)
ProcedureReturn #Return_Error
EndIf
;// mémorise la valeur du pointeur, ce pointeur va évoluer
*Memory_Add_temp = hModule
;// teste la taille de la mémoire qui doit valoir au moins 2 octets pour lire #IMAGE_DOS_SIGNATURE
If MemorySize(*Memory_Add_temp)<SizeOf(word)
SetError_Code(#Error_Code_Reading_Over_LastMemoryFileAdress)
ProcedureReturn #Return_Error
EndIf
;// on avance le pointeur sur la zone d'énumération après avoir testé le header
;// Lecture et vérification de la signature MS-DOS du fichier, "MZ"
If UPeekW(*Memory_Add_temp)<>#IMAGE_DOS_SIGNATURE
SetError_Code(#Error_Code_IMAGE_DOS_SIGNATURE)
ProcedureReturn #Return_Error
EndIf
;// définition de la dernière adresse de la mémoire, ne pas écrire après !
*LastMemoryAdress = *Memory_Add_temp + MemorySize(*Memory_Add_temp)-1
;// vérifie que les adresses de la zone IMAGE_DOS_HEADER sont définies
If (*Memory_Add_temp + SizeOf(IMAGE_DOS_HEADER))>*LastMemoryAdress
SetError_Code(#Error_Code_Reading_Over_LastMemoryFileAdress)
ProcedureReturn #Return_Error
EndIf
;// lecture de l'offset du NE header
Offset_NE_Header = PeekL(*Memory_Add_temp + OffsetOf(IMAGE_DOS_HEADER\e_lfanew))
;// teste que l'offset est différent de 0 sinon erreur
If Offset_NE_Header = 0
SetError_Code(#Error_Code_OFFSET_NULL_ICL_NE)
ProcedureReturn #Return_Error
EndIf
;// avance le pointeur pour arriver sur la zone IMAGE_OS2_HEADER
;// cette zone commence à l'adresse de base + la valeur de la variable Offset_NE_Header
*Memory_Add_temp + Offset_NE_Header
;// vérifie que les adresses de la zone IMAGE_OS2_HEADER sont définies
If (*Memory_Add_temp + SizeOf(IMAGE_OS2_HEADER)>*LastMemoryAdress)
SetError_Code(#Error_Code_Reading_Over_LastMemoryFileAdress)
ProcedureReturn #Return_Error
EndIf
;// vérification de la signature, élément ne_magic.w (Magic number) de la structure IMAGE_OS2_HEADER
If UPeekW(*Memory_Add_temp)<>#IMAGE_OS2_SIGNATURE
SetError_Code(#Error_OS2_SIGNATURE)
ProcedureReturn #Return_Error
EndIf
;// lecture de l'offset de la table des ressources
Offset__Resource_Table = UPeekW(*Memory_Add_temp + OffsetOf(IMAGE_OS2_HEADER\ne_rsrctab))
If Offset__Resource_Table = #Null
SetError_Code(#Error_Offset__Resource_Table_Null)
ProcedureReturn #Return_Error
EndIf
;// on positionne le pointeur sur la Resource Table
*Memory_Add_temp + Offset__Resource_Table
;// vérifie que les adresses de la zone RESOURCE_TABLE sont définies
If (*Memory_Add_temp + SizeOf(RESOURCE_TABLE)>*LastMemoryAdress) Or (Offset__Resource_Table<1)
SetError_Code(#Error_Code_Reading_Over_LastMemoryFileAdress)
ProcedureReturn #Return_Error
EndIf
;// Lecture du décalage, élément de la table de ressources
rscAlignShift = UPeekW(*Memory_Add_temp + OffsetOf(RESOURCE_TABLE\rscAlignShift))
;// teste que le décalage existe et limite à 1Go la taille possible avec un décalage de 14
If (rscAlignShift<0) Or (rscAlignShift>14)
SetError_Code(#Error_RESOURCE_TABLE_rscAlignShift)
ProcedureReturn #Return_Error
EndIf
ProcedureReturn #True
EndProcedure