1b39c5158Smillert#!perl 2b39c5158Smillertuse strict; 3b39c5158Smillertuse warnings; 4b39c5158Smillertuse File::Basename; 5b39c5158Smillertuse File::Copy; 6b39c5158Smillertuse File::Path; 7b39c5158Smillert 8b39c5158Smillertmy $name = shift || 'PerlLog'; 9b39c5158Smillert 10b39c5158Smillert# get the version from the message file 11b39c5158Smillertopen(my $msgfh, '<', "$name.mc") or die "fatal: Can't read file '$name.mc': $!\n"; 12b39c5158Smillertmy $top = <$msgfh>; 13b39c5158Smillertclose($msgfh); 14b39c5158Smillert 15b39c5158Smillertmy ($version) = $top =~ /Sys::Syslog Message File (\d+\.\d+\.\d+)/ 16b39c5158Smillert or die "error: File '$name.mc' doesn't have a version number\n"; 17b39c5158Smillert 18b39c5158Smillert# compile the message text files 19b39c5158Smillertsystem("mc -d $name.mc"); 20b39c5158Smillertsystem("rc $name.rc"); 21b39c5158Smillertsystem(qq{ link -nodefaultlib -incremental:no -release /nologo -base:0x60000000 } 22b39c5158Smillert .qq{ -comment:"Perl Syslog Message File v$version" } 23b39c5158Smillert .qq{ -machine:i386 -dll -noentry -out:$name.dll $name.res }); 24b39c5158Smillert 25b39c5158Smillert# uuencode the resource file 26b39c5158Smillertopen(my $rsrc, '<', "$name.RES") or die "fatal: Can't read resource file '$name.RES': $!"; 27b39c5158Smillertbinmode($rsrc); 28b39c5158Smillertmy $uudata = pack "u", do { local $/; <$rsrc> }; 29b39c5158Smillertclose($rsrc); 30b39c5158Smillert 31b39c5158Smillertopen(my $uufh, '>', "$name\_RES.uu") or die "fatal: Can't write file '$name\_RES.uu': $!"; 32b39c5158Smillertprint $uufh $uudata; 33b39c5158Smillertclose($uufh); 34b39c5158Smillert 35b39c5158Smillert# uuencode the DLL 36b39c5158Smillertopen(my $dll, '<', "$name.dll") or die "fatal: Can't read DLL '$name.dll': $!"; 37b39c5158Smillertbinmode($dll); 38b39c5158Smillert$uudata = pack "u", do { local $/; <$dll> }; 39b39c5158Smillertclose($dll); 40b39c5158Smillert 41b39c5158Smillertopen($uufh, '>', "$name\_dll.uu") or die "fatal: Can't write file '$name\_dll.uu': $!"; 42b39c5158Smillertprint $uufh $uudata; 43b39c5158Smillertclose($uufh); 44b39c5158Smillert 45b39c5158Smillert# parse the generated header to extract the constants 46b39c5158Smillertopen(my $header, '<', "$name.h") or die "fatal: Can't read header file '$name.h': $!"; 47b39c5158Smillertmy %vals; 48b39c5158Smillertmy $max = 0; 49b39c5158Smillert 50b39c5158Smillertwhile (<$header>) { 51b39c5158Smillert if (/^#define\s+(\w+)\s+(\d+)$/ || /^#define\s+(\w+)\s+\(\(DWORD\)(\d+)L\)/) { 52b39c5158Smillert $vals{$1} = $2; 53b39c5158Smillert if (substr($1, 0, 1) eq 'C') { 54b39c5158Smillert $max = $2 if $max < $2; 55b39c5158Smillert } 56b39c5158Smillert } 57b39c5158Smillert} 58b39c5158Smillert 59b39c5158Smillertclose($header); 60b39c5158Smillert 61b39c5158Smillertmy ($hash, $f2c, %fac); 62b39c5158Smillert 63b39c5158Smillertfor my $name (sort { substr($a,0,1) cmp substr($b,0,1) || $vals{$a} <=> $vals{$b} } keys %vals) { 64b39c5158Smillert $hash .= " $name => $vals{$name},\n" ; 65b39c5158Smillert if ($name =~ /^CAT_(\w+)$/) { 66b39c5158Smillert $fac{$1} = $vals{$name}; 67b39c5158Smillert } 68b39c5158Smillert} 69b39c5158Smillert 70b39c5158Smillertfor my $name (sort {$fac{$a} <=> $fac{$b}} keys %fac) { 71b39c5158Smillert $f2c .= " Sys::Syslog::LOG_$name() => '$name',\n"; 72b39c5158Smillert} 73b39c5158Smillert 74b39c5158Smillert# write the Sys::Syslog::Win32 module 75b39c5158Smillertopen my $out, '>', "Win32.pm" or die "fatal: Can't write Win32.pm: $!"; 76b39c5158Smillertmy $template = join '', <DATA>; 77b39c5158Smillert$template =~ s/__CONSTANT__/$hash/; 78b39c5158Smillert$template =~ s/__F2C__/$f2c/; 79b39c5158Smillert$template =~ s/__NAME_VER__/$name/; 80b39c5158Smillert$template =~ s/__VER__/$version/; 81b39c5158Smillert$max = sprintf "0x%08x", $max; 82b39c5158Smillert$template =~ s/__MAX__/'$max'/g; 83b39c5158Smillert$template =~ s/__TIME__/localtime()/ge; 84b39c5158Smillertprint $out $template; 85b39c5158Smillertclose $out; 8691f110e0Safresh1print "Updated Win32.pm and relevant message files\n"; 87b39c5158Smillert 88b39c5158Smillert__END__ 89b39c5158Smillertpackage Sys::Syslog::Win32; 90b39c5158Smillertuse strict; 91b39c5158Smillertuse warnings; 92b39c5158Smillertuse Carp; 93b39c5158Smillertuse File::Spec; 94b39c5158Smillert 95b39c5158Smillert# === WARNING === WARNING === WARNING === WARNING === WARNING === WARNING === 96b39c5158Smillert# 97b39c5158Smillert# This file was generated by Sys-Syslog/win32/compile.pl on __TIME__ 98b39c5158Smillert# Any changes being made here will be lost the next time Sys::Syslog 99b39c5158Smillert# is installed. 100b39c5158Smillert# 101b39c5158Smillert# Do NOT USE THIS MODULE DIRECTLY: this is a utility module for Sys::Syslog. 102b39c5158Smillert# It may change at any time to fit the needs of Sys::Syslog therefore no 103b39c5158Smillert# warranty is made WRT to its API. You Have Been Warned. 104b39c5158Smillert# 105b39c5158Smillert# === WARNING === WARNING === WARNING === WARNING === WARNING === WARNING === 106b39c5158Smillert 107b39c5158Smillertour $Source; 108b39c5158Smillertmy $logger; 109b39c5158Smillertmy $Registry; 110b39c5158Smillert 111b39c5158Smillertuse Win32::EventLog; 112b39c5158Smillertuse Win32::TieRegistry 0.20 ( 113b39c5158Smillert TiedRef => \$Registry, 114b39c5158Smillert Delimiter => "/", 115b39c5158Smillert ArrayValues => 1, 116b39c5158Smillert SplitMultis => 1, 117b39c5158Smillert AllowLoad => 1, 118b39c5158Smillert qw( 119b39c5158Smillert REG_SZ 120b39c5158Smillert REG_EXPAND_SZ 121b39c5158Smillert REG_DWORD 122b39c5158Smillert REG_BINARY 123b39c5158Smillert REG_MULTI_SZ 124b39c5158Smillert KEY_READ 125b39c5158Smillert KEY_WRITE 126b39c5158Smillert KEY_ALL_ACCESS 127b39c5158Smillert ), 128b39c5158Smillert); 129b39c5158Smillert 130b39c5158Smillertmy $is_Cygwin = $^O =~ /Cygwin/i; 131b39c5158Smillertmy $is_Win32 = $^O =~ /Win32/i; 132b39c5158Smillert 133b39c5158Smillertmy %const = ( 134b39c5158Smillert__CONSTANT__ 135b39c5158Smillert); 136b39c5158Smillert 137b39c5158Smillertmy %id2name = ( 138b39c5158Smillert__F2C__ 139b39c5158Smillert); 140b39c5158Smillert 141b39c5158Smillertmy @priority2eventtype = ( 142b39c5158Smillert EVENTLOG_ERROR_TYPE(), # LOG_EMERG 143b39c5158Smillert EVENTLOG_ERROR_TYPE(), # LOG_ALERT 144b39c5158Smillert EVENTLOG_ERROR_TYPE(), # LOG_CRIT 145b39c5158Smillert EVENTLOG_ERROR_TYPE(), # LOG_ERR 146b39c5158Smillert EVENTLOG_WARNING_TYPE(), # LOG_WARNING 147b39c5158Smillert EVENTLOG_WARNING_TYPE(), # LOG_NOTICE 148b39c5158Smillert EVENTLOG_INFORMATION_TYPE(), # LOG_INFO 149b39c5158Smillert EVENTLOG_INFORMATION_TYPE(), # LOG_DEBUG 150b39c5158Smillert); 151b39c5158Smillert 152b39c5158Smillert 153b39c5158Smillert# 154b39c5158Smillert# _install() 155b39c5158Smillert# -------- 156b39c5158Smillert# Used to set up a connection to the eventlog. 157b39c5158Smillert# 158b39c5158Smillertsub _install { 159b39c5158Smillert return $logger if $logger; 160b39c5158Smillert 161b39c5158Smillert # can't just use basename($0) here because Win32 path often are a 162b39c5158Smillert # a mix of / and \, and File::Basename::fileparse() can't handle that, 163b39c5158Smillert # while File::Spec::splitpath() can.. Go figure.. 164b39c5158Smillert my (undef, undef, $basename) = File::Spec->splitpath($0); 165b39c5158Smillert ($Source) ||= $basename; 166b39c5158Smillert 167b39c5158Smillert $Source.=" [SSW:__VER__]"; 168b39c5158Smillert 169b39c5158Smillert #$Registry->Delimiter("/"); # is this needed? 170b39c5158Smillert my $root = 'LMachine/SYSTEM/CurrentControlSet/Services/Eventlog/Application/'; 171b39c5158Smillert my $dll = 'Sys/Syslog/__NAME_VER__.dll'; 172b39c5158Smillert 173b39c5158Smillert if (!$Registry->{$root.$Source} || 174b39c5158Smillert !$Registry->{$root.$Source.'/CategoryMessageFile'}[0] || 175b39c5158Smillert !-e $Registry->{$root.$Source.'/CategoryMessageFile'}[0] ) 176b39c5158Smillert { 177b39c5158Smillert 178b39c5158Smillert # find the resource DLL, which should be along Syslog.dll 179b39c5158Smillert my ($file) = grep { -e $_ } map { ("$_/$dll" => "$_/auto/$dll") } @INC; 180b39c5158Smillert $dll = $file if $file; 181b39c5158Smillert 182b39c5158Smillert # on Cygwin, convert the Unix path into absolute Windows path 183b39c5158Smillert if ($is_Cygwin) { 184b39c5158Smillert if ($] > 5.009005) { 185b39c5158Smillert chomp($file = Cygwin::posix_to_win_path($file, 1)); 186b39c5158Smillert } 187b39c5158Smillert else { 188b39c5158Smillert local $ENV{PATH} = ''; 189b39c5158Smillert chomp($dll = `/usr/bin/cygpath --absolute --windows "$dll"`); 190b39c5158Smillert } 191b39c5158Smillert } 192b39c5158Smillert 193b39c5158Smillert $dll =~ s![\\/]+!\\!g; # must be backslashes! 194b39c5158Smillert die "fatal: Can't find resource DLL for Sys::Syslog\n" if !$dll; 195b39c5158Smillert 196b39c5158Smillert $Registry->{$root.$Source} = { 197b39c5158Smillert '/EventMessageFile' => [ $dll, REG_EXPAND_SZ ], 198b39c5158Smillert '/CategoryMessageFile' => [ $dll, REG_EXPAND_SZ ], 199b39c5158Smillert '/CategoryCount' => [ __MAX__, REG_DWORD ], 200b39c5158Smillert #'/TypesSupported' => [ __MAX__, REG_DWORD ], 201b39c5158Smillert }; 202b39c5158Smillert 203b39c5158Smillert warn "Configured eventlog to use $dll for $Source\n" if $Sys::Syslog::DEBUG; 204b39c5158Smillert } 205b39c5158Smillert 206b39c5158Smillert #Carp::confess("Registry has the wrong value for '$Source', possibly mismatched dll!\nMine:$dll\nGot :$Registry->{$root.$Source.'/CategoryMessageFile'}[0]\n") 207b39c5158Smillert # if $Registry->{$root.$Source.'/CategoryMessageFile'}[0] ne $dll; 208b39c5158Smillert 209b39c5158Smillert # we really should do something useful with this but for now 210b39c5158Smillert # we set it to "" to prevent Win32::EventLog from warning 211b39c5158Smillert my $host = ""; 212b39c5158Smillert 213b39c5158Smillert $logger = Win32::EventLog->new($Source, $host) 214b39c5158Smillert or Carp::confess("Failed to connect to the '$Source' event log"); 215b39c5158Smillert 216b39c5158Smillert return $logger; 217b39c5158Smillert} 218b39c5158Smillert 219b39c5158Smillert 220b39c5158Smillert# 221b39c5158Smillert# _syslog_send() 222b39c5158Smillert# ------------ 223b39c5158Smillert# Used to convert syslog messages into eventlog messages 224b39c5158Smillert# 225b39c5158Smillertsub _syslog_send { 226b39c5158Smillert my ($buf, $numpri, $numfac) = @_; 227b39c5158Smillert $numpri ||= EVENTLOG_INFORMATION_TYPE(); 228b39c5158Smillert $numfac ||= Sys::Syslog::LOG_USER(); 229b39c5158Smillert my $name = $id2name{$numfac}; 230b39c5158Smillert 231b39c5158Smillert my $opts = { 232b39c5158Smillert EventType => $priority2eventtype[$numpri], 233b39c5158Smillert EventID => $const{"MSG_$name"}, 234b39c5158Smillert Category => $const{"CAT_$name"}, 235b39c5158Smillert Strings => "$buf\0", 236b39c5158Smillert Data => "", 237b39c5158Smillert }; 238b39c5158Smillert 239b39c5158Smillert if ($Sys::Syslog::DEBUG) { 240b39c5158Smillert require Data::Dumper; 241b39c5158Smillert warn Data::Dumper->Dump( 242b39c5158Smillert [$numpri, $numfac, $name, $opts], 243b39c5158Smillert [qw(numpri numfac name opts)] 244b39c5158Smillert ); 245b39c5158Smillert } 246b39c5158Smillert 247b39c5158Smillert return $logger->Report($opts); 248b39c5158Smillert} 249b39c5158Smillert 250b39c5158Smillert 251b39c5158Smillert=head1 NAME 252b39c5158Smillert 253b39c5158SmillertSys::Syslog::Win32 - Win32 support for Sys::Syslog 254b39c5158Smillert 255b39c5158Smillert=head1 DESCRIPTION 256b39c5158Smillert 257b39c5158SmillertThis module is a back-end plugin for C<Sys::Syslog>, for supporting the Win32 258b39c5158Smillertevent log. It is not expected to be directly used by any module other than 259b39c5158SmillertC<Sys::Syslog> therefore it's API may change at any time and no warranty is 260b39c5158Smillertmade with regards to backward compatibility. You Have Been Warned. 261b39c5158Smillert 262*6fb12b70Safresh1In order to execute this script and compile the Win32 support files, you 263*6fb12b70Safresh1need some helper programs: mc.exe, rc.exe and link.exe 264*6fb12b70Safresh1 265*6fb12b70Safresh1mc.exe and rc.exe can be downloaded from 266*6fb12b70Safresh1http://www.microsoft.com/en-us/download/details.aspx?id=11310 267*6fb12b70Safresh1 268*6fb12b70Safresh1link.exe is usually shipped with Visual Studio. 269*6fb12b70Safresh1 270b39c5158Smillert=head1 SEE ALSO 271b39c5158Smillert 272b39c5158SmillertL<Sys::Syslog> 273b39c5158Smillert 274b39c5158Smillert=head1 AUTHORS 275b39c5158Smillert 276b39c5158SmillertSE<eacute>bastien Aperghis-Tramoni and Yves Orton 277b39c5158Smillert 278b39c5158Smillert=head1 LICENSE 279b39c5158Smillert 280b39c5158SmillertThis program is free software; you can redistribute it and/or modify it 281b39c5158Smillertunder the same terms as Perl itself. 282b39c5158Smillert 283b39c5158Smillert=cut 284b39c5158Smillert 285b39c5158Smillert1; 286