source: gs2-extensions/parallel-building/trunk/src/perllib/cpan/Image/ExifTool/LNK.pm@ 24626

Last change on this file since 24626 was 24626, checked in by jmt12, 13 years ago

An (almost) complete copy of the perllib directory from a (circa SEP2011) head checkout from Greenstone 2 trunk - in order to try and make merging in this extension a little easier later on (as there have been some major changes to buildcol.pl commited in the main trunk but not in the x64 branch)

  • Property svn:executable set to *
File size: 22.1 KB
Line 
1#------------------------------------------------------------------------------
2# File: LNK.pm
3#
4# Description: Read meta information from MS Shell Link files
5#
6# Revisions: 2009/09/19 - P. Harvey Created
7#
8# References: 1) http://msdn.microsoft.com/en-us/library/dd871305(PROT.10).aspx
9# 2) http://www.i2s-lab.com/Papers/The_Windows_Shortcut_File_Format.pdf
10#------------------------------------------------------------------------------
11
12package Image::ExifTool::LNK;
13
14use strict;
15use vars qw($VERSION);
16use Image::ExifTool qw(:DataAccess :Utils);
17
18$VERSION = '1.03';
19
20sub ProcessItemID($$$);
21sub ProcessLinkInfo($$$);
22
23# Information extracted from LNK (Windows Shortcut) files
24%Image::ExifTool::LNK::Main = (
25 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
26 GROUPS => { 2 => 'Other' },
27 NOTES => 'Information extracted from MS Shell Link (Windows shortcut) files.',
28 # maybe the Flags aren't very useful to the user (since they are
29 # mainly structural), but extract them anyway for completeness
30 0x14 => {
31 Name => 'Flags',
32 Format => 'int32u',
33 PrintConv => { BITMASK => {
34 0 => 'IDList',
35 1 => 'LinkInfo',
36 2 => 'Description',
37 3 => 'RelativePath',
38 4 => 'WorkingDir',
39 5 => 'CommandArgs',
40 6 => 'IconFile',
41 7 => 'Unicode',
42 8 => 'NoLinkInfo',
43 9 => 'ExpString',
44 10 => 'SeparateProc',
45 12 => 'DarwinID',
46 13 => 'RunAsUser',
47 14 => 'ExpIcon',
48 15 => 'NoPidAlias',
49 17 => 'RunWithShim',
50 18 => 'NoLinkTrack',
51 19 => 'TargetMetadata',
52 20 => 'NoLinkPathTracking',
53 21 => 'NoKnownFolderTracking',
54 22 => 'NoKnownFolderAlias',
55 23 => 'LinkToLink',
56 24 => 'UnaliasOnSave',
57 25 => 'PreferEnvPath',
58 26 => 'KeepLocalIDList',
59 }},
60 },
61 0x18 => {
62 Name => 'FileAttributes',
63 Format => 'int32u',
64 PrintConv => { BITMASK => {
65 0 => 'Read-only',
66 1 => 'Hidden',
67 2 => 'System',
68 3 => 'Volume', #(not used)
69 4 => 'Directory',
70 5 => 'Archive',
71 6 => 'Encrypted?', #(ref 2, not used in XP)
72 7 => 'Normal',
73 8 => 'Temporary',
74 9 => 'Sparse',
75 10 => 'Reparse point',
76 11 => 'Compressed',
77 12 => 'Offline',
78 13 => 'Not indexed',
79 14 => 'Encrypted',
80 }},
81 },
82 0x1c => {
83 Name => 'CreateDate',
84 Format => 'int64u',
85 Groups => { 2 => 'Time' },
86 # convert time from 100-ns intervals since Jan 1, 1601
87 RawConv => '$val ? $val : undef',
88 ValueConv => '$val=$val/1e7-11644473600; ConvertUnixTime($val,1)',
89 PrintConv => '$self->ConvertDateTime($val)',
90 },
91 0x24 => {
92 Name => 'AccessDate',
93 Format => 'int64u',
94 Groups => { 2 => 'Time' },
95 RawConv => '$val ? $val : undef',
96 ValueConv => '$val=$val/1e7-11644473600; ConvertUnixTime($val,1)',
97 PrintConv => '$self->ConvertDateTime($val)',
98 },
99 0x2c => {
100 Name => 'ModifyDate',
101 Format => 'int64u',
102 Groups => { 2 => 'Time' },
103 RawConv => '$val ? $val : undef',
104 ValueConv => '$val=$val/1e7-11644473600; ConvertUnixTime($val,1)',
105 PrintConv => '$self->ConvertDateTime($val)',
106 },
107 0x34 => {
108 Name => 'TargetFileSize',
109 Format => 'int32u',
110 },
111 0x38 => {
112 Name => 'IconIndex',
113 Format => 'int32u',
114 PrintConv => '$val ? $val : "(none)"',
115 },
116 0x3c => {
117 Name => 'RunWindow',
118 Format => 'int32u',
119 PrintConv => {
120 0 => 'Hide',
121 1 => 'Normal',
122 2 => 'Show Minimized',
123 3 => 'Show Maximized',
124 4 => 'Show No Activate',
125 5 => 'Show',
126 6 => 'Minimized',
127 7 => 'Show Minimized No Activate',
128 8 => 'Show NA',
129 9 => 'Restore',
130 10 => 'Show Default',
131 },
132 },
133 0x40 => {
134 Name => 'HotKey',
135 Format => 'int32u',
136 PrintHex => 1,
137 PrintConv => {
138 OTHER => sub {
139 my $val = shift;
140 my $ch = $val & 0xff;
141 if (chr $ch =~ /^[A-Z0-9]$/) {
142 $ch = chr $ch;
143 } elsif ($ch >= 0x70 and $ch <= 0x87) {
144 $ch = 'F' . ($ch - 0x6f);
145 } elsif ($ch == 0x90) {
146 $ch = 'Num Lock';
147 } elsif ($ch == 0x91) {
148 $ch = 'Scroll Lock';
149 } else {
150 $ch = sprintf('Unknown (0x%x)', $ch);
151 }
152 $ch = "Alt-$ch" if $val & 0x400;
153 $ch = "Control-$ch" if $val & 0x200;
154 $ch = "Shift-$ch" if $val & 0x100;
155 return $ch;
156 },
157 0x00 => '(none)',
158 # these entries really only for documentation
159 0x90 => 'Num Lock',
160 0x91 => 'Scroll Lock',
161 "0x30'-'0x39" => "0-9",
162 "0x41'-'0x5a" => "A-Z",
163 "0x70'-'0x87" => "F1-F24",
164 0x100 => 'Shift',
165 0x200 => 'Control',
166 0x400 => 'Alt',
167 },
168 },
169 # note: tags 0x10xx are synthesized tag ID's
170 0x10000 => {
171 Name => 'ItemID',
172 SubDirectory => { TagTable => 'Image::ExifTool::LNK::ItemID' },
173 },
174 0x20000 => {
175 Name => 'LinkInfo',
176 SubDirectory => { TagTable => 'Image::ExifTool::LNK::LinkInfo' },
177 },
178 0x30004 => 'Description',
179 0x30008 => 'RelativePath',
180 0x30010 => 'WorkingDirectory',
181 0x30020 => 'CommandLineArguments',
182 0x30040 => 'IconFileName',
183 # note: tags 0xa000000x are actually ID's (not indices)
184 0xa0000000 => {
185 Name => 'UnknownData',
186 SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
187 },
188 0xa0000001 => {
189 Name => 'EnvVarData',
190 SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
191 },
192 0xa0000002 => {
193 Name => 'ConsoleData',
194 SubDirectory => { TagTable => 'Image::ExifTool::LNK::ConsoleData' },
195 },
196 0xa0000003 => {
197 Name => 'TrackerData',
198 SubDirectory => { TagTable => 'Image::ExifTool::LNK::TrackerData' },
199 },
200 0xa0000004 => {
201 Name => 'ConsoleFEData',
202 SubDirectory => { TagTable => 'Image::ExifTool::LNK::ConsoleFEData' },
203 },
204 0xa0000005 => {
205 Name => 'SpecialFolderData',
206 SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
207 },
208 0xa0000006 => {
209 Name => 'DarwinData',
210 SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
211 },
212 0xa0000007 => {
213 Name => 'IconEnvData',
214 SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
215 },
216 0xa0000008 => {
217 Name => 'ShimData',
218 SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
219 },
220 0xa0000009 => {
221 Name => 'PropertyStoreData',
222 SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
223 },
224 0xa000000b => {
225 Name => 'KnownFolderData',
226 SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
227 },
228 0xa000000c => {
229 Name => 'VistaIDListData',
230 SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
231 },
232);
233
234%Image::ExifTool::LNK::ItemID = (
235 GROUPS => { 2 => 'Other' },
236 PROCESS_PROC => \&ProcessItemID,
237 # (can't find any documentation on these items)
238 0x0032 => {
239 Name => 'Item0032',
240 SubDirectory => { TagTable => 'Image::ExifTool::LNK::Item0032' },
241 },
242);
243
244%Image::ExifTool::LNK::Item0032 = (
245 GROUPS => { 2 => 'Other' },
246 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
247 0x0e => {
248 Name => 'TargetFileDOSName',
249 Format => 'var_string',
250 },
251 #not at a fixed offset -- offset is given by last 2 bytes of the item + 0x14
252 #0x22 => {
253 # Name => 'TargetFileName',
254 # Format => 'var_ustring',
255 #},
256);
257
258%Image::ExifTool::LNK::LinkInfo = (
259 GROUPS => { 2 => 'Other' },
260 PROCESS_PROC => \&ProcessLinkInfo,
261 FORMAT => 'int32u',
262 VARS => { NO_ID => 1 },
263 VolumeID => { },
264 DriveType => {
265 PrintConv => {
266 0 => 'Unknown',
267 1 => 'Invalid Root Path',
268 2 => 'Removable Media',
269 3 => 'Fixed Disk',
270 4 => 'Remote Drive',
271 5 => 'CD-ROM',
272 6 => 'Ram Disk',
273 },
274 },
275 DriveSerialNumber => { },
276 VolumeLabel => { },
277 LocalBasePath => { },
278 CommonNetworkRelLink => { },
279 CommonPathSuffix => { },
280 NetName => { },
281 DeviceName => { },
282 NetProviderType => {
283 PrintHex => 1,
284 PrintConv => {
285 0x1a0000 => 'AVID',
286 0x1b0000 => 'DOCUSPACE',
287 0x1c0000 => 'MANGOSOFT',
288 0x1d0000 => 'SERNET',
289 0x1e0000 => 'RIVERFRONT1',
290 0x1f0000 => 'RIVERFRONT2',
291 0x200000 => 'DECORB',
292 0x210000 => 'PROTSTOR',
293 0x220000 => 'FJ_REDIR',
294 0x230000 => 'DISTINCT',
295 0x240000 => 'TWINS',
296 0x250000 => 'RDR2SAMPLE',
297 0x260000 => 'CSC',
298 0x270000 => '3IN1',
299 0x290000 => 'EXTENDNET',
300 0x2a0000 => 'STAC',
301 0x2b0000 => 'FOXBAT',
302 0x2c0000 => 'YAHOO',
303 0x2d0000 => 'EXIFS',
304 0x2e0000 => 'DAV',
305 0x2f0000 => 'KNOWARE',
306 0x300000 => 'OBJECT_DIRE',
307 0x310000 => 'MASFAX',
308 0x320000 => 'HOB_NFS',
309 0x330000 => 'SHIVA',
310 0x340000 => 'IBMAL',
311 0x350000 => 'LOCK',
312 0x360000 => 'TERMSRV',
313 0x370000 => 'SRT',
314 0x380000 => 'QUINCY',
315 0x390000 => 'OPENAFS',
316 0x3a0000 => 'AVID1',
317 0x3b0000 => 'DFS',
318 },
319 },
320);
321
322%Image::ExifTool::LNK::UnknownData = (
323 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
324 GROUPS => { 2 => 'Other' },
325);
326
327%Image::ExifTool::LNK::ConsoleData = (
328 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
329 GROUPS => { 2 => 'Other' },
330 0x08 => {
331 Name => 'FillAttributes',
332 Format => 'int16u',
333 PrintConv => 'sprintf("0x%.2x", $val)',
334 },
335 0x0a => {
336 Name => 'PopupFillAttributes',
337 Format => 'int16u',
338 PrintConv => 'sprintf("0x%.2x", $val)',
339 },
340 0x0c => {
341 Name => 'ScreenBufferSize',
342 Format => 'int16u[2]',
343 PrintConv => '$val=~s/ / x /; $val',
344 },
345 0x10 => {
346 Name => 'WindowSize',
347 Format => 'int16u[2]',
348 PrintConv => '$val=~s/ / x /; $val',
349 },
350 0x14 => {
351 Name => 'WindowOrigin',
352 Format => 'int16u[2]',
353 PrintConv => '$val=~s/ / x /; $val',
354 },
355 0x20 => {
356 Name => 'FontSize',
357 Format => 'int16u[2]',
358 PrintConv => '$val=~s/ / x /; $val',
359 },
360 0x24 => {
361 Name => 'FontFamily',
362 Format => 'int32u',
363 PrintHex => 1,
364 PrintConv => {
365 0 => "Don't Care",
366 0x10 => 'Roman',
367 0x20 => 'Swiss',
368 0x30 => 'Modern',
369 0x40 => 'Script',
370 0x50 => 'Decorative',
371 },
372 },
373 0x28 => {
374 Name => 'FontWeight',
375 Format => 'int32u',
376 },
377 0x2c => {
378 Name => 'FontName',
379 Format => 'undef[64]',
380 RawConv => q{
381 $val = $self->Decode($val, 'UCS2');
382 $val =~ s/\0.*//;
383 return length($val) ? $val : undef;
384 },
385 },
386 0x6c => {
387 Name => 'CursorSize',
388 Format => 'int32u',
389 },
390 0x70 => {
391 Name => 'FullScreen',
392 Format => 'int32u',
393 PrintConv => '$val ? "Yes" : "No"',
394 },
395 0x74 => { #PH (MISSING FROM MS DOCUMENTATION! -- screws up subsequent offsets)
396 Name => 'QuickEdit',
397 Format => 'int32u',
398 PrintConv => '$val ? "Yes" : "No"',
399 },
400 0x78 => {
401 Name => 'InsertMode',
402 Format => 'int32u',
403 PrintConv => '$val ? "Yes" : "No"',
404 },
405 0x7c => {
406 Name => 'WindowOriginAuto',
407 Format => 'int32u',
408 PrintConv => '$val ? "Yes" : "No"',
409 },
410 0x80 => {
411 Name => 'HistoryBufferSize',
412 Format => 'int32u',
413 },
414 0x84 => {
415 Name => 'NumHistoryBuffers',
416 Format => 'int32u',
417 },
418 0x88 => {
419 Name => 'RemoveHistoryDuplicates',
420 Format => 'int32u',
421 PrintConv => '$val ? "Yes" : "No"',
422 },
423);
424
425%Image::ExifTool::LNK::TrackerData = (
426 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
427 GROUPS => { 2 => 'Other' },
428 0x10 => {
429 Name => 'MachineID',
430 Format => 'var_string',
431 },
432);
433
434%Image::ExifTool::LNK::ConsoleFEData = (
435 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
436 GROUPS => { 2 => 'Other' },
437 0x08 => {
438 Name => 'CodePage',
439 Format => 'int32u',
440 },
441);
442
443#------------------------------------------------------------------------------
444# Extract null-terminated ASCII or Unicode string from buffer
445# Inputs: 0) buffer ref, 1) start position, 2) flag for unicode string
446# Return: string or undef if start position is outside bounds
447sub GetString($$;$)
448{
449 my ($dataPt, $pos, $unicode) = @_;
450 return undef if $pos >= length($$dataPt);
451 pos($$dataPt) = $pos;
452 return $1 if ($unicode ? $$dataPt=~/\G((?:..)*?)\0\0/sg : $$dataPt=~/\G(.*?)\0/sg);
453 return substr($$dataPt, $pos);
454}
455
456#------------------------------------------------------------------------------
457# Process item ID data
458# Inputs: 0) ExifTool object reference, 1) dirInfo reference, 2) tag table ref
459# Returns: 1 on success
460sub ProcessItemID($$$)
461{
462 my ($exifTool, $dirInfo, $tagTablePtr) = @_;
463 my $dataPt = $$dirInfo{DataPt};
464 my $dataLen = length $$dataPt;
465 my $pos = 0;
466 my %opts = (
467 DataPt => $dataPt,
468 DataPos => $$dirInfo{DataPos},
469 );
470 $exifTool->VerboseDir('ItemID', undef, $dataLen);
471 for (;;) {
472 last if $pos + 4 >= $dataLen;
473 my $size = Get16u($dataPt, $pos);
474 last if $size < 2 or $pos + $size > $dataLen;
475 my $tag = Get16u($dataPt, $pos+2); # (just a guess -- may not be a tag at all)
476 Image::ExifTool::AddTagToTable($tagTablePtr, $tag, {
477 Name => sprintf('Item%.4x', $tag),
478 SubDirectory => { TagTable => 'Image::ExifTool::LNK::UnknownData' },
479 }) unless $$tagTablePtr{$tag};
480 $exifTool->HandleTag($tagTablePtr, $tag, undef, %opts, Start => $pos, Size => $size);
481 $pos += $size;
482 }
483}
484
485#------------------------------------------------------------------------------
486# Process link information data
487# Inputs: 0) ExifTool object reference, 1) dirInfo reference, 2) tag table ref
488# Returns: 1 on success
489sub ProcessLinkInfo($$$)
490{
491 my ($exifTool, $dirInfo, $tagTablePtr) = @_;
492 my $dataPt = $$dirInfo{DataPt};
493 my $dataLen = length $$dataPt;
494 return 0 if $dataLen < 0x20;
495 my $hdrLen = Get32u($dataPt, 4);
496 my $lif = Get32u($dataPt, 8); # link info flags
497 my %opts = (
498 DataPt => $dataPt,
499 DataPos => $$dirInfo{DataPos},
500 Size => 4, # (typical value size)
501 );
502 my ($off, $unicode, $pos, $val, $size);
503 $exifTool->VerboseDir('LinkInfo', undef, $dataLen);
504 if ($lif & 0x01) {
505 # read Volume ID
506 $off = Get32u($dataPt, 0x0c);
507 if ($off + 0x20 <= $dataLen) {
508 # my $len = Get32u($dataPt, $off);
509 $exifTool->HandleTag($tagTablePtr, 'DriveType', undef, %opts, Start=>$off+4);
510 $pos = Get32u($dataPt, $off + 0x0c);
511 if ($pos == 0x14) {
512 # use VolumeLabelOffsetUnicode instead
513 $pos = Get32u($dataPt, $off + 0x10);
514 $unicode = 1;
515 }
516 $pos += $off;
517 $val = GetString($dataPt, $pos, $unicode);
518 if (defined $val) {
519 $size = length $val;
520 $val = $exifTool->Decode($val, 'UCS2') if $unicode;
521 $exifTool->HandleTag($tagTablePtr, 'VolumeLabel', $val, %opts, Start=>$pos, Size=>$size);
522 }
523 }
524 # read local base path
525 if ($hdrLen >= 0x24) {
526 $pos = Get32u($dataPt, 0x1c);
527 $unicode = 1;
528 } else {
529 $pos = Get32u($dataPt, 0x10);
530 undef $unicode;
531 }
532 $val = GetString($dataPt, $pos, $unicode);
533 if (defined $val) {
534 $size = length $val;
535 $val = $exifTool->Decode($val, 'UCS2') if $unicode;
536 $exifTool->HandleTag($tagTablePtr, 'LocalBasePath', $val, %opts, Start=>$pos, Size=>$size);
537 }
538 }
539 if ($lif & 0x02) {
540 # read common network relative link
541 $off = Get32u($dataPt, 0x14);
542 if ($off and $off + 0x14 <= $dataLen) {
543 my $siz = Get32u($dataPt, $off);
544 $pos = Get32u($dataPt, $off + 0x08);
545 if ($pos > 0x14 and $siz >= 0x18) {
546 $pos = Get32u($dataPt, $off + 0x14);
547 $unicode = 1;
548 } else {
549 undef $unicode;
550 }
551 $val = GetString($dataPt, $pos, $unicode);
552 if (defined $val) {
553 $size = length $val;
554 $val = $exifTool->Decode($val, 'UCS2') if $unicode;
555 $exifTool->HandleTag($tagTablePtr, 'NetName', $val, %opts, Start=>$pos, Size=>$size);
556 }
557 my $flg = Get32u($dataPt, $off + 0x04);
558 if ($flg & 0x01) {
559 $pos = Get32u($dataPt, $off + 0x0c);
560 if ($pos > 0x14 and $siz >= 0x1c) {
561 $pos = Get32u($dataPt, $off + 0x18);
562 $unicode = 1;
563 } else {
564 undef $unicode;
565 }
566 $val = GetString($dataPt, $pos, $unicode);
567 if (defined $val) {
568 $size = length $val;
569 $val = $exifTool->Decode($val, 'UCS2') if $unicode;
570 $exifTool->HandleTag($tagTablePtr, 'DeviceName', $val, %opts, Start=>$pos, Size=>$size);
571 }
572 }
573 if ($flg & 0x02) {
574 $val = Get32u($dataPt, $off + 0x10);
575 $exifTool->HandleTag($tagTablePtr, 'NetProviderType', $val, %opts, Start=>$off + 0x10);
576 }
577 }
578 }
579 return 1;
580}
581
582#------------------------------------------------------------------------------
583# Extract information from a MS Shell Link (Windows shortcut) file
584# Inputs: 0) ExifTool object reference, 1) dirInfo reference
585# Returns: 1 on success, 0 if this wasn't a valid LNK file
586sub ProcessLNK($$)
587{
588 my ($exifTool, $dirInfo) = @_;
589 my $raf = $$dirInfo{RAF};
590 my ($buff, $buf2, $len, $i);
591
592 # read LNK file header
593 $raf->Read($buff, 0x4c) == 0x4c or return 0;
594 $buff =~ /^.{4}\x01\x14\x02\0{5}\xc0\0{6}\x46/s or return 0;
595 $len = unpack('V', $buff);
596 $len >= 0x4c or return 0;
597 if ($len > 0x4c) {
598 $raf->Read($buf2, $len - 0x4c) == $len - 0x4c or return 0;
599 $buff .= $buf2;
600 }
601 $exifTool->SetFileType('Windows Shortcut');
602 SetByteOrder('II');
603
604 my $tagTablePtr = GetTagTable('Image::ExifTool::LNK::Main');
605 my %dirInfo = (
606 DataPt => \$buff,
607 DataPos => 0,
608 DataLen => length $buff,
609 DirLen => length $buff,
610 );
611 $exifTool->ProcessDirectory(\%dirInfo, $tagTablePtr);
612
613 my $flags = Get32u(\$buff, 0x14);
614
615 # read link target ID list
616 if ($flags & 0x01) {
617 $raf->Read($buff, 2) or return 1;
618 $len = unpack('v', $buff);
619 $raf->Read($buff, $len) == $len or return 1;
620 $exifTool->HandleTag($tagTablePtr, 0x10000, undef,
621 DataPt => \$buff,
622 DataPos => $raf->Tell() - $len,
623 Size => $len,
624 );
625 }
626
627 # read link information
628 if ($flags & 0x02) {
629 $raf->Read($buff, 4) or return 1;
630 $len = unpack('V', $buff);
631 return 1 if $len < 4;
632 $raf->Read($buf2, $len - 4) == $len - 4 or return 1;
633 $buff .= $buf2;
634 $exifTool->HandleTag($tagTablePtr, 0x20000, undef,
635 DataPt => \$buff,
636 DataPos => $raf->Tell() - $len,
637 Size => $len,
638 );
639 }
640
641 # read string data
642 my @strings = qw(Description RelativePath WorkingDirectory
643 CommandLineArguments IconFileName);
644 for ($i=0; $i<@strings; ++$i) {
645 my $mask = 0x04 << $i;
646 next unless $flags & $mask;
647 $raf->Read($buff, 2) or return 1;
648 $len = unpack('v', $buff);
649 $len *= 2 if $flags & 0x80; # characters are 2 bytes if Unicode flag is set
650 $raf->Read($buff, $len) or return 1;
651 my $val;
652 $val = $exifTool->Decode($buff, 'UCS2') if $flags & 0x80;
653 $exifTool->HandleTag($tagTablePtr, 0x30000 | $mask, $val,
654 DataPt => \$buff,
655 DataPos => $raf->Tell() - $len,
656 Size => $len,
657 );
658 }
659
660 # read extra data
661 while ($raf->Read($buff, 4) == 4) {
662 $len = unpack('V', $buff);
663 last if $len < 4;
664 $len -= 4;
665 $raf->Read($buf2, $len) == $len or last;
666 next unless $len > 4;
667 $buff .= $buf2;
668 my $tag = Get32u(\$buff, 4);
669 my $tagInfo = $$tagTablePtr{$tag};
670 unless (ref $tagInfo eq 'HASH' and $$tagInfo{SubDirectory}) {
671 $tagInfo = $$tagTablePtr{0xa0000000};
672 }
673 $exifTool->HandleTag($tagTablePtr, $tag, undef,
674 DataPt => \$buff,
675 DataPos => $raf->Tell() - $len - 4,
676 TagInfo => $tagInfo,
677 );
678 }
679 return 1;
680}
681
6821; # end
683
684__END__
685
686=head1 NAME
687
688Image::ExifTool::LNK - Read MS Shell Link (.LNK) meta information
689
690=head1 SYNOPSIS
691
692This module is used by Image::ExifTool
693
694=head1 DESCRIPTION
695
696This module contains definitions required by Image::ExifTool to extract meta
697information MS Shell Link (Windows shortcut) files.
698
699=head1 AUTHOR
700
701Copyright 2003-2011, Phil Harvey (phil at owl.phy.queensu.ca)
702
703This library is free software; you can redistribute it and/or modify it
704under the same terms as Perl itself.
705
706=head1 REFERENCES
707
708=over 4
709
710=item L<http://msdn.microsoft.com/en-us/library/dd871305(PROT.10).aspx>
711
712=item L<http://www.i2s-lab.com/Papers/The_Windows_Shortcut_File_Format.pdf>
713
714=back
715
716=head1 SEE ALSO
717
718L<Image::ExifTool::TagNames/LNK Tags>,
719L<Image::ExifTool(3pm)|Image::ExifTool>
720
721=cut
722
Note: See TracBrowser for help on using the repository browser.