| 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__ |