File Coverage

blib/lib/Win32/Mock/Win32/EventLog.pm
Criterion Covered Total %
statement 21 135 15.5
branch 0 32 0.0
condition 0 7 0.0
subroutine 7 31 22.5
pod 0 23 0.0
total 28 228 12.2


line stmt bran cond sub pod time code
1             package # hide from PAUSE
2             Win32::EventLog;
3 1     1   1496 use strict;
  1         3  
  1         40  
4 1     1   6 use warnings;
  1         2  
  1         28  
5 1     1   6 use Carp;
  1         2  
  1         75  
6 1     1   6 use Exporter ();
  1         2  
  1         19  
7              
8             {
9 1     1   5 no strict;
  1         1  
  1         120  
10             $VERSION = "0.01";
11             @ISA = qw(Exporter);
12             @EXPORT = qw(
13             EVENTLOG_AUDIT_FAILURE
14             EVENTLOG_AUDIT_SUCCESS
15             EVENTLOG_BACKWARDS_READ
16             EVENTLOG_END_ALL_PAIRED_EVENTS
17             EVENTLOG_END_PAIRED_EVENT
18             EVENTLOG_ERROR_TYPE
19             EVENTLOG_FORWARDS_READ
20             EVENTLOG_INFORMATION_TYPE
21             EVENTLOG_PAIRED_EVENT_ACTIVE
22             EVENTLOG_PAIRED_EVENT_INACTIVE
23             EVENTLOG_SEEK_READ
24             EVENTLOG_SEQUENTIAL_READ
25             EVENTLOG_START_PAIRED_EVENT
26             EVENTLOG_SUCCESS
27             EVENTLOG_WARNING_TYPE
28             );
29             }
30              
31 1     1   7 use vars qw($GetMessageText);
  1         2  
  1         102  
32             use constant {
33 1         2529 TRUE => !!1,
34             FALSE => !!0,
35              
36             ELF_LOG_SIGNATURE => 0x654c664c,
37              
38             # Event Types
39             EVENTLOG_SUCCESS => 0x0000,
40             EVENTLOG_ERROR_TYPE => 0x0001,
41             EVENTLOG_WARNING_TYPE => 0x0002,
42             EVENTLOG_INFORMATION_TYPE => 0x0004,
43             EVENTLOG_AUDIT_SUCCESS => 0x0008,
44             EVENTLOG_AUDIT_FAILURE => 0x0010,
45              
46             # ReadEventLog() flags
47             EVENTLOG_SEQUENTIAL_READ => 0x0001,
48             EVENTLOG_SEEK_READ => 0x0002,
49             EVENTLOG_FORWARDS_READ => 0x0004,
50             EVENTLOG_BACKWARDS_READ => 0x0008,
51              
52             # don't know what these are, and can't find the actual values
53             EVENTLOG_START_PAIRED_EVENT => 0x0001,
54             EVENTLOG_PAIRED_EVENT_ACTIVE => 0x0002,
55             EVENTLOG_PAIRED_EVENT_INACTIVE => 0x0004,
56             EVENTLOG_END_PAIRED_EVENT => 0x0008,
57             EVENTLOG_END_ALL_PAIRED_EVENTS => 0x0010,
58 1     1   14 };
  1         2  
59              
60              
61             # singleton for storing events
62             my %main_eventlog = (
63             # HOSTNAME => {
64             # SOURCE => [
65             # {
66             # Category => ...,
67             # EventType => ...,
68             # EventID => ...,
69             # Data => ...,
70             # Strings => ...,
71             # },
72             # {
73             # ...
74             # },
75             # ]
76             # }
77             );
78              
79             # index of last read record
80             my $last_read_record = 0;
81              
82             #use XXX; END { YYY \%main_eventlog }
83              
84              
85             #
86             # new()
87             # ---
88             sub new {
89 0     0 0   my ($class, $source, $computer) = @_;
90 0 0         $class = ref $class if ref $class;
91 0 0         croak "error: missing source" unless $source;
92 0           my $handle;
93              
94             # create new handle
95 0 0         if ($source =~ /\\/) {
96 0           OpenBackupEventLog($handle, $computer, $source);
97             }
98             else {
99 0           OpenEventLog($handle, $computer, $source)
100             }
101              
102             #$handle ||= ( $main_eventlog{$computer}{$source} ||= [] );
103              
104 0           my $self = bless {
105             handle => $handle, Source => $source, Computer => $computer
106             }, $class;
107              
108 0           return $self
109             }
110              
111              
112             sub DESTROY {
113             shift->Close
114 0     0     }
115              
116              
117             #
118             # Open()
119             # ----
120             sub Open {
121 0     0 0   $_[0] = Win32::EventLog->new($_[1], $_[2]);
122             }
123              
124              
125             #
126             # OpenBackup()
127             # ----------
128             sub OpenBackup {
129 0     0 0   my ($class, $source, $computer) = @_;
130              
131 0           OpenBackupEventLog(my $handle, $computer, $source);
132              
133 0           my $self = bless {
134             handle => $handle, Source => $source, Computer => $computer
135             }, $class;
136              
137 0           return $self
138             }
139              
140              
141             #
142             # Backup()
143             # ------
144             sub Backup {
145 0     0 0   my ($self, $filename) = @_;
146 0 0         die " usage: OBJECT->Backup(FILENAME)\n" unless @_ == 2;
147 0           return BackupEventLog($self->{handle}, $filename);
148             }
149              
150              
151             #
152             # Close()
153             # -----
154             sub Close {
155 0     0 0   my ($self) = @_;
156 0           CloseEventLog($self->{handle});
157 0           $self->{handle} = 0;
158             }
159              
160              
161             #
162             # Read()
163             # ----
164             sub Read {
165 0     0 0   my ($self, $flags, $offset, $entry_r) = @_;
166              
167             # fetch the event
168 0           my $rc = ReadEventLog(
169             $self->{handle}, $flags, $offset,
170             # these variables are set by ReadEventLog():
171             my $header, my $source, my $computer, my $sid, my $data, my $strings
172             );
173              
174             # decode the header
175 0           my ($length, $reserved, $record_number, $time_generated, $time_written,
176             $event_id, $event_type, $num_strings, $event_category, $reserved_flags,
177             $closing_record_number, $string_offset, $user_sid_length, $user_sid_offset,
178             $data_length, $data_offset) = unpack("l6s4l6", $header);
179              
180             # make a hash out of the values returned from ReadEventLog()
181 0           my %record = (
182             Source => $source,
183             Computer => $computer,
184             RecordNumber => $record_number,
185             TimeGenerated => $time_generated,
186             Timewritten => $time_written,
187             Category => $event_category,
188             EventType => $event_type,
189             EventID => $event_id,
190             User => $sid,
191             Strings => $strings,
192             Data => $data,
193             Length => $data_length,
194             ClosingRecordNumber => $closing_record_number,
195             );
196              
197             # get the text message here
198 0 0 0       if ($rc and $GetMessageText) {
199 0           GetEventLogText($source, $event_id, $strings, $num_strings, my $message);
200 0           $record{Message} = $message;
201             }
202              
203 0 0         if (ref $entry_r eq 'HASH') {
204 0           %{$entry_r} = %record # needed for the Read(..., \%foo) case
  0            
205             }
206             else {
207 0           $_[2] = \%record
208             }
209              
210 0           return $rc
211             }
212              
213              
214             #
215             # GetMessageText()
216             # --------------
217             sub GetMessageText {
218 0     0 0   my ($self) = @_;
219            
220 0           GetEventLogText(
221             $self->{Source}, $self->{EventID}, $self->{Strings},
222             $self->{Strings} =~ tr/\0/\0/, my $message
223             );
224              
225 0           $self->{Message} = $message;
226 0           return $message
227             }
228              
229              
230             #
231             # Report()
232             # ------
233             sub Report {
234 0     0 0   my ($self, $EventInfo) = @_;
235 0 0         die "usage: OBJECT->Report( HASHREF )\n" unless @_ == 2;
236 0 0         die "Win32::EventLog::Report requires a hash reference as arg 2\n"
237             unless ref($EventInfo) eq "HASH";
238              
239 0 0         my $computer = $EventInfo->{Computer} ? $EventInfo->{Computer}
240             : $self->{Computer};
241 0 0         my $source = exists($EventInfo->{Source}) ? $EventInfo->{Source}
242             : $self->{Source};
243              
244 0           return WriteEventLog(
245             $computer, $source, $EventInfo->{EventType},
246             $EventInfo->{Category}, $EventInfo->{EventID}, 0,
247             $EventInfo->{Data}, split(/\0/, $EventInfo->{Strings})
248             );
249             }
250              
251              
252             #
253             # GetOldest()
254             # ---------
255             sub GetOldest {
256 0     0 0   my ($self, $event_r) = @_;
257 0 0         die "usage: OBJECT->GetOldest( SCALAREF )\n" unless @_ == 2;
258 0           return GetOldestEventLogRecord($self->{handle}, $event_r);
259             }
260              
261              
262             #
263             # GetNumber()
264             # ---------
265             sub GetNumber {
266 0     0 0   my ($self, $event_r) = @_;
267 0 0         die "usage: OBJECT->GetNumber( SCALARREF )\n" unless @_ == 2;
268 0           return GetNumberOfEventLogRecords($self->{handle}, $event_r);
269             }
270              
271              
272             #
273             # Clear()
274             # -----
275             sub Clear {
276 0     0 0   my ($self, $file) = @_;
277 0 0         die "usage: OBJECT->Clear( FILENAME )\n" unless @_ == 2;
278 0           return ClearEventLog($self->{handle}, $file);
279             }
280              
281              
282             # =========================================================================
283             # Mocked XS Functions
284             # =========================================================================
285              
286             #
287             # ReadEventLog()
288             # ------------
289             # http://msdn2.microsoft.com/en-us/library/aa363674.aspx
290             #
291             sub ReadEventLog ($$$\$\$\$\$\$\$) {
292 0     0 0   my ($eventlog, $flags, $offset, $event_header_r, $source_r, $computer_r,
293             $sid_r, $data_r, $strings_r) = @_;
294              
295             # set all these variables as some are not used even under real Win32::EventLog
296 0           $$event_header_r = $$source_r = $$computer_r = $$data_r = $$sid_r = $$strings_r = "";
297              
298             # find the record number to read
299 0           my $record_num = $last_read_record;
300              
301 0 0         if ($flags & EVENTLOG_SEEK_READ) {
302 0           $record_num = $offset
303             }
304             else { # default to EVENTLOG_SEQUENTIAL_READ
305 0 0         if ($flags & EVENTLOG_BACKWARDS_READ) {
306 0           $record_num--
307             }
308             else { # default to EVENTLOG_FORWARDS_READ
309 0           $record_num++
310             }
311             }
312              
313             # read the record
314 0           my $record = $eventlog->[$record_num];
315 0           my $user_sid = "$<-$("; # UID-GID
316 0           my $strings_num = $record->{Strings} =~ tr/\0/\0/;
317              
318             # construct the event header
319 0           $$event_header_r = pack("l6s4l6" =>
320             0, # length
321             ELF_LOG_SIGNATURE, # reserved
322             $record->{RecordNumber}, # record number
323             $record->{TimeGenerated}, # time generated
324             $record->{Timewritten}, # time written
325             $record->{EventID}, # event ID
326             $record->{EventType}, # event type
327             $strings_num, # number of strings
328             $record->{Category}, # event category
329             0, # reserved flags
330             0, # closing record number
331             0, # string offset
332             length $user_sid, # user sid length
333             0, # user sid offset
334             0, # data length
335             0, # data offset
336             );
337              
338             # set the variables
339 0           $$source_r = $record->{Source};
340 0           $$computer_r = $record->{Computer};
341 0           $$sid_r = $user_sid;
342 0           $$data_r = $record->{Data};
343 0           $$strings_r = $record->{Strings};
344              
345 0           return TRUE
346             }
347              
348              
349             #
350             # WriteEventLog()
351             # -------------
352             sub WriteEventLog {
353 0     0 0   my ($computer, $source, $event_type, $category, $event_id, $reserved,
354             $data, @strings) = @_;
355              
356             # get the singleton
357 0           my $eventlog = $main_eventlog{$computer}{$source};
358              
359             # prepare fields
360 0   0       $reserved ||= ELF_LOG_SIGNATURE;
361 0           my $now = time();
362              
363             # store the event
364 0           push @$eventlog, {
365             Computer => $computer,
366             Source => $source,
367 0           RecordNumber => $#{$eventlog}+1,
368             TimeGenerated => $now,
369             Timewritten => $now,
370             Category => $category,
371             EventType => $event_type,
372             EventID => $event_id,
373             Reserved => $reserved,
374             Data => $data,
375             Strings => \@strings,
376             };
377              
378 0           return TRUE
379             }
380              
381              
382             #
383             # GetEventLogText()
384             # ---------------
385             sub GetEventLogText ($$$$\$) {
386 0     0 0   my ($source, $event_id, $strings, $strings_num, $message_r) = @_;
387 0           $$message_r = join "", "[$source/EventId:$event_id] ", split /\0/, $strings;
388 0           return TRUE
389             }
390              
391              
392             #
393             # BackupEventLog()
394             # --------------
395             sub BackupEventLog {
396 0     0 0   my ($eventlog, $filename) = @_;
397              
398 0           require YAML;
399 0           return YAML::DumpFile($filename => $eventlog)
400             }
401              
402              
403             #
404             # ClearEventLog()
405             # -------------
406             sub ClearEventLog {
407 0     0 0   my ($eventlog, $filename) = @_;
408              
409 0           my $rc = BackupEventLog($eventlog, $filename);
410 0 0         if ($rc) { %main_eventlog = (); $last_read_record = 0 }
  0            
  0            
411              
412 0           return $rc
413             }
414              
415              
416             #
417             # CloseEventLog()
418             # -------------
419             sub CloseEventLog {
420 0     0 0   my ($eventlog) = @_;
421 0           $last_read_record = 0;
422 0           return TRUE
423             }
424              
425              
426             #
427             # DeregisterEventSource()
428             # ---------------------
429             sub DeregisterEventSource {
430 0     0 0   my ($eventlog) = @_;
431 0           return TRUE
432             }
433              
434              
435             #
436             # GetNumberOfEventLogRecords()
437             # --------------------------
438             sub GetNumberOfEventLogRecords ($\$) {
439 0     0 0   my ($eventlog, $nb_records_r) = @_;
440 0           print STDERR "GetNumberOfEventLogRecords(): @_\n";
441 0           $$nb_records_r = scalar @$eventlog;
442 0           return TRUE
443             }
444              
445              
446             #
447             # GetOldestEventLogRecord()
448             # -----------------------
449             sub GetOldestEventLogRecord {
450 0     0 0   my ($eventlog, $oldest_record_r) = @_;
451 0           print STDERR "GetOldestEventLogRecord(): @_\n";
452 0           $$oldest_record_r = $#{$eventlog};
  0            
453 0           return TRUE
454             }
455              
456              
457             #
458             # OpenBackupEventLog()
459             # ------------------
460             # http://msdn2.microsoft.com/en-us/library/aa363671.aspx
461             #
462             sub OpenBackupEventLog (\$$$) {
463 0     0 0   my ($eventlog_r, $computer, $filename) = @_;
464              
465 0           require YAML;
466 0           $$eventlog_r = YAML::LoadFile($filename);
467              
468 0           return TRUE
469             }
470              
471              
472             #
473             # OpenEventLog()
474             # ------------
475             # http://msdn2.microsoft.com/en-us/library/aa363672.aspx
476             #
477             sub OpenEventLog (\$$$) {
478 0     0 0   my ($eventlog_r, $computer, $source) = @_;
479 0           print STDERR "OpenEventLog(): @_\n";
480              
481 0   0       $main_eventlog{$computer}{$source} ||= [];
482 0           $$eventlog_r = $main_eventlog{$computer}{$source};
483              
484 0           return TRUE
485             }
486              
487              
488             #
489             # RegisterEventSource()
490             # -------------------
491             sub RegisterEventSource {
492 0     0 0   my ($computer, $source) = @_;
493 0           return $main_eventlog{$computer}{$source}
494             }
495              
496              
497             1
498              
499             __END__