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 )