source: trunk/cic-hcap/bin/windows/perl/site/lib/Win32/EventLog.pm@ 11852

Last change on this file since 11852 was 11852, checked in by mdewsnip, 18 years ago

Initial revision

  • Property svn:keywords set to Author Date Id Revision
File size: 13.2 KB
Line 
1#
2# EventLog.pm
3#
4# Creates an object oriented interface to the Windows NT Evenlog
5# Written by Jesse Dougherty
6#
7
8package Win32::EventLog;
9
10use strict;
11use vars qw($VERSION $AUTOLOAD @ISA @EXPORT $GetMessageText);
12$VERSION = '0.074';
13
14require Exporter;
15require DynaLoader;
16
17die "The Win32::Eventlog module works only on Windows NT"
18 unless Win32::IsWinNT();
19
20@ISA= qw(Exporter DynaLoader);
21@EXPORT = qw(
22 EVENTLOG_AUDIT_FAILURE
23 EVENTLOG_AUDIT_SUCCESS
24 EVENTLOG_BACKWARDS_READ
25 EVENTLOG_END_ALL_PAIRED_EVENTS
26 EVENTLOG_END_PAIRED_EVENT
27 EVENTLOG_ERROR_TYPE
28 EVENTLOG_FORWARDS_READ
29 EVENTLOG_INFORMATION_TYPE
30 EVENTLOG_PAIRED_EVENT_ACTIVE
31 EVENTLOG_PAIRED_EVENT_INACTIVE
32 EVENTLOG_SEEK_READ
33 EVENTLOG_SEQUENTIAL_READ
34 EVENTLOG_START_PAIRED_EVENT
35 EVENTLOG_SUCCESS
36 EVENTLOG_WARNING_TYPE
37);
38
39$GetMessageText=0;
40
41sub AUTOLOAD {
42 my($constname);
43 ($constname = $AUTOLOAD) =~ s/.*:://;
44 # reset $! to zero to reset any current errors.
45 local $! = 0;
46 my $val = constant($constname, @_ ? $_[0] : 0);
47 if ($!) {
48 if ($! =~ /Invalid/) {
49 $AutoLoader::AUTOLOAD = $AUTOLOAD;
50 goto &AutoLoader::AUTOLOAD;
51 }
52 else {
53 my ($pack,$file,$line) = caller;
54 die "Unknown Win32::EventLog macro $constname, at $file line $line.\n";
55 }
56 }
57 eval "sub $AUTOLOAD { $val }";
58 goto &$AUTOLOAD;
59}
60
61#
62# new()
63#
64# Win32::EventLog->new("source name", "ServerName");
65#
66sub new {
67 die "usage: PACKAGE->new(SOURCENAME[, SERVERNAME])\n" unless @_ > 1;
68 my ($class,$source,$server) = @_;
69 my $handle;
70
71 # Create new handle
72 if ($source !~ /\\/) {
73 OpenEventLog($handle, $server, $source);
74 }
75 else {
76 OpenBackupEventLog($handle, $server, $source);
77 }
78 return bless {handle => $handle,
79 Source => $source,
80 Computer => $server} => $class;
81}
82
83sub DESTROY {shift->Close}
84
85#
86# Open (the rather braindead old way)
87# A variable initialized to empty must be supplied as the first
88# arg, followed by whatever new() takes
89#
90sub Open {
91 $_[0] = Win32::EventLog->new($_[1],$_[2]);
92}
93
94sub OpenBackup {
95 my ($class,$source,$server) = @_;
96 OpenBackupEventLog(my $handle, $server, $source);
97 return bless {handle => $handle,
98 Source => $source,
99 Computer => $server} => $class;
100}
101
102sub Backup {
103 die " usage: OBJECT->Backup(FILENAME)\n" unless @_ == 2;
104 my ($self,$file) = @_;
105 return BackupEventLog($self->{handle}, $file);
106}
107
108sub Close {
109 my $self = shift;
110 CloseEventLog($self->{handle});
111 $self->{handle} = 0;
112}
113
114# Read
115# Note: the EventInfo arguement requires a hash reference.
116sub Read {
117 my $self = shift;
118
119 die "usage: OBJECT->Read(FLAGS, RECORDOFFSET, HASHREF)\n" unless @_ == 3;
120
121 my ($readflags,$recordoffset) = @_;
122 # The following is stolen shamelessly from Wyt's tests for the registry.
123 my $result = ReadEventLog($self->{handle}, $readflags, $recordoffset,
124 my $header, my $source, my $computer, my $sid,
125 my $data, my $strings);
126 my ($length,
127 $reserved,
128 $recordnumber,
129 $timegenerated,
130 $timewritten,
131 $eventid,
132 $eventtype,
133 $numstrings,
134 $eventcategory,
135 $reservedflags,
136 $closingrecordnumber,
137 $stringoffset,
138 $usersidlength,
139 $usersidoffset,
140 $datalength,
141 $dataoffset) = unpack('l6s4l6', $header);
142
143 # make a hash out of the values returned from ReadEventLog.
144 my %h = ( Source => $source,
145 Computer => $computer,
146 Length => $datalength,
147 Category => $eventcategory,
148 RecordNumber => $recordnumber,
149 TimeGenerated => $timegenerated,
150 Timewritten => $timewritten,
151 EventID => $eventid,
152 EventType => $eventtype,
153 ClosingRecordNumber => $closingrecordnumber,
154 User => $sid,
155 Strings => $strings,
156 Data => $data,
157 );
158
159 # get the text message here
160 if ($result and $GetMessageText) {
161 GetEventLogText($source, $eventid, $strings, $numstrings, my $message);
162 $h{Message} = $message;
163 }
164
165 if (ref($_[2]) eq 'HASH') {
166 %{$_[2]} = %h; # this needed for Read(...,\%foo) case
167 }
168 else {
169 $_[2] = \%h;
170 }
171 return $result;
172}
173
174sub GetMessageText {
175 my $self = shift;
176 local $^W;
177 GetEventLogText($self->{Source},
178 $self->{EventID},
179 $self->{Strings},
180 $self->{Strings} =~ tr/\0/\0/,
181 my $message);
182
183 $self->{Message} = $message;
184 return $message;
185}
186
187sub Report {
188 die "usage: OBJECT->Report( HASHREF )\n" unless @_ == 2;
189 my ($self,$EventInfo) = @_;
190
191 die "Win32::EventLog::Report requires a hash reference as arg 2\n"
192 unless ref($EventInfo) eq "HASH";
193
194 my $computer = $EventInfo->{Computer} ? $EventInfo->{Computer}
195 : $self->{Computer};
196 my $source = exists($EventInfo->{Source}) ? $EventInfo->{Source}
197 : $self->{Source};
198
199 return WriteEventLog($computer, $source, $EventInfo->{EventType},
200 $EventInfo->{Category}, $EventInfo->{EventID}, 0,
201 $EventInfo->{Data}, split(/\0/, $EventInfo->{Strings}));
202
203}
204
205sub GetOldest {
206 my $self = shift;
207 die "usage: OBJECT->GetOldest( SCALAREF )\n" unless @_ == 1;
208 return GetOldestEventLogRecord($self->{handle},$_[0]);
209}
210
211sub GetNumber {
212 my $self = shift;
213 die "usage: OBJECT->GetNumber( SCALARREF )\n" unless @_ == 1;
214 return GetNumberOfEventLogRecords($self->{handle}, $_[0]);
215}
216
217sub Clear {
218 my ($self,$file) = @_;
219 die "usage: OBJECT->Clear( FILENAME )\n" unless @_ == 2;
220 return ClearEventLog($self->{handle}, $file);
221}
222
223bootstrap Win32::EventLog;
224
2251;
226__END__
227
228=head1 NAME
229
230Win32::EventLog - Process Win32 Event Logs from Perl
231
232=head1 SYNOPSIS
233
234 use Win32::EventLog
235 $handle=Win32::EventLog->new("Application");
236
237=head1 DESCRIPTION
238
239This module implements most of the functionality available from the
240Win32 API for accessing and manipulating Win32 Event Logs. The access
241to the EventLog routines is divided into those that relate to an
242EventLog object and its associated methods and those that relate other
243EventLog tasks (like adding an EventLog record).
244
245=head1 The EventLog Object and its Methods
246
247The following methods are available to open, read, close and backup
248EventLogs.
249
250=over 4
251
252=item Win32::EventLog->new(SOURCENAME [,SERVERNAME]);
253
254The new() method creates a new EventLog object and returns a handle
255to it. This hande is then used to call the methods below.
256
257The method is overloaded in that if the supplied SOURCENAME
258argument contains one or more literal '\' characters (an illegal
259character in a SOURCENAME), it assumes that you are trying to open
260a backup eventlog and uses SOURCENAME as the backup eventlog to
261open. Note that when opening a backup eventlog, the SERVERNAME
262argument is ignored (as it is in the underlying Win32 API). For
263EventLogs on remote machines, the SOURCENAME parameter must
264therefore be specified as a UNC path.
265
266=item $handle->Backup(FILENAME);
267
268The Backup() method backs up the EventLog represented by $handle. It
269takes a single arguemt, FILENAME. When $handle represents an
270EventLog on a remote machine, FILENAME is filename on the remote
271machine and cannot be a UNC path (i.e you must use F<C:\TEMP\App.EVT>).
272The method will fail if the log file already exists.
273
274=item $handle->Read(FLAGS, OFFSET, HASHREF);
275
276The Read() method read an EventLog entry from the EventLog represented
277by $handle.
278
279=item $handle->Close();
280
281The Close() method closes the EventLog represented by $handle. After
282Close() has been called, any further attempt to use the EventLog
283represented by $handle will fail.
284
285=item $handle->GetOldest(SCALARREF);
286
287The GetOldest() method number of the the oldest EventLog record in
288the EventLog represented by $handle. This is required to correctly
289compute the OFFSET required by the Read() method.
290
291=item $handle->GetNumber(SCALARREF);
292
293The GetNumber() method returns the number of EventLog records in
294the EventLog represented by $handle. The number of the most recent
295record in the EventLog is therefore computed by
296
297 $handle->GetOldest($oldest);
298 $handle->GetNumber($lastRec);
299 $lastRecOffset=$oldest+$lastRec;
300
301=item $handle->Clear(FILENAME);
302
303The Clear() method clears the EventLog represented by $handle. If
304you provide a non-null FILENAME, the EventLog will be backed up
305into FILENAME before the EventLog is cleared. The method will fail
306if FILENAME is specified and the file refered to exists. Note also
307that FILENAME specifies a file local to the machine on which the
308EventLog resides and cannot be specified as a UNC name.
309
310=item $handle->Report(HASHREF);
311
312The Report() method generates an EventLog entry. The HASHREF should
313contain the following keys:
314
315=over 4
316
317=item C<Computer>
318
319The C<Computer> field specfies which computer you want the EventLog
320entry recorded. If this key doesn't exist, the server name used to
321create the $handle is used.
322
323=item C<Source>
324
325The C<Source> field specifies the source that generated the EventLog
326entry. If this key doesn't exist, the source name used to create the
327$handle is used.
328
329=item C<EventType>
330
331The C<EventType> field should be one of the constants
332
333=over 4
334
335=item C<EVENTLOG_ERROR_TYPE>
336
337An Error event is being logged.
338
339=item C<EVENTLOG_WARNING_TYPE>
340
341A Warning event is being logged.
342
343=item C<EVENTLOG_INFORMATION_TYPE>
344
345An Information event is being logged.
346
347=item C<EVENTLOG_AUDIT_SUCCESS>
348
349A Success Audit event is being logged (typically in the Security
350EventLog).
351
352=item C<EVENTLOG_AUDIT_FAILURE>
353
354A Failure Audit event is being logged (typically in the Security
355EventLog).
356
357=back
358
359These constants are exported into the main namespace by default.
360
361=item C<Category>
362
363The C<Category> field can have any value you want. It is specific to
364the particular Source.
365
366=item C<EventID>
367
368The C<EventID> field should contain the ID of the message that this
369event pertains too. This assumes that you have an associated message
370file (indirectly referenced by the field C<Source>).
371
372=item C<Data>
373
374The C<Data> field contains raw data associated with this event.
375
376=item C<Strings>
377
378The C<Strings> field contains the single string that itself contains
379NUL terminated sub-strings. This are used with the EventID to generate
380the message as seen from (for example) the Event Viewer application.
381
382=back
383
384=back
385
386=head1 Other Win32::EventLog functions.
387
388The following functions are part of the Win32::EventLog package but
389are not callable from an EventLog object.
390
391=over 4
392
393=item GetMessageText(HASHREF);
394
395The GetMessageText() function assumes that HASHREF was obtained by
396a call to C<$handle-E<gt>Read()>. It returns the formatted string that
397represents the fully resolved text of the EventLog message (such as
398would be seen in the Windows NT Event Viewer). For convenience, the
399key 'Message' in the supplied HASHREF is also set to the return value
400of this function.
401
402If you set the variable $Win32::EventLog::GetMessageText to 1 then
403each call to C<$handle-E<gt>Read()> will call this function automatically.
404
405=back
406
407=head1 Example 1
408
409The following example illustrates the way in which the EventLog module
410can be used. It opens the System EventLog and reads through it from
411oldest to newest records. For each record from the B<Source> EventLog
412it extracts the full text of the Entry and prints the EventLog message
413text out.
414
415 use Win32::EventLog;
416
417 $handle=Win32::EventLog->new("System", $ENV{ComputerName})
418 or die "Can't open Application EventLog\n";
419 $handle->GetNumber($recs)
420 or die "Can't get number of EventLog records\n";
421 $handle->GetOldest($base)
422 or die "Can't get number of oldest EventLog record\n";
423
424 while ($x < $recs) {
425 $handle->Read(EVENTLOG_FORWARDS_READ|EVENTLOG_SEEK_READ,
426 $base+$x,
427 $hashRef)
428 or die "Can't read EventLog entry #$x\n";
429 if ($hashRef->{Source} eq "EventLog") {
430 Win32::EventLog::GetMessageText($hashRef);
431 print "Entry $x: $hashRef->{Message}\n";
432 }
433 $x++;
434 }
435
436=head1 Example 2
437
438To backup and clear the EventLogs on a remote machine, do the following :-
439
440 use Win32::EventLog;
441
442 $myServer="\\\\my-server"; # your servername here.
443 my($date)=join("-", ((split(/\s+/, scalar(localtime)))[0,1,2,4]));
444 my($dest);
445
446 for my $eventLog ("Application", "System", "Security") {
447 $handle=Win32::EventLog->new($eventLog, $myServer)
448 or die "Can't open Application EventLog on $myServer\n";
449
450 $dest="C:\\BackupEventLogs\\$eventLog\\$date.evt";
451 $handle->Backup($dest)
452 or warn "Could not backup and clear the $eventLog EventLog on $myServer ($^E)\n";
453
454 $handle->Close;
455 }
456
457Note that only the Clear method is required. Note also that if the
458file $dest exists, the function will fail.
459
460=head1 BUGS
461
462None currently known.
463
464The test script for 'make test' should be re-written to use the
465EventLog object.
466
467=head1 AUTHOR
468
469Original code by Jesse Dougherty for HiP Communications. Additional
470fixes and updates attributed to Martin Pauley
471<[email protected]>) and Bret Giddings ([email protected]).
Note: See TracBrowser for help on using the repository browser.