Image-ExifTool
view release on metacpan or search on metacpan
lib/Image/ExifTool/EXE.pm view on Meta::CPAN
# 4 int32u cputype
# 8 int32u cpusubtype
# 12 int32u filetype
# 16 int32u ncmds
# 20 int32u sizeofcmds
# 24 int32u flags
my $tagTablePtr = GetTagTable('Image::ExifTool::EXE::MachO');
SetByteOrder($$info[1]);
my $cpuType = Get32s($dataPt, 4);
my $subType = Get32s($dataPt, 8);
$et->HandleTag($tagTablePtr, 0, $$info[0]);
$et->HandleTag($tagTablePtr, 1, $$info[1]);
$et->HandleTag($tagTablePtr, 3, $cpuType);
$et->HandleTag($tagTablePtr, 4, "$cpuType $subType");
if ($doObj) {
my $objType = Get32u($dataPt, 12);
my $flags = Get32u($dataPt, 24);
$et->HandleTag($tagTablePtr, 5, $objType);
$et->HandleTag($tagTablePtr, 6, $flags);
# override file type if this is an object file or library
MachOverride($et, $objType);
} else { # otherwise this was a static library
$et->OverrideFileType('Mach-O static library', undef, 'A');
}
return 1;
}
return 0;
}
#------------------------------------------------------------------------------
# Extract information from an EXE file
# Inputs: 0) ExifTool object reference, 1) dirInfo reference
# Returns: 1 on success, 0 if this wasn't a valid EXE file
sub ProcessEXE($$)
{
my ($et, $dirInfo) = @_;
my $raf = $$dirInfo{RAF};
my ($buff, $buf2, $type, $mime, $ext, $tagTablePtr, %dirInfo);
my $size = $raf->Read($buff, 0x40) or return 0;
my $fast3 = $$et{OPTIONS}{FastScan} && $$et{OPTIONS}{FastScan} == 3;
#
# DOS and Windows EXE
#
if ($buff =~ /^MZ/ and $size == 0x40) {
# DOS/Windows executable
# validate DOS header
# (ref http://www.delphidabbler.com/articles?article=8&part=2)
# 0 int16u magic - Magic number ("MZ")
# 2 int16u cblp - Bytes on last page of file
# 4 int16u cp - Pages in file
# 6 int16u crlc - Relocations
# 8 int16u cparhdr - Size of header in paragraphs
# 10 int16u minalloc - Minimum extra paragraphs needed
# 12 int16u maxalloc - Maximum extra paragraphs needed
# 14 int16u ss - Initial (relative) SS value
# 16 int16u sp - Initial SP value
# 18 int16u csum - Checksum
# 20 int16u ip - Initial IP value
# 22 int16u cs - Initial (relative) CS value
# 24 int16u lfarlc - Address of relocation table
# 26 int16u ovno - Overlay number
# 28 int16u[4] res - Reserved words
# 36 int16u oemid - OEM identifier (for oeminfo)
# 38 int16u oeminfo - OEM info; oemid specific
# 40 int16u[10] res2 - Reserved words
# 60 int32u; lfanew - File address of new exe header
SetByteOrder('II');
my ($cblp, $cp, $lfarlc, $lfanew) = unpack('x2v2x18vx34V', $buff);
my $fileSize = ($cp - ($cblp ? 1 : 0)) * 512 + $cblp;
#(patch to accommodate observed 64-bit files)
#return 0 if $fileSize < 0x40 or $fileSize < $lfarlc;
#return 0 if $fileSize < 0x40; (changed to warning in ExifTool 12.08)
$et->Warn('Invalid file size in DOS header') if $fileSize < 0x40;
# read the Windows NE, PE or LE (virtual device driver) header
#if ($lfarlc == 0x40 and $fileSize > $lfanew + 2 and ...
if ($raf->Seek($lfanew, 0) and $raf->Read($buff, 0x40) and $buff =~ /^(NE|PE|LE)/) {
if ($1 eq 'NE') {
if ($size >= 0x40) { # NE header is 64 bytes (ref 2)
# check for DLL
my $appFlags = Get16u(\$buff, 0x0c);
$ext = $appFlags & 0x80 ? 'DLL' : 'EXE';
$type = "Win16 $ext";
# offset 0x02 is 2 bytes with linker version and revision numbers
# offset 0x36 is executable type (2 = Windows)
}
} elsif ($1 eq 'PE') {
# PE header comes at byte 4 in buff:
# 4 int16u Machine
# 6 int16u NumberOfSections
# 8 int32u TimeDateStamp
# 12 int32u PointerToSymbolTable
# 16 int32u NumberOfSymbols
# 20 int16u SizeOfOptionalHeader
# 22 int16u Characteristics
if ($size >= 24) { # PE header is 24 bytes (plus optional header)
my $mach = Get16u(\$buff, 4); # MachineType
my $flags = Get16u(\$buff, 22); # ImageFileCharacteristics
my $machine = $Image::ExifTool::EXE::Main{0}{PrintConv}{$mach} || '';
my $winType = $machine =~ /64/ ? 'Win64' : 'Win32';
$ext = $flags & 0x2000 ? 'DLL' : 'EXE';
$et->SetFileType("$winType $ext", undef, $ext);
return 1 if $fast3;
# read the rest of the optional header if necessary
my $optSize = Get16u(\$buff, 20);
my $more = $optSize + 24 - $size;
my $magic = 0;
if ($more > 0) {
if ($raf->Read($buf2, $more) == $more) {
$buff .= $buf2;
$size += $more;
$magic = Get16u(\$buff, 24);
# verify PE magic number
unless ($magic == 0x107 or $magic == 0x10b or $magic == 0x20b) {
$et->Warn('Unknown PE magic number');
return 1;
}
# --> 64-bit if $magic is 0x20b ????
} else {
$et->Warn('Error reading optional header');
}
( run in 0.889 second using v1.01-cache-2.11-cpan-71847e10f99 )