|
PRÉSENTATION :
Les fichiers log de Windows visibles habituellement dans la gestion de l'ordinateur.
NOTES :
Le programme présenté ici permet de lire les fichiers standard "Application", "Security" et "System". Pour les fichiers
utilisateurs, il suffit de donner le nom l'ors de l'ouverture de fichier évènements.
Ces fichiers et fonctions ne sont utilisables que sous Windows NT/2000 ou XP
CODE :
Unit Unit1;
//
// Sujet : Lecture des fichiers LOG de Windows
//
// Par Nono40 : http://nono40.developpez.com http://nono40.fr.st
// mailto:nono40@fr.st
//
// Le 10/11/2003
//
Interface
Uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, ExtCtrls;
Type
TForm1 = Class(TForm)
Panel1: TPanel;
btnAppli: TButton;
Liste: TListView;
btnSecu: TButton;
btnSys: TButton;
Procedure ListeClick(Sender: TObject);
Procedure btnAppliClick(Sender: TObject);
Procedure btnSecuClick(Sender: TObject);
Procedure btnSysClick(Sender: TObject);
Private
{ Déclarations privées }
Procedure AfficherLog(NomLog:String);
Public
{ Déclarations publiques }
End;
Var
Form1: TForm1;
Implementation
{$R *.dfm}
// Définition du type d'enregistrement utilisé
// pour la lecture des évènements.
// Attention, il n'y a ici que la partie fixe.
// le reste de la structure étant variable d'un
// évènement à l'autre, il n'est pas défini ici.
Type
PEventLogRecord = ^TEventLogRecord;
TEventLogRecord = Packed Record
Length : DWord; // Longueur totale
// y compris la partie variable
Reserved : DWord;
RecordNumber : DWord; // Numéro enregistrement
TimeGenerated : DWord; // Heure de l'évènement
TimeWritten : DWord; // Heure de son enregistrement
EventID : DWord; // ID ( Dépend de la source )
EventType : Word; // Type d'évènement
NumStrings : Word; // Nombre de chaines de détail
EventCategory : Word; // Catégorie ( Dépend de la source )
ReservedFlags : Word;
ClosingRecordNumber : DWord;
StringOffset : DWord; // Offset de la première chaine de détail
UserSidLength : DWord; // Longueur du SID
UserSidOffset : DWord; // Offset du début du SID
DataLength : DWord; // Longueur des données
DataOffset : DWord; // Offset du début des données
End;
Const
// Définition des constantes d'accès aux fichiers LOG
EVENTLOG_SEQUENTIAL_READ = $0001;
EVENTLOG_SEEK_READ = $0002;
EVENTLOG_FORWARDS_READ = $0004;
EVENTLOG_BACKWARDS_READ = $0008;
// Taille par défaut du buffer de lecture
buffer_size=100000;
Var
// Vriables contenant le fichier Log en cours de lecture
LogEnCours:String='';
Procedure TForm1.AfficherLog(NomLog: String);
Var
hLog : THandle;
pEvent : PEventLogRecord ;
bBuffer : Array[0..BUFFER_SIZE-1]Of Char;
dwRead : DWord;
dwNeeded : DWord;
Source : String;
Ordinateur : String;
Utilisateur : Array[0..255]Of Char;
lUtilisateur : DWord;
Domaine : Array[0..255]Of Char;
lDomaine : DWord;
SidUse : Cardinal;
pStr : PChar;
DateBase : TDateTime;
DateHeure : TDateTime;
Begin
// Mémorisation du fichier LOG en cours de lecture
LogEnCours := NomLog;
// Les dates/heures inclues dans les fichiers log
// sont données en secondes à partir du 01/01/1970 à 00:00
DateBase:=EncodeDate(1970,1,1);
// Ouverture du fichier LOG
hLog := OpenEventLog( Nil, // Ordinateur local
PChar(LogEnCours)); // Fichier voulu
If hLog = 0 Then
Begin
ShowMessage('Impossible d''ouvrir le fichier LOG');
Exit;
End;
// On fait pointer pEvent sur le début du buffer
pEvent := PEventLogRecord(@bBuffer);
// Effacement de la liste
Liste.Clear;
Liste.Items.BeginUpdate;
Try
// L'ouverture du fichier Log place la lecture en début de
// fichier. Il est donc possible de le lire de façon séquetielle.
While ReadEventLog(hLog, // Handle du fichier
EVENTLOG_FORWARDS_READ Or // Lecture en avant
EVENTLOG_SEQUENTIAL_READ, // Lecture séquentielle
0, // Position ignorée en séquentielle
pEvent, // Pointeur vers le buffer
BUFFER_SIZE, // Taille du buffer
dwRead, // Nombre d'octets lus
dwNeeded) Do // Nombre d'octets demandés
Begin
// Il est possible de lire plusieurs enregistrement en une fois
// il faut donc balayer tout le buffer
While (dwRead > 0) Do
Begin
// Affichage des informations
With Liste.Items.Add Do
Begin
// La propriété Data va contenir le numéro d'enregistrement
// pour pouvoir le lire directement lors du double-click
Data:=Pointer(pEvent.RecordNumber);
// Type d'évènement
Case pEvent^.EventType Of
EVENTLOG_ERROR_TYPE : Caption:='Erreur';
EVENTLOG_WARNING_TYPE : Caption:='Avertissement';
EVENTLOG_INFORMATION_TYPE : Caption:='Information';
EVENTLOG_AUDIT_SUCCESS : Caption:='Audit réussi';
EVENTLOG_AUDIT_FAILURE : Caption:='Erreur audit';
End;
// Date et Heure de l'évènement
DateHeure:=DateBase+pEvent.TimeGenerated/24/3600;
SubItems.Add(FormatDateTime('DD/MM/YYYY',DateHeure));
SubItems.Add(FormatDateTime('HH:NN:SS' ,DateHeure));
// Catégorie
If pEvent.EventCategory=0
Then SubItems.Add('Aucune')
Else SubItems.Add(IntToStr(pEvent.EventCategory));
SubItems.Add(IntToStr(pEvent.EventID And $FFFF));
// Utilisateur lié à lévènement
If pEvent.UserSidLength=0 Then
Begin
SubItems.Add('N/A')
End Else
Begin
// Il faut lire les informations du SID contenu
// dans l'enregistrement. Ce SID est à UserSidOffset octets
// du début de l'enregistrement.
pStr := PChar(pEvent);
Inc(pStr,pEvent.UserSidOffset);
lUtilisateur := SizeOf(Utilisateur);
lDomaine := SizeOf(Domaine);
LookUpAccountSID(Nil,pStr,Utilisateur,lUtilisateur,Domaine,lDomaine,SidUse);
SubItems.Add(Utilisateur)
End;
// Lecture de la source et du nom de l'ordinateur
// Ces infos sont situées à la suite de la partie
// fixe de l'enregistrement.
pStr := PChar(pEvent);
Inc(pStr,sizeof(TEventLogRecord));
Source := pStr;
Inc(pStr,Length(Source)+1);
Ordinateur := pStr;
SubItems.Add(Ordinateur);
SubItems.Add(Source);
// Affichage si des chaines de détails sont présentes.
If pEvent.NumStrings<>0
Then SubItems.Add('Oui')
Else SubItems.Add('Non');
End;
// Réduction de la longueur lue
DwRead:=DWRead - pEvent.Length;
// Passage à l"enregistrement suivant.
Inc(PByte(pEvent),pEvent.Length);
End;
// Remise du pointeur en début de buffer pour
// la prochaine lecture
pEvent := PEventLogRecord(@bBuffer);
End;
Finally
Liste.Items.EndUpdate;
End;
// Fermeture du handle
CloseEventLog(hLog);
End;
Procedure TForm1.ListeClick(Sender: TObject);
Var
hLog : THandle;
pEvent : PEventLogRecord ;
bBuffer : Array[0..BUFFER_SIZE-1]Of Char;
dwRead : DWord;
dwNeeded : DWord;
pStr : PChar;
UneChaine : String;
LesChaine : String;
i : Integer;
Begin
// Si pas de fichier en cours on sort
If LogEnCours='' Then Exit;
// Si pas de ligne sélectionnée on sort
If Liste.Items[Liste.ItemIndex]=Nil Then Exit;
// Ouverture du fichier LOG
hLog := OpenEventLog( Nil, // Ordinateur local
PChar(LogEnCours)); // Fichier voulu
If hLog = 0 Then
Begin
ShowMessage('Impossible d''ouvrir le fichier LOG');
Exit;
End;
// On fait pointer pEvent sur le début du buffer
pEvent := PEventLogRecord(@bBuffer);
// Lecture d'un enregistrement
If ReadEventLog(hLog, // Handle
EVENTLOG_SEEK_READ Or // Lecture directe
EVENTLOG_FORWARDS_READ, // Lecture en avant
// On se sert du champ Data pour connaitre le
// numéro d'enregistrement à lire
Cardinal(Liste.Items[Liste.ItemIndex].Data),
pEvent, // Pointeur vers le buffer
BUFFER_SIZE, // Taille du buffer
dwRead, // Nombre d'octets lus
dwNeeded) Then // Nombre d'octets demandés
Begin
// Recherche de l'adresse de la première chaine
pStr := PChar(pEvent);
Inc(pStr,pEvent.StringOffset);
LesChaine:='';
// Lecture des chaines de détail
For i:=1 To pEvent.NumStrings Do
Begin
UneChaine:=pStr;
// Les chaines se suivent les unes
// derrière les autres, ( chaine à zéro terminal )
Inc(pStr,Length(UneChaine)+1);
LesChaine:=LesChaine+UneChaine+#13;
End;
End;
// Fermeture du fichier
CloseEventLog(hLog);
// Affichage des chaines de détail
If LesChaine<>'' Then ShowMessage(LesChaine);
End;
Procedure TForm1.btnAppliClick(Sender: TObject);
Begin
AfficherLog('Application');
End;
Procedure TForm1.btnSecuClick(Sender: TObject);
Begin
AfficherLog('Security');
End;
Procedure TForm1.btnSysClick(Sender: TObject);
Begin
AfficherLog('System');
End;
end.
|
| |