IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Utilisation des FilesMapping sous C++ Builder

Ce tutoriel démontre l'utilisation des File Mapping avec un exemple d'application

Sources du Programme disponible ici. ♪

Article lu   fois.

L'auteur

Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Définition

Files Mapping est une des plus puissantes fonctionnalités 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 Fichiers 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.
Image non disponible

II. 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.

II-A. API utilisées

  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 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 fichiers Mappés sur disque avec la valeur 0 en précisant l'adresse de départ ainsi que le nombre d'éléments à supprimer

II-B. 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 :

  • @@Testbitmap@Finalize
  • @@Testbitmap@Initialize
  • @Classes@TComponent@UpdateRegistry$qqr4boolx17System@AnsiStringxt2
  • @Forms@TForm@$bctr$qqrp18Classes@TComponent
  • @Forms@TForm@$bdtr$qqrv

ce qui ne donne pas une représentation très professionnelle de l'exécutable fourni. Les exécutables 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.

II-C. 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 partie GUI non portable sur un autre compilateur, l'adaptation du code est par contre possible.

II-D. Cahier des Charges

  • Établir 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.

III. Définition du GUI

Image non disponible

III-A. 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

Cliquer avec la touche droite de la souris sur la tool Bar et créer quatre Boutons

TToolsButtons

ToolsButtons1

TToolsButtons

ToolsButtons2

TToolsButtons

ToolsButtons3

TToolsButtonsl

ToolsButtons4

III-B. ImageList

Nous allons créer Charger les Images dans le composant ImageList1

choisir cinq Images dans les fichiers communs de Borland

Image1

Open File

Image2

Execute

Image3

Cancel

Image4

Close

Image5

Help

Image non disponible

III-C. ActionsList

Ouvrir le composant ActionList1

Nom

Caption

Image

OnExecute

OpenFile

Open

*

OpenFileExecute

Execute

Execute

*

ExecuteExecute

CancelAction

Cancel

*

CancelActionExecute

About

À propos de

*

AboutExecute

*= Index de l'image choisie

Image non disponible

III-D. Menu Principal

Création d'un menu selon image suivante :

Image non disponible

donner aux Items Actions les valeurs suivantes

Item

Action

Open

OpenFile

Execute

Execute

Close

CloseApp

À Propos de

About

III-E. Tools Buttons

Donner 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é.

IV. Classe TMMF

Pour travailler en C++ avec les API WIN32 il est préférable de déclarer une nouvelle classe.

IV-A. 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.

IV-B. Déclaration de la classe

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
#ifndef MMFH
#define MMFH
#include <vcl.h>
//---------------------------------------------------------------------------
class TMMF {
    
        private :
        HANDLE FFileMap;
        HANDLE FFileHandle;
        void * FMappingPtr;
        DWORD FFileSize;
        DWORD FFileSizeHigh;
        AnsiString FFileName;
        AnsiString FErrorMsg;
        void __fastcall GetFile();
        void __fastcall GetMapping();
        void __fastcall GetPtrAdresse();
        void __fastcall GetSizeofFile();
        
    protected :
    
        public :
        __fastcall TMMF();
        __fastcall TMMF(AnsiString FileName);
        __fastcall ~TMMF();
        bool __fastcall Execute();
        __property HANDLE FileHandle = { read = FFileHandle };
        __property HANDLE MappingHandle = { read = FFileMap };
        __property void * PtrMapping = { read = FMappingPtr };
        __property AnsiString ErrorMessage = { read = FErrorMsg };
        __property DWORD FileSize = { read = FFileSize };
        
    
} //---------------------------------------------------------------------------

définitions des champs

Champs

description

HANDLE FFileMap

Contient le Handle du fichier Ouvert

HANDLE FFileHandle

Contient le Nom du Fichier

void* FMappingPtr

Contient le pointeur sur la zone mappée

DWORD FFileSize

Contient la taille du fichier mappé

DWORD FFileSizeHigh

Contient la taille haute du fichier mappé

AnsiString FFileName

Contient le nom du fichier à mappé

AnsiString FErrorMsg

Contient le message d'erreur

définitions des méthodes

Méthode

partie

description

__fastcall TMMF()

public

Constructeur par défault

__fastcall TMMF(AnsiString FileName)

public

Constructeur avec nom du fichier

__fastcall ~TMMF();

public

destructeur

bool __fastcall Execute()

public

appel des différentes fonctions

void __fastcall GetFile()

private

initialise FfileHandle

void __fastcall GetPtrAdresse()

private

initialise FMappingPtr

void __fastcall GetSizeofFile()

private

initialise FfileSize et FfileSizeHigh

IV-C. Implémentation de la classe

Constructeur

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
#include "MMF.h"
//---------------------------------------------------------------------------
__fastcall TMMF::TMMF()
    :FFileMap(NULL),
    FFileHandle(NULL),
    FMappingPtr(NULL),
    FFileSize(0),
    FFileSizeHigh(0),
    FFileName(""),
    FErrorMsg("")
    
{
    
}

IV-D. Constructeur avec FileName

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
//---------------------------------------------------------------------------
__fastcall TMMF::TMMF(AnsiString FileName) 
    :FFileMap(NULL),
    FFileHandle(NULL),
    FMappingPtr(NULL),
    FFileSize(0),
    FFileSizeHigh(0),
    FFileName(""),
    FErrorMsg("")
    
{
    FFileName=FileName;
    
} //---------------------------------------------------------------------------

IV-E. Destructeur

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
__fastcall TMMF::~TMMF()
{
    if (FMappingPtr)
    {
        UnmapViewOfFile(FMappingPtr);
        FMappingPtr=NULL;
        }
    if (FFileMap)
    { 
        CloseHandle(FFileMap);
        FFileMap=NULL;
        } 
    if (FFileHandle)
    { 
        CloseHandle(FFileHandle);
        FFileHandle=NULL;
        } 
    
} //---------------------------------------------------------------------------

IV-F. Méthode GetFile

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
void __fastcall TMMF::GetFile()
{
    FFileHandle=CreateFile(FFileName.c_str(), // pointer to name of the file
    
        GENERIC_READ|GENERIC_WRITE, // access (read-write) mode
        FILE_SHARE_READ|FILE_SHARE_WRITE,// share mode
        NULL, // pointer to security attributes
        OPEN_EXISTING, // how to create
        FILE_ATTRIBUTE_NORMAL, // file attributes
        NULL); //TODO: Add your source code here
        
    if (FFileHandle==NULL |(long )FFileHandle==-1)
    RaiseLastOSError();
    
} //---------------------------------------------------------------------------

IV-G. Méthode GetMapping

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
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); //
        
    if (!FFileMap)
    RaiseLastOSError();
    
} //---------------------------------------------------------------------------

IV-H. Méthode GetPtrAdresse

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
void __fastcall TMMF::GetPtrAdresse()
{
    FMappingPtr=MapViewOfFile(FFileMap,
    
        FILE_MAP_ALL_ACCESS,
        0,
        0,
        0);
        
    if (!FMappingPtr)
    RaiseLastOSError();
    
}

IV-I. Méthode Execute

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
bool __fastcall TMMF::Execute()
{
    try 
    {
        GetFile();
        GetMapping();
        GetPtrAdresse();
        }
    catch (EOSError &E)
    {
        FErrorMsg=E.Message;
        return false;
        }
    GetSizeofFile();
    return true;
    
}

IV-J. Méthode GetSizeofFile

 
Sélectionnez
1.
2.
3.
4.
void __fastcall TMMF::GetSizeofFile()
{
    FFileSize=GetFileSize(FFileHandle,&FFileSizeHigh); 
}

IV-K. Explicatif

Généralement les APIwin32 retournent 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()

IV-L. Description des méthodes

IV-L-1. Le constructeur

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
__fastcall TMMF::TMMF(AnsiString FileName)
    :FFileMap(NULL),
    FFileHandle(NULL),
    FMappingPtr(NULL),
    FFileSize(0),
    FFileSizeHigh(0),
    FFileName(""),
    FErrorMsg("")
    
{
    FFileName=FileName;
    
} }

initialise les membres de la classe puis copie dans FFileName le paramètre du constructeur.

IV-L-2. le Destructeur

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
__fastcall TMMF::~TMMF()
{
    if (FMappingPtr)
    {
        UnmapViewOfFile(FMappingPtr);
        FMappingPtr=NULL;
        }
    if (FFileMap)
    { 
        CloseHandle(FFileMap);
        FFileMap=NULL;
        } 
    if (FFileHandle)
    { 
        CloseHandle(FFileHandle);
        FFileHandle=NULL;
        } 
    
} //---------------------------------------------------------------------------

teste l'état des différents pointeurs , libère la zone mappée ainsi que les handles de fichiers

IV-L-3. méthode GetFile()

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
void __fastcall TMMF::GetFile()
{
    FFileHandle=CreateFile(FFileName.c_str(), // pointer to name of the file
    
        GENERIC_READ|GENERIC_WRITE, // access (read-write) mode
        FILE_SHARE_READ|FILE_SHARE_WRITE,// share mode
        NULL, // pointer to security attributes
        OPEN_EXISTING, // how to create
        FILE_ATTRIBUTE_NORMAL, // file attributes
        NULL); //TODO: Add your source code here
        
    if (FFileHandle==NULL |(long )FFileHandle==-1)
    RaiseLastOSError();
    
} //---------------------------------------------------------------------------

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

IV-L-4. méthode GetMapping

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
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); //
        
    if (!FFileMap)
    RaiseLastOSError();
    
} //---------------------------------------------------------------------------

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.

IV-L-5. méthode GetPtrAdresse

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
void __fastcall TMMF::GetPtrAdresse()
{
    FMappingPtr=MapViewOfFile(FFileMap,
    
        FILE_MAP_ALL_ACCESS,
        0,
        0,
        0);
        
    if (!FMappingPtr)
    RaiseLastOSError();
    
}

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.

IV-L-6. méthode GetSizeofFile

 
Sélectionnez
1.
2.
3.
4.
void __fastcall TMMF::GetSizeofFile()
{
    FFileSize=GetFileSize(FFileHandle,&FFileSizeHigh);
    }

cette méthode initialise les deux champs membres FFileSize et FFileSizeHigh avec la longueur du fichier obtenu par l'appel à GetFileSize.

IV-L-7. méthode Execute

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
bool __fastcall TMMF::Execute()
{
    try 
    {
        GetFile();
        GetMapping();
        GetPtrAdresse();
        }
    catch (EOSError &E)
    {
        FErrorMsg=E.Message;
        return false;
        }
    GetSizeofFile();
    return true;
    
}

la méthode Execute est le cœur 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.

V. Classe Tform

Déclaration de la classe

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
//---------------------------------------------------------------------------
#ifndef mainH
#define mainH
//---------------------------------------------------------------------------
#include lt;Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Dialogs.hpp>
#include <ActnList.hpp>
#include <ComCtrls.hpp>
#include <ExtCtrls.hpp>
#include <ImgList.hpp>
#include <Menus.hpp>
#include <ToolWin.hpp>
#define ExeKeyName "exefile\\shell"
#define CommandKeyName "ExportCleaner\\Command"
#define PrgKeyName "ExportCleaner"
#define Command "ExportCleaner.exe %1"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
    __published: // Composants g&#195;&#169;r&#195;&#169;s par l'EDI
    TPanel *Panel1;
    TToolBar *ToolBar1;
    TOpenDialog *OpenDialog1;
    TMainMenu *MainMenu1;
    TImageList *ImageList1;
    TActionList *ActionList1;
    TAction *OpenFile;
    TAction *Execute;
    TAction *CloseApp;
    TEdit *Edit1;
    TButton *Button1;
    TLabel *Label1;
    TMenuItem *Open1;
    TMenuItem *Execute1;
    TMenuItem *Open2;
    TMenuItem *Close1;
    TMenuItem *N3;
    TAction *CancelAction;
    TStatusBar *StatusBar1;
    TToolButton *ToolButton1;
    TToolButton *ToolButton2;
    TToolButton *ToolButton5;
    TToolButton *ToolButton6;
    TMenuItem *Aide;
    TAction *About;
    TMenuItem *AProposde1;
    void __fastcall OpenFileExecute(TObject *Sender);
    void __fastcall CloseAppExecute(TObject *Sender);
    void __fastcall ExecuteExecute(TObject *Sender);
    void __fastcall CancelActionExecute(TObject *Sender);
    void __fastcall FormDestroy(TObject *Sender);
    void __fastcall AboutExecute(TObject *Sender);
    private :
    AnsiString FileName; // D&#195;&#169;clarations de l'utilisateur
    void * DirectoryEntry;
    void __fastcall CleanPtr();
    void __fastcall ParseCmdLine();
    public : // D&#195;&#169;clarations de l'utilisateur
    __fastcall TForm1(TComponent* Owner);
    
} ;
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

nous allons déclarer dans la partie private de la classe TForm1 les champs Suivants :

 
Sélectionnez
1.
2.
AnsiString FileName; // D&#195;&#169;clarations de l'utilisateur
void* DirectoryEntry;

les Méthodes suivantes :

 
Sélectionnez
1.
2.
void__fastcall CleanPtr();
void__fastcall ParseCmdLine();

description des champs :

  • FileName est utilisé pour stocker le nom de l'exécutable à traiter ;
  • DirectoryEntry est un pointeur sur la directoy entry de l'exécutable.

V-A. Constructeur

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
    
{
    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 hanldes de fichiers sont tous libérés l'appel à la méthode ParseCmdLine permet de controler si une ligne de commande est présente.

V-B. Méthode OpenFileExecute

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
void __fastcall TForm1::OpenFileExecute(TObject *Sender)
{ 
    if (OpenDialog1->Execute())
    {
        FileName=OpenDialog1->FileName;
        Edit1->Text= FileName;
        StatusBar1->SimpleText="Please Press Execute";
        }
    Execute->Enabled = (FileName!="");
    }

cette méthode appelée depuis le menu ou un Tools Button affiche une DialogBox Standard qui permet la saisie de l'exécutable à traiter.

V-C. Méthode CloseApp

 
Sélectionnez
1.
2.
3.
4.
void __fastcall TForm1::CloseAppExecute(TObject *Sender)
{ 
    Close();
    }

Appelle la fermeture du programme.

V-D. Méthode ExecuteExecute

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
void __fastcall TForm1::ExecuteExecute(TObject *Sender)
{ 
    ULONG DSize;
    IMAGE_NT_HEADERS * myImage;
    DWORD HeaderSum,CheckSum ;
    TMMF * myMMF = new TMMF(FileName);
    Execute->Enabled=false;
    OpenFile->Enabled=false;
    if (myMMF->Execute())
    { 
        try 
        { 
            DirectoryEntry=ImageDirectoryEntryToData(myMMF->PtrMapping,
            false,
            IMAGE_DIRECTORY_ENTRY_EXPORT,
            &DSize );
            if (!DirectoryEntry)
            RaiseLastOSError();
            FlushViewOfFile(DirectoryEntry,DSize);
            myImage= CheckSumMappedFile(myMMF->PtrMapping,
            myMMF->FileSize,
            &HeaderSum,
            &CheckSum);
            myImage->OptionalHeader.DataDirectory[0].VirtualAddress=0L;
            myImage->OptionalHeader.DataDirectory[0].Size=0L;
            }
        catch (EOSError &E)
        { 
            StatusBar1->SimpleText="Exe File Contains no Export Directories";
            MessageDlg(StatusBar1->SimpleText,mtInformation,TMsgDlgButtons()<< mbOK, 0);
            delete myMMF;
            CleanPtr();
            OpenFile->Enabled=true;
            return ;
            } 
        StatusBar1->SimpleText="Saved Successfuly ..." ;
        MessageDlg(StatusBar1->SimpleText,mtInformation, TMsgDlgButtons()<< mbOK, 0);
        }
    else 
    { 
        MessageDlg(myMMF->ErrorMessage, mtError, TMsgDlgButtons() << mbOK, 0);
        StatusBar1->SimpleText="Error occurs ....";
        }
    delete myMMF;
    CleanPtr();
    OpenFile->Enabled=true;
    }

cette méthode est le cœur du programme

 
Sélectionnez
1.
    IMAGE_NT_HEADERS * myImage; DWORD HeaderSum,CheckSum ; ULONG DSize;

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

 
Sélectionnez
1.
    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'exécutable par un appel a l'API WIN32 ImageDirectoryEntryToData. En cas de retour avec une valeur NULL une exception est déclenchée

Cette exception est interceptée dans le Bloc Catch qui affiche une boîte de dialogue Affiche un 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

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
myImage= CheckSumMappedFile(

    pMap,
    FielSize,
    &HeaderSum,
    &CheckSum);
    myImage->OptionalHeader.DataDirectory[0].VirtualAddress=0L;
    myImage->OptionalHeader.DataDirectory[0].Size=0L;

l'Api CheckSumMappedFile nous renvoie un pointeur sur IMAGE_NT_HEADERS, ainsi que la taille du Header et son check Summ on positionne à la taille à 0

 
Sélectionnez
1.
2.
    myImage->OptionalHeader.DataDirectory[0].VirtualAddress=0L;
    myImage->OptionalHeader.DataDirectory[0].Size=0L;

On affiche le résultat des opérations dans la StatusBar ,ainsi que dans une boite de dialogue , détruit le myMMF,et sort de la méthode

V-E. Méthode CleanPtr

 
Sélectionnez
1.
2.
3.
4.
5.
6.
void __fastcall TForm1::CleanPtr()
{ 
    DirectoryEntry=NULL;
    FileName=NULL;
    Edit1->Text="";
    }

la méthode CleanPtr réinitialise les variables,ainsi que le champ Edit1->Text

V-F. Méthode CancelActionExecute

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
void __fastcall TForm1::CancelActionExecute(TObject *Sender)
{ 
    OpenFile->Enabled=true;
    Execute->Enabled=false;
    CleanPtr();
    StatusBar1->SimpleText="Please Select exe File";
    }

Cancel annule les ordres en cours , appelle cleanPtr, et remet le système dans son état de départ

V-G. Méthode FormDestroy

 
Sélectionnez
1.
2.
3.
4.
void __fastcall TForm1::FormDestroy(TObject *Sender)
{ 
    CleanPtr();
    }

Form Destroy Appelé par Close() libère la mémoire

V-H. Méthode ParseCmdLine

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
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 clic bouton droit de la souris de lancer le programme exportCLeaner.exe

une boite de dialogue vous indique le résultat de l'opération

La ligne de commande avec une valeur égale à /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 commandes 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 exécutable et si la réponse est positive on lance l'application.

VI. Installation 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 choisir $TDW.
  • Sélectionner le bouton Insérer.
  • Sélectionner le bouton OK.

ExportCleaner est désormais installé et apparait dans la liste d'outils.

VII. Utilisation dans C++ Builder

  • Compiler un nouveau projet.
  • Sélectionner dans le menu Outil l'item ExportCleaaner.
  • À la fin de l'exécution 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
  • La technique des PatchFiles C++ Builder
  • Maîtrisez les files d'impression sous windows C++ Builder
  • Travailler avec les Interfaces en C++Builder Partie 1 C++ Builder
  • Composant de gestion des ports d'imprimantes C++ Builder
  • Programme de Test Version ActiveX du composant TDLIoport Delphi

Sans oublier :

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2013 DjmSoftware. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.