Files Mapping est une des plus puissantes fonctionnalité API Win32 permettant de partager dans la mémoire attribuée
à chaque Processus (2 Gb) des zones de mémoires physiques ou de fichiers stockés sur disque.
Il est alors possible de travailler de manière avec le contenu d'un fichier ou contenu mémoire
Les Fichiers sur disques peuvent être des tous de types même le système Page Files
Les Fichires peuvent être chargés entièrement ou découpés en bloc
La seule limitation est que l'on ne peut pas utiliser des fichiers se trouvant sur une autre Computer
1. Avantages
Partage mémoire entre plusieurs Processus de manière à communiquer entre eux
Accès très rapide aux fichiers sur le disque
Mise a jour de DLL, etc
1.1. API Utilisée
1. CreateFile
2. CreateFileMapping
3. MapiewOfFile
4. MapViewOfFileEx
5. OpenMappedFile
6. UmpapViewOfFile
7. FlushViewOfFile
Explication des Api
CreateFile
Permet de créer ou d'ouvrir les objets suivants
1. files
2. pipes
3. mailslots
4. communications resources
5. disk devices (Windows NT only)
6. consoles
7. directories (open only)
CreateFileMapping
Crée un un object de mémoire partagée Nommé ou anonyme MapiewOfFile
Mappe dans la zone mémoire du process l'object précédemment obtenu par l'appel à Create FileMapping MapViewOfFileEx
Identique à MapiewOfFile mais avec la possibilité supplémentaire d'indiquer ou l'object
FileMapping doit être placé dans la mémoire du process appelant OpenFileMapping
Ouvre un object FileMapping
Cette fonction est généralement utilisée pour connaître le Handle d'un object FileMapping UmpapViewOfFile
Retire de l'espace mémoire du process l'object FileMapping FlushViewOfFile
Permet de remplir des fichier Mappés sur dique avec la valeur 0 en précisant
l'adresse de départ ainsi que le nombre d'éléments à supprimer
1.2. Programme d'exemple
Dans le but de démontrer une utilisation possible des Mapping Files
Je vous propose une application
J'ai remarqué que depuis la version 3 du compilateur Borland C++ Builder
La table d'exportation de l'exécutable généré est toujours emplie avec des symboles
plus ou moins barbares du genre suivant
ce qui ne donne pas une représentation très professionnelle de l'exécutable fourni
les exécutable générés par Delphi ne souffrent pas de ce défaut
l'application proposée à l'utilité de supprimer la table d'exportation des exécutables
générés par C++ Builder
1.3. Limitation
Ce programme est écrit en C++ à l'aide de C++ Builder 6
Dans ce programme est utilisé certaines fonctionnalités VCL qui rendent la parti GUI
non portable sur une autre compilateur, l'adaptation du code est par contre possible
1.4. Cahier des Charges
Etablir un Tools avec un GUI
Permettre la possibilité d'installer et de désinstaller ce programme dans la Shell
Permettre le fonctionnement via une ligne de commande
Permettre la Commande Via la Shell (Touche droite de la souris sur un fichier Exe)
· Création d'une classe de travail pour les Files Mapping
2. Définition du GUI
2.1. définition de la forme principale
Pour Commencer nous allons définir la forme Principale
Déposer les Composants suivants sur une Form
1 TAction List
ActionList1
1 TImageList
ImageList1
1 TMainMenu
MainMenu1
1 TOpenDialog
OpenDialog1
1 TTool Bar
Align = alTop
1 TPanel
Align = alClient
1 TStatusBar
""
Déposer les Composants sur le Panel
1 Tedit
Edit1
1 Tbutton
Button1
1 Tlabel
Label1
Clicker avec la touche droite de la souris sur la tool Bar et créer 4 Boutons
TToolsButtons
ToolsButtons1
TToolsButtons
ToolsButtons2
TToolsButtons
ToolsButtons3
TToolsButtonsl
ToolsButtons4
2.2. ImageList
Nous allons créer Charger les Images dans le composant ImageList1
choisir 5 Images dans les fichiers communs de Borland
Image1
Open File
Image2
Execute
Image3
Cancel
Image4
Close
Image5
Help
2.3. ActionsList
Ouvrir le composant ActionList1
Nom
Caption
Image
OnExecute
OpenFile
Open
*
OpenFileExecute
Execute
Execute
*
ExecuteExecute
CancelAction
Cancel
*
CancelActionExecute
About
A propos de
*
AboutExecute
*= Index de l'image choisie
2.3. Menu Principal
Création d'un menu selon Image Suivante
donnez aux Items Actions les valeurs suivantes
Item
Action
Open
OpenFile
Execute
Execute
Close
CloseApp
A Propos de
About
2.4. Tools Buttons
Donnez aux aux Actions de Buttons les Valeurs Suivantes
Item
Action
ToolButton1
OpenFile
ToolButton2
Execute
CancelAction
CancelAction
ToolButton6
CloseApp
Le design de l'application est maintenant terminé
3. Classe TMMF
Pour travailler en C++ avec les API WIN32 il est préférable de déclarer une nouvelle classe
3.1. But de cette classe
Encapsuler les Api relatives aux Files Mapping
Fournir via l'appel a une méthode public un pointeur sur une zone mappée
Dans le cas d'une erreur fournir un message d'erreur win32
3.2. Déclaration de la classe
#ifndef MMFH #define MMFH #include <vcl.h> //--------------------------------------------------------------------------- class TMMF {
Généralement les APIwin32 retourne un code indiquant si l'opération désirée s'est terminée par un succès
Une valeur de 0 ou true indique une opération terminée avec succès
Dans le cas contraire un appel GetLastError() nous retourne le code d'erreur
La VCL intègre une classe EOSError permettant de retourner dans la variable membre Message
le code ainsi que le message d'erreur
Il suffit donc de tester la sortie de l'api et en cas d'insuccès de générer une exception
De type EOSError par un appel à RaiseLastOSError()
La classe d'exception EOSError est intégrée dans C++ builder 6 dans les versions précédentes
On peut utiliser la classe d'exception EWin32Error et pour le déclenchement
d'une exception de ce type l'appel à RaiseLastWin32Error()
cette méthode utilise l'API WIN32 CreateFile pour obtenir un Handle de fichier
le champ FFileHandle contient le Handle du fichier
si la valeur de retour est différente d'un Handle Valide on génère une exception
méthode GetMapping
void__fastcall TMMF::GetMapping() {
FFileMap=CreateFileMapping(FFileHandle, // handle to file to map
NULL, // optional security attributes
PAGE_READWRITE, // protection for mapping object
0, // high-order 32 bits of object size
0, // low-order 32 bits of object size
NULL); //
cette méthode utilise l'API WIN32 CreateFileMapping pour créer une zone commune en mémoire
et retourner dans le le champ FFileMap un Handle sur cette zone
si la valeur de retour est NULL on génère une exception
cette méthode utilise l'API WIN32 MapViewofFile qui retourne dans FMappingPtr
un pointeur sur la zone mappée en mémoire avec FFileMap en paramètre
si la valeur de retour est NULL on génère une exception
la méthode Execute est le cur de cette classe , elle appelle successivement dans une partie protégée
du programme (try catch) GetFile,GetMapping,GetPtrAdresse
en cas d'erreur dans une de ces méthodes la variable FerrorMessage
est initialisée avec le message d'erreur retournée par le système d'exploitation
{
pMap=NULL;
CleanPtr();
StatusBar1->SimpleText="Please Select exe File"; if (ParamCount()>=1)
ParseCmdLine(); // appel avec une ligne de commande
}
on appelle un méthode pour s'assurer que les pointeurs sont dans un état défini,
et que les hanlde de fichiers sont tous libéré
l'appel à la méthode ParseCmdLine permet de controler si une ligne de commande est présente
MyImage est un pointeur sur la structure IMAGE_NT_HEADERS qui contient la
Strucuture du fichier dans le monde Windows PE32
HeaderSum,CheckSum,Dsize sont des variables de Travail
TMMF * myMMF = new TMMF(FileName);
MyMMF contient une instance de la classe TMMF
L'appel à la méthode Execute va nous retourner un pointeur sur la zone mappée
Dans un bloc protégé on va tenter d'obtenir dans DirectoryEntry un pointeur sur la table d'exportation
de l'executable par un appel a l'API WIN32 ImageDirectoryEntryToData
En cas de retour avec une valeur NULL une execption est déclenchée
Cette exeption est interceptée dans le Bloc Catch qui affiche une boîte de dialogue
Affiche une message dans la ligne de Status, détruit le myMMF,et sort de la méthode
si tout c'est bien passé Il nous reste maintenant à supprimer cette table d'exportation à l'aide
FlushViewOfFile(DirectoryEntry,DSize);
Nous devons maintenant ajuster l'entête PE de notre exécutable à une valeur correcte
void__fastcall TForm1::ParseCmdLine()
{
AnsiString Tmp; int ParamNr=ParamCount(); if (ParamNr ==1) // Command Line Exists
{
AnsiString cmd=ParamStr(1).UpperCase(); if ((cmd =="/INSTALL") ||(cmd =="/UNINSTALL"))
{
TRegistry* mReg= new TRegistry(); try
{
mReg->RootKey=HKEY_CLASSES_ROOT;
mReg->OpenKey(ExeKeyName,false); // open Shell Key in registry if (cmd =="/INSTALL")
}{ if (!mReg->KeyExists(PrgKeyName))
{
mReg->OpenKey(CommandKeyName,true); // Command Install
mReg->WriteString("",Command);
MessageDlg("Export Cleaner installed Succesfuly", mtInformation, TMsgDlgButtons() << mbOK, 0);
}
}
}
if (cmd =="/UNINSTALL")
{ if (mReg->KeyExists(PrgKeyName))
mReg->DeleteKey(PrgKeyName); // delete Registry Key
MessageDlg("Export Cleaner desinstalled Succesfuly", mtInformation, TMsgDlgButtons() << mbOK, 0);
}
} catch (...)
{
mReg->CloseKey();
} delete mReg;
Application->Terminate(); // Exit Application
} else
{ for (int i=0;i<ParamNr;i++)
{
Tmp+=ParamStr(i+1);
Tmp+=" ";
}
Tmp.Delete(Tmp.Length(),1); //delete Last Space
FileName=Tmp; if ((!FileExists(Tmp)) &&(ExtractFileExt(Tmp)!=".exe") )
MessageBox(Application->Handle, "File Not Exist or Not a valid Exe File", "Export Cleaner",
MB_OK|MB_ICONINFORMATION); else ExecuteExecute(NULL); // Call suppress
Application->Terminate(); // Exit Application
}
}
}
cette méthode teste la présence d'une ligne de commande
si la ligne de commande est égale à INSTALL le programme installe dans la registry
un shell pour les fichiers de type exe
ce qui permettra avec un click bouton droit de la souris la possibilité de lancer le
programme exportCLeaner.exe
une boite de dialogue vous indique le résultat de l'opération
La ligne de commande avec un une valeur egale à /UNINSTALL supprimera de la registry la shell
pour les fichiers de type exe
si une ligne de commande est présente et n'est pas égale aux commdes d'installation cela signifie
que le paramètre est le nom du fichier exe à traiter
on test s'il s'agit bien d'un fichier executable et si la réponse est positive on lance l'application
5. Instalation dans C++ Builder
dans le menu Outils sélectionner Configurer les outils
sélectionner ajouter
Dans le champ Titre insérer ExportCLeaner
sélectionner le bouton Parcourir et sélectionner le fichier ExportCleaner.exe
sélectionner le bouton Macro dans la listBox choisisser $TDW
sélectionner le bouton Insérer
sélectionner le bouton OK
ExportCleaner est désormais installé et apparait dans la liste d'outils
6. Utilisation dans C++ Builder
Compiler un nouveau projet
sélectionner dans le menu Outil l'item ExportCleaaner
a la fin de l'excution du programme une boite de dialogue vous indique le résultat de l'opération
Voir également mes autres articles :
Utilisation des Files Mapping sous C++Builder
C++ Builder
Ce document est issu de
http://www.developpez.com
et reste la propriété exclusive de son auteur.
La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.