#!perl -w
# A modified version of Max Maischein's (aka Corion) script found at
# http://www.perlmonks.org/index.pl?node_id=15871 on Perl Monks.
# This one works for 16-bit and 32-bit fileversions, both .exe and .dl
+l.
die "Specify a .exe/.dll-file to get information on.\n" unless @ARGV =
+= 1;
my $filename = shift;
get_version($filename);
sub MakeUnicode {
my ($S) = @_;
$S =~ s/(.)/$1\x00/g;
return $S;
};
sub MakeASCII {
my ($S) = @_;
$S =~ s/(.)\x00/$1/g;
return $S;
};
sub dumpfile {
my $filename = shift;
my $exedata;
my %Result;
# Regex definitions
# For files that are 32-bit
my $StringFileInfoU =
"..\x00\x00[\x00\x01]\x00" . MakeUnicode("StringFileInfo") . "
+(?:\x00\x00)+" . # StringFileInfo header
"((..)\x00\x00[\x00\x01]\x00(?:[0-9A-Fa-f]\x00){8}(?:\x00\x00
+)+)" . # StringTable header
"(.*)"; # Strings
# For files that are 16-bit
my $StringFileInfoA =
"..\x00\x00" . "StringFileInfo" . "(?:\x00)+" . # StringFileIn
+fo header
"((..)\x00\x00(?:[0-9A-Fa-f]){8}(?:\x00)+)" . # StringTable h
+eader
"(.*)"; # Strings
open EXE, "<$filename" or die "Cannot open $filename\n";
binmode EXE;
local $/;
undef $/;
$exedata = <EXE>; # sluuuuurp
close EXE;
# 32bit Windows Unicode format
if ($exedata =~ /$StringFileInfoU/gms) {
my ($STHeader, $Len, $Info) = ($1,$2,$3);
undef $exedata;
#print "[32bit] ";
$Result{"FileType"} = "32-bit UNICODE";
$Len = unpack( "v", $Len );
$Len -= length( $STHeader );
$Info = substr( $Info, 0, $Len );
while ($Info) {
my $Sublen;
my ($Next, $Value, $Type) = unpack("vvv", substr( $Info,
+ 0, 6 ));
$Sublen = $Next - 6;
while ($Next % 4) { $Next++ };
last unless $Next;
my $Item = substr($Info, 6, $Sublen);
my (@Info) = ();
# Extract the key :
$Item =~ s/^((?:..)+?)(\x00\x00)+//sm;
my ($Key) = MakeASCII( $1 );
while ($Item =~ s/^((?:..)+?)(\x00\x00)+//sm) {
push @Info, MakeASCII( $1 );
}
$Result{$Key} = $Info[0];
shift @Info;
if ($Next < length( $Info )) { # != ?
$Info = substr( $Info, $Next );
} else {
$Info = "";
}
}
# 16bit Windows ASCII format
} elsif ($exedata =~ /$StringFileInfoA/gms) {
my ($STHeader, $Len, $Info) = ($1,$2,$3);
undef $exedata;
#print "[16bit] ";
$Len = unpack( "v", $Len );
$Len -= length( $STHeader );
$Info = substr( $Info, 0, $Len );
while ($Info) {
my $Sublen;
my ($Next, $Value) = unpack("vv", substr( $Info, 0, 4 ))
+;
$Sublen = $Next - 4;
while ($Next % 4) { $Next++ };
last unless $Next;
my $Item = substr($Info, 4, $Sublen);
my (@Info) = ();
# Extract the key :
$Item =~ s/^((?:.)+?)(\x00)+//sm;
my ($Key) = ( $1 );
while ($Item =~ s/^((?:.)+?)(\x00)+//sm) {
push @Info, $1;
}
$Result{$Key} = $Info[0];
shift @Info;
if ($Next < length( $Info )) { # != ?
$Info = substr( $Info, $Next );
} else {
$Info = "";
}
}
} else {
print "[StringFileInfo not found in $filename]\n";
}
return \%Result;
}
sub get_version {
my $data = dumpfile($_[0]);
while(my($key,$value) = each(%{$data})){
print "$key=$value\n";
}
}
Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
Read Where should I post X? if you're not absolutely sure you're posting in the right place.
Please read these before you post! —
Posts may use any of the Perl Monks Approved HTML tags:
- a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
| |
For: |
|
Use: |
| & | | & |
| < | | < |
| > | | > |
| [ | | [ |
| ] | | ] |
Link using PerlMonks shortcuts! What shortcuts can I use for linking?
See Writeup Formatting Tips and other pages linked from there for more info.