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.
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▲
- CreateFile
- CreateFileMapping
- MapiewOfFile
- MapViewOfFileEx
- OpenMappedFile
- UmpapViewOfFile
- FlushViewOfFile
Explication des API
CreateFile : Permet de créer ou d'ouvrir les objets suivants :
- files
- pipes
- mailslots
- communications resources
- disk devices (Windows NT only)
- consoles
- 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▲
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 |
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
III-D. Menu Principal▲
Création d'un menu selon image suivante :
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▲
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
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▲
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▲
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▲
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▲
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▲
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▲
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▲
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▲
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▲
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()▲
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▲
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▲
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▲
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▲
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
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éré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éclarations de l'utilisateur
void
*
DirectoryEntry;
void
__fastcall CleanPtr
(
);
void
__fastcall ParseCmdLine
(
);
public : // Dé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 :
2.
AnsiString FileName; // Déclarations de l'utilisateur
void
*
DirectoryEntry;
les Méthodes suivantes :
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▲
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▲
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▲
2.
3.
4.
void
__fastcall TForm1::CloseAppExecute
(
TObject *
Sender)
{
Close
(
);
}
Appelle la fermeture du programme.
V-D. Méthode ExecuteExecute▲
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
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
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
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
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▲
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▲
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▲
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▲
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 :