123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723 |
- #------------------------------------------------------------------------------
- # File: LNK.pm
- #
- # Description: Read meta information from MS Shell Link files
- #
- # Revisions: 2009/09/19 - P. Harvey Created
- #
- # References: 1) http://msdn.microsoft.com/en-us/library/dd871305(PROT.10).aspx
- # 2) http://www.i2s-lab.com/Papers/The_Windows_Shortcut_File_Format.pdf
- #------------------------------------------------------------------------------
- package Image::ExifTool::LNK;
- use strict;
- use vars qw($VERSION);
- use Image::ExifTool qw(:DataAccess :Utils);
- $VERSION = '1.07';
- sub ProcessItemID($$$);
- sub ProcessLinkInfo($$$);
- # Information extracted from LNK (Windows Shortcut) files
- %Image::ExifTool::LNK::Main = (
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- GROUPS => { 2 => 'Other' },
- VARS => { HEX_ID => 1 }, # print hex ID's in documentation
- NOTES => 'Information extracted from MS Shell Link (Windows shortcut) files.',
- # maybe the Flags aren't very useful to the user (since they are
- # mainly structural), but extract them anyway for completeness
- 0x14 => {
- Name => 'Flags',
- Format => 'int32u',
- PrintConv => { BITMASK => {
- 0 => 'IDList',
- 1 => 'LinkInfo',
- 2 => 'Description',
- 3 => 'RelativePath',
- 4 => 'WorkingDir',
- 5 => 'CommandArgs',
- 6 => 'IconFile',
- 7 => 'Unicode',
- 8 => 'NoLinkInfo',
- 9 => 'ExpString',
- 10 => 'SeparateProc',
- 12 => 'DarwinID',
- 13 => 'RunAsUser',
- 14 => 'ExpIcon',
- 15 => 'NoPidAlias',
- 17 => 'RunWithShim',
- 18 => 'NoLinkTrack',
- 19 => 'TargetMetadata',
- 20 => 'NoLinkPathTracking',
- 21 => 'NoKnownFolderTracking',
- 22 => 'NoKnownFolderAlias',
- 23 => 'LinkToLink',
- 24 => 'UnaliasOnSave',
- 25 => 'PreferEnvPath',
- 26 => 'KeepLocalIDList',
- }},
- },
- 0x18 => {
- Name => 'FileAttributes',
- Format => 'int32u',
- PrintConv => { BITMASK => {
- 0 => 'Read-only',
- 1 => 'Hidden',
- 2 => 'System',
- 3 => 'Volume', #(not used)
- 4 => 'Directory',
- 5 => 'Archive',
- 6 => 'Encrypted?', #(ref 2, not used in XP)
- 7 => 'Normal',
- 8 => 'Temporary',
- 9 => 'Sparse',
- 10 => 'Reparse point',
- 11 => 'Compressed',
- 12 => 'Offline',
- 13 => 'Not indexed',
- 14 => 'Encrypted',
- }},
- },
- 0x1c => {
- Name => 'CreateDate',
- Format => 'int64u',
- Groups => { 2 => 'Time' },
- # convert time from 100-ns intervals since Jan 1, 1601
- RawConv => '$val ? $val : undef',
- ValueConv => '$val=$val/1e7-11644473600; ConvertUnixTime($val,1)',
- PrintConv => '$self->ConvertDateTime($val)',
- },
- 0x24 => {
- Name => 'AccessDate',
- Format => 'int64u',
- Groups => { 2 => 'Time' },
- RawConv => '$val ? $val : undef',
- ValueConv => '$val=$val/1e7-11644473600; ConvertUnixTime($val,1)',
- PrintConv => '$self->ConvertDateTime($val)',
- },
- 0x2c => {
- Name => 'ModifyDate',
- Format => 'int64u',
- Groups => { 2 => 'Time' },
- RawConv => '$val ? $val : undef',
- ValueConv => '$val=$val/1e7-11644473600; ConvertUnixTime($val,1)',
- PrintConv => '$self->ConvertDateTime($val)',
- },
- 0x34 => {
- Name => 'TargetFileSize',
- Format => 'int32u',
- },
- 0x38 => {
- Name => 'IconIndex',
- Format => 'int32u',
- PrintConv => '$val ? $val : "(none)"',
- },
- 0x3c => {
- Name => 'RunWindow',
- Format => 'int32u',
- PrintConv => {
- 0 => 'Hide',
- 1 => 'Normal',
- 2 => 'Show Minimized',
- 3 => 'Show Maximized',
- 4 => 'Show No Activate',
- 5 => 'Show',
- 6 => 'Minimized',
- 7 => 'Show Minimized No Activate',
- 8 => 'Show NA',
- 9 => 'Restore',
- 10 => 'Show Default',
- },
- },
- 0x40 => {
- Name => 'HotKey',
- Format => 'int32u',
- PrintHex => 1,
- PrintConv => {
- OTHER => sub {
- my $val = shift;
- my $ch = $val & 0xff;
- if (chr $ch =~ /^[A-Z0-9]$/) {
- $ch = chr $ch;
- } elsif ($ch >= 0x70 and $ch <= 0x87) {
- $ch = 'F' . ($ch - 0x6f);
- } elsif ($ch == 0x90) {
- $ch = 'Num Lock';
- } elsif ($ch == 0x91) {
- $ch = 'Scroll Lock';
- } else {
- $ch = sprintf('Unknown (0x%x)', $ch);
- }
- $ch = "Alt-$ch" if $val & 0x400;
- $ch = "Control-$ch" if $val & 0x200;
- $ch = "Shift-$ch" if $val & 0x100;
- return $ch;
- },
- 0x00 => '(none)',
- # these entries really only for documentation
- 0x90 => 'Num Lock',
- 0x91 => 'Scroll Lock',
- "0x30'-'0x39" => "0-9",
- "0x41'-'0x5a" => "A-Z",
- "0x70'-'0x87" => "F1-F24",
- 0x100 => 'Shift',
- 0x200 => 'Control',
- 0x400 => 'Alt',
- },
- },
- # note: tags 0x10xx are synthesized tag ID's
- 0x10000 => {
- Name => 'ItemID',
- SubDirectory => { TagTable => 'Image::ExifTool::LNK::ItemID' },
- },
- 0x20000 => {
- Name => 'LinkInfo',
- SubDirectory => { TagTable => 'Image::ExifTool::LNK::LinkInfo' },
- },
- 0x30004 => 'Description',
- 0x30008 => 'RelativePath',
- 0x30010 => 'WorkingDirectory',
- 0x30020 => 'CommandLineArguments',
- 0x30040 => 'IconFileName',
- # note: tags 0xa000000x are actually ID's (not indices)
- 0xa0000000 => {
- Name => 'UnknownData',
- SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
- },
- 0xa0000001 => {
- Name => 'EnvVarData',
- SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
- },
- 0xa0000002 => {
- Name => 'ConsoleData',
- SubDirectory => { TagTable => 'Image::ExifTool::LNK::ConsoleData' },
- },
- 0xa0000003 => {
- Name => 'TrackerData',
- SubDirectory => { TagTable => 'Image::ExifTool::LNK::TrackerData' },
- },
- 0xa0000004 => {
- Name => 'ConsoleFEData',
- SubDirectory => { TagTable => 'Image::ExifTool::LNK::ConsoleFEData' },
- },
- 0xa0000005 => {
- Name => 'SpecialFolderData',
- SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
- },
- 0xa0000006 => {
- Name => 'DarwinData',
- SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
- },
- 0xa0000007 => {
- Name => 'IconEnvData',
- SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
- },
- 0xa0000008 => {
- Name => 'ShimData',
- SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
- },
- 0xa0000009 => {
- Name => 'PropertyStoreData',
- SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
- },
- 0xa000000b => {
- Name => 'KnownFolderData',
- SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
- },
- 0xa000000c => {
- Name => 'VistaIDListData',
- SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
- },
- );
- %Image::ExifTool::LNK::ItemID = (
- GROUPS => { 2 => 'Other' },
- PROCESS_PROC => \&ProcessItemID,
- # (can't find any documentation on these items)
- 0x0032 => {
- Name => 'Item0032',
- SubDirectory => { TagTable => 'Image::ExifTool::LNK::Item0032' },
- },
- );
- %Image::ExifTool::LNK::Item0032 = (
- GROUPS => { 2 => 'Other' },
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- 0x0e => {
- Name => 'TargetFileDOSName',
- Format => 'var_string',
- },
- #not at a fixed offset -- offset is given by last 2 bytes of the item + 0x14
- #0x22 => {
- # Name => 'TargetFileName',
- # Format => 'var_ustring',
- #},
- );
- %Image::ExifTool::LNK::LinkInfo = (
- GROUPS => { 2 => 'Other' },
- PROCESS_PROC => \&ProcessLinkInfo,
- FORMAT => 'int32u',
- VARS => { NO_ID => 1 },
- VolumeID => { },
- DriveType => {
- PrintConv => {
- 0 => 'Unknown',
- 1 => 'Invalid Root Path',
- 2 => 'Removable Media',
- 3 => 'Fixed Disk',
- 4 => 'Remote Drive',
- 5 => 'CD-ROM',
- 6 => 'Ram Disk',
- },
- },
- DriveSerialNumber => { },
- VolumeLabel => { },
- LocalBasePath => { },
- CommonNetworkRelLink => { },
- CommonPathSuffix => { },
- NetName => { },
- DeviceName => { },
- NetProviderType => {
- PrintHex => 1,
- PrintConv => {
- 0x1a0000 => 'AVID',
- 0x1b0000 => 'DOCUSPACE',
- 0x1c0000 => 'MANGOSOFT',
- 0x1d0000 => 'SERNET',
- 0x1e0000 => 'RIVERFRONT1',
- 0x1f0000 => 'RIVERFRONT2',
- 0x200000 => 'DECORB',
- 0x210000 => 'PROTSTOR',
- 0x220000 => 'FJ_REDIR',
- 0x230000 => 'DISTINCT',
- 0x240000 => 'TWINS',
- 0x250000 => 'RDR2SAMPLE',
- 0x260000 => 'CSC',
- 0x270000 => '3IN1',
- 0x290000 => 'EXTENDNET',
- 0x2a0000 => 'STAC',
- 0x2b0000 => 'FOXBAT',
- 0x2c0000 => 'YAHOO',
- 0x2d0000 => 'EXIFS',
- 0x2e0000 => 'DAV',
- 0x2f0000 => 'KNOWARE',
- 0x300000 => 'OBJECT_DIRE',
- 0x310000 => 'MASFAX',
- 0x320000 => 'HOB_NFS',
- 0x330000 => 'SHIVA',
- 0x340000 => 'IBMAL',
- 0x350000 => 'LOCK',
- 0x360000 => 'TERMSRV',
- 0x370000 => 'SRT',
- 0x380000 => 'QUINCY',
- 0x390000 => 'OPENAFS',
- 0x3a0000 => 'AVID1',
- 0x3b0000 => 'DFS',
- },
- },
- );
- %Image::ExifTool::LNK::UnknownData = (
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- GROUPS => { 2 => 'Other' },
- );
- %Image::ExifTool::LNK::ConsoleData = (
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- GROUPS => { 2 => 'Other' },
- 0x08 => {
- Name => 'FillAttributes',
- Format => 'int16u',
- PrintConv => 'sprintf("0x%.2x", $val)',
- },
- 0x0a => {
- Name => 'PopupFillAttributes',
- Format => 'int16u',
- PrintConv => 'sprintf("0x%.2x", $val)',
- },
- 0x0c => {
- Name => 'ScreenBufferSize',
- Format => 'int16u[2]',
- PrintConv => '$val=~s/ / x /; $val',
- },
- 0x10 => {
- Name => 'WindowSize',
- Format => 'int16u[2]',
- PrintConv => '$val=~s/ / x /; $val',
- },
- 0x14 => {
- Name => 'WindowOrigin',
- Format => 'int16u[2]',
- PrintConv => '$val=~s/ / x /; $val',
- },
- 0x20 => {
- Name => 'FontSize',
- Format => 'int16u[2]',
- PrintConv => '$val=~s/ / x /; $val',
- },
- 0x24 => {
- Name => 'FontFamily',
- Format => 'int32u',
- PrintHex => 1,
- PrintConv => {
- 0 => "Don't Care",
- 0x10 => 'Roman',
- 0x20 => 'Swiss',
- 0x30 => 'Modern',
- 0x40 => 'Script',
- 0x50 => 'Decorative',
- },
- },
- 0x28 => {
- Name => 'FontWeight',
- Format => 'int32u',
- },
- 0x2c => {
- Name => 'FontName',
- Format => 'undef[64]',
- RawConv => q{
- $val = $self->Decode($val, 'UCS2');
- $val =~ s/\0.*//s;
- return length($val) ? $val : undef;
- },
- },
- 0x6c => {
- Name => 'CursorSize',
- Format => 'int32u',
- },
- 0x70 => {
- Name => 'FullScreen',
- Format => 'int32u',
- PrintConv => '$val ? "Yes" : "No"',
- },
- 0x74 => { #PH (MISSING FROM MS DOCUMENTATION! -- screws up subsequent offsets)
- Name => 'QuickEdit',
- Format => 'int32u',
- PrintConv => '$val ? "Yes" : "No"',
- },
- 0x78 => {
- Name => 'InsertMode',
- Format => 'int32u',
- PrintConv => '$val ? "Yes" : "No"',
- },
- 0x7c => {
- Name => 'WindowOriginAuto',
- Format => 'int32u',
- PrintConv => '$val ? "Yes" : "No"',
- },
- 0x80 => {
- Name => 'HistoryBufferSize',
- Format => 'int32u',
- },
- 0x84 => {
- Name => 'NumHistoryBuffers',
- Format => 'int32u',
- },
- 0x88 => {
- Name => 'RemoveHistoryDuplicates',
- Format => 'int32u',
- PrintConv => '$val ? "Yes" : "No"',
- },
- );
- %Image::ExifTool::LNK::TrackerData = (
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- GROUPS => { 2 => 'Other' },
- 0x10 => {
- Name => 'MachineID',
- Format => 'var_string',
- },
- );
- %Image::ExifTool::LNK::ConsoleFEData = (
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- GROUPS => { 2 => 'Other' },
- 0x08 => {
- Name => 'CodePage',
- Format => 'int32u',
- },
- );
- #------------------------------------------------------------------------------
- # Extract null-terminated ASCII or Unicode string from buffer
- # Inputs: 0) buffer ref, 1) start position, 2) flag for unicode string
- # Return: string or undef if start position is outside bounds
- sub GetString($$;$)
- {
- my ($dataPt, $pos, $unicode) = @_;
- return undef if $pos >= length($$dataPt);
- pos($$dataPt) = $pos;
- return $1 if ($unicode ? $$dataPt=~/\G((?:..)*?)\0\0/sg : $$dataPt=~/\G(.*?)\0/sg);
- return substr($$dataPt, $pos);
- }
- #------------------------------------------------------------------------------
- # Process item ID data
- # Inputs: 0) ExifTool object reference, 1) dirInfo reference, 2) tag table ref
- # Returns: 1 on success
- sub ProcessItemID($$$)
- {
- my ($et, $dirInfo, $tagTablePtr) = @_;
- my $dataPt = $$dirInfo{DataPt};
- my $dataLen = length $$dataPt;
- my $pos = 0;
- my %opts = (
- DataPt => $dataPt,
- DataPos => $$dirInfo{DataPos},
- );
- $et->VerboseDir('ItemID', undef, $dataLen);
- for (;;) {
- last if $pos + 4 >= $dataLen;
- my $size = Get16u($dataPt, $pos);
- last if $size < 2 or $pos + $size > $dataLen;
- my $tag = Get16u($dataPt, $pos+2); # (just a guess -- may not be a tag at all)
- AddTagToTable($tagTablePtr, $tag, {
- Name => sprintf('Item%.4x', $tag),
- SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
- }) unless $$tagTablePtr{$tag};
- $et->HandleTag($tagTablePtr, $tag, undef, %opts, Start => $pos, Size => $size);
- $pos += $size;
- }
- }
- #------------------------------------------------------------------------------
- # Process link information data
- # Inputs: 0) ExifTool object reference, 1) dirInfo reference, 2) tag table ref
- # Returns: 1 on success
- sub ProcessLinkInfo($$$)
- {
- my ($et, $dirInfo, $tagTablePtr) = @_;
- my $dataPt = $$dirInfo{DataPt};
- my $dataLen = length $$dataPt;
- return 0 if $dataLen < 0x20;
- my $hdrLen = Get32u($dataPt, 4);
- my $lif = Get32u($dataPt, 8); # link info flags
- my %opts = (
- DataPt => $dataPt,
- DataPos => $$dirInfo{DataPos},
- Size => 4, # (typical value size)
- );
- my ($off, $unicode, $pos, $val, $size);
- $et->VerboseDir('LinkInfo', undef, $dataLen);
- if ($lif & 0x01) {
- # read Volume ID
- $off = Get32u($dataPt, 0x0c);
- if ($off + 0x20 <= $dataLen) {
- # my $len = Get32u($dataPt, $off);
- $et->HandleTag($tagTablePtr, 'DriveType', undef, %opts, Start=>$off+4);
- $pos = Get32u($dataPt, $off + 0x0c);
- if ($pos == 0x14) {
- # use VolumeLabelOffsetUnicode instead
- $pos = Get32u($dataPt, $off + 0x10);
- $unicode = 1;
- }
- $pos += $off;
- $val = GetString($dataPt, $pos, $unicode);
- if (defined $val) {
- $size = length $val;
- $val = $et->Decode($val, 'UCS2') if $unicode;
- $et->HandleTag($tagTablePtr, 'VolumeLabel', $val, %opts, Start=>$pos, Size=>$size);
- }
- }
- # read local base path
- if ($hdrLen >= 0x24) {
- $pos = Get32u($dataPt, 0x1c);
- $unicode = 1;
- } else {
- $pos = Get32u($dataPt, 0x10);
- undef $unicode;
- }
- $val = GetString($dataPt, $pos, $unicode);
- if (defined $val) {
- $size = length $val;
- $val = $et->Decode($val, 'UCS2') if $unicode;
- $et->HandleTag($tagTablePtr, 'LocalBasePath', $val, %opts, Start=>$pos, Size=>$size);
- }
- }
- if ($lif & 0x02) {
- # read common network relative link
- $off = Get32u($dataPt, 0x14);
- if ($off and $off + 0x14 <= $dataLen) {
- my $siz = Get32u($dataPt, $off);
- $pos = Get32u($dataPt, $off + 0x08);
- if ($pos > 0x14 and $siz >= 0x18) {
- $pos = Get32u($dataPt, $off + 0x14);
- $unicode = 1;
- } else {
- undef $unicode;
- }
- $val = GetString($dataPt, $pos, $unicode);
- if (defined $val) {
- $size = length $val;
- $val = $et->Decode($val, 'UCS2') if $unicode;
- $et->HandleTag($tagTablePtr, 'NetName', $val, %opts, Start=>$pos, Size=>$size);
- }
- my $flg = Get32u($dataPt, $off + 0x04);
- if ($flg & 0x01) {
- $pos = Get32u($dataPt, $off + 0x0c);
- if ($pos > 0x14 and $siz >= 0x1c) {
- $pos = Get32u($dataPt, $off + 0x18);
- $unicode = 1;
- } else {
- undef $unicode;
- }
- $val = GetString($dataPt, $pos, $unicode);
- if (defined $val) {
- $size = length $val;
- $val = $et->Decode($val, 'UCS2') if $unicode;
- $et->HandleTag($tagTablePtr, 'DeviceName', $val, %opts, Start=>$pos, Size=>$size);
- }
- }
- if ($flg & 0x02) {
- $val = Get32u($dataPt, $off + 0x10);
- $et->HandleTag($tagTablePtr, 'NetProviderType', $val, %opts, Start=>$off + 0x10);
- }
- }
- }
- return 1;
- }
- #------------------------------------------------------------------------------
- # Extract information from a MS Shell Link (Windows shortcut) file
- # Inputs: 0) ExifTool object reference, 1) dirInfo reference
- # Returns: 1 on success, 0 if this wasn't a valid LNK file
- sub ProcessLNK($$)
- {
- my ($et, $dirInfo) = @_;
- my $raf = $$dirInfo{RAF};
- my ($buff, $buf2, $len, $i);
- # read LNK file header
- $raf->Read($buff, 0x4c) == 0x4c or return 0;
- $buff =~ /^.{4}\x01\x14\x02\0{5}\xc0\0{6}\x46/s or return 0;
- $len = unpack('V', $buff);
- $len >= 0x4c or return 0;
- if ($len > 0x4c) {
- $raf->Read($buf2, $len - 0x4c) == $len - 0x4c or return 0;
- $buff .= $buf2;
- }
- $et->SetFileType();
- SetByteOrder('II');
- my $tagTablePtr = GetTagTable('Image::ExifTool::LNK::Main');
- my %dirInfo = (
- DataPt => \$buff,
- DataPos => 0,
- DataLen => length $buff,
- DirLen => length $buff,
- );
- $et->ProcessDirectory(\%dirInfo, $tagTablePtr);
- my $flags = Get32u(\$buff, 0x14);
- # read link target ID list
- if ($flags & 0x01) {
- $raf->Read($buff, 2) or return 1;
- $len = unpack('v', $buff);
- $raf->Read($buff, $len) == $len or return 1;
- $et->HandleTag($tagTablePtr, 0x10000, undef,
- DataPt => \$buff,
- DataPos => $raf->Tell() - $len,
- Size => $len,
- );
- }
- # read link information
- if ($flags & 0x02) {
- $raf->Read($buff, 4) or return 1;
- $len = unpack('V', $buff);
- return 1 if $len < 4;
- $raf->Read($buf2, $len - 4) == $len - 4 or return 1;
- $buff .= $buf2;
- $et->HandleTag($tagTablePtr, 0x20000, undef,
- DataPt => \$buff,
- DataPos => $raf->Tell() - $len,
- Size => $len,
- );
- }
- # read string data
- my @strings = qw(Description RelativePath WorkingDirectory
- CommandLineArguments IconFileName);
- for ($i=0; $i<@strings; ++$i) {
- my $mask = 0x04 << $i;
- next unless $flags & $mask;
- $raf->Read($buff, 2) or return 1;
- $len = unpack('v', $buff);
- $len *= 2 if $flags & 0x80; # characters are 2 bytes if Unicode flag is set
- $raf->Read($buff, $len) or return 1;
- my $val;
- $val = $et->Decode($buff, 'UCS2') if $flags & 0x80;
- $et->HandleTag($tagTablePtr, 0x30000 | $mask, $val,
- DataPt => \$buff,
- DataPos => $raf->Tell() - $len,
- Size => $len,
- );
- }
- # read extra data
- while ($raf->Read($buff, 4) == 4) {
- $len = unpack('V', $buff);
- last if $len < 4;
- $len -= 4;
- $raf->Read($buf2, $len) == $len or last;
- next unless $len > 4;
- $buff .= $buf2;
- my $tag = Get32u(\$buff, 4);
- my $tagInfo = $$tagTablePtr{$tag};
- unless (ref $tagInfo eq 'HASH' and $$tagInfo{SubDirectory}) {
- $tagInfo = $$tagTablePtr{0xa0000000};
- }
- $et->HandleTag($tagTablePtr, $tag, undef,
- DataPt => \$buff,
- DataPos => $raf->Tell() - $len - 4,
- TagInfo => $tagInfo,
- );
- }
- return 1;
- }
- 1; # end
- __END__
- =head1 NAME
- Image::ExifTool::LNK - Read MS Shell Link (.LNK) meta information
- =head1 SYNOPSIS
- This module is used by Image::ExifTool
- =head1 DESCRIPTION
- This module contains definitions required by Image::ExifTool to extract meta
- information MS Shell Link (Windows shortcut) files.
- =head1 AUTHOR
- Copyright 2003-2016, Phil Harvey (phil at owl.phy.queensu.ca)
- This library is free software; you can redistribute it and/or modify it
- under the same terms as Perl itself.
- =head1 REFERENCES
- =over 4
- =item L<http://msdn.microsoft.com/en-us/library/dd871305(PROT.10).aspx>
- =item L<http://www.i2s-lab.com/Papers/The_Windows_Shortcut_File_Format.pdf>
- =back
- =head1 SEE ALSO
- L<Image::ExifTool::TagNames/LNK Tags>,
- L<Image::ExifTool(3pm)|Image::ExifTool>
- =cut
|