Dissecting a Shortcut
Ever wondered about the layout of shortcut files? Those tiny little buggers with the extension LNK you have probably dozens of on your desktop? For years the format was subject to reverse engineering and speculation. Last year Microsoft finally released an official format specification, documenting this surprisingly complex format. This article is the result of analyzing a typical LNK file with the help of Microsoft’s documentation and information from other sources.
The shortcut points to a copy of notepad.exe stored in “C:\Programme\Testordner”. The shortcut was created with Explorer on a German installation of Windows XP.
===== < Start of header (ShellLinkHeader)
4C 00 00 00 < HeaderSize: 0x4C = 76 bytes
01 14 02 00 < LinkCLSID: always 00021401-0000-0000-C000-000000000046
00 00 00 00 < "
C0 00 00 00 < "
00 00 00 46 < "
9B 00 00 00 < LinkFlags: 0x9B = 10011011 = HasLinkTargetIDList + HasLinkInfo + HasRelativePath + HasWorkingDir + IsUnicode
20 00 00 00 < FileAttributes: 0x20 = 00100000 = Archive
8C 05 B9 C6 < CreationTime: 0x01CC63D6C6B9058C = Friday, August 26, 2011 11:59:00am (as per http://www.silisoftware.com/tools/date.php)
D6 63 CC 01 < "
B7 AD 6F CD < AccessTime: 0x01CC63D6CD6FADB7 = Friday, August 26, 2011 11:59:11am
D6 63 CC 01 < "
00 A0 A1 10 < WriteTime: 0x01C89E2710A1A000 = Monday, April 14, 2008 2:00:00pm
27 9E C8 01 < "
00 12 01 00 < FileSize: 0x011200 = 70,144 bytes
00 00 00 00 < IconIndex: 0
01 00 00 00 < ShowCommand: 1 = SW_SHOWNORMAL
00 00 < HotKey (2 bytes): 0 = no hotkey defined
00 00 < Reserved1 (2 bytes)
00 00 00 00 < Reserved2
00 00 00 00 < Reserved3
===== < End of header
===== < Start of LinkTargetIDList (HasLinkTargetIDList indicates presence of this structure)
FD 00 < IDListSize: 0xFD = 253 bytes
----- < Start of IDList structure
----- < Start of ItemID structure
14 00 < ItemIDSize: 0x14 = 20 bytes
1F < Type indicator: 0x1F = folder
50 < Folder ID: 0x50 = My Computer
E0 4F < Folder GUID: 20d04fe0-3aea-1069-a2d8-08002b30309d = My Computer
D0 20 EA 3A < "
69 10 A2 D8 < "
08 00 2B 30 < "
30 9D < "
----- < End of ItemID structure
----- < Start of ItemID structure
19 00 < ItemIDSize: 0x19 = 25 bytes
2F < Type indicator: 0x2F = volume name
43 3A 5C < Volume name: C:\
00 00 00 00 < "
00 00 00 00 < "
00 00 00 00 < "
00 00 00 00 < "
00 00 00 < "
----- < End of ItemID structure
----- < Start of ItemID structure
42 < ItemIDSize: 0x42 = 66 bytes
00 < "
31 < Type indicator: 0x31 = file entry
00 < Flags
00 < File size
00 00 00 < "
95 < Last modification timestamp in DOS format: 0x45B83E95 = 01000 101101 11000 0011111 0100 10101 = 21.08.2011 8:47:24
3E B8 45 < "
11 < File/directory attributes: 0x11 = FILE_ATTRIBUTE_DIRECTORY + FILE_ATTRIBUTE_READONLY
00 < "
50 52 4F < Short name: PROGRA~1
47 52 41 7E < "
31 00 00 < "
2A < Extension size: 0x2A = 42 bytes
00 < "
03 00 < Extension version: 3 = Windows XP
04 < Unknown
00 < "
EF BE < Unknown (0xBEEF)
95 < Creation timestamp in DOS format: 0x40F63E95 = 01000 000111 10110 0011111 0100 10101 = 21.08.2011 8:07:22
3E F6 40 < "
1A < Last access timestamp in DOS format: 0x4F313F1A = 01001 111001 10001 0011111 1000 11010 = 26.8.2011 9:57:17
3F 31 4F < "
14 < Unknown
00 00 00 < "
50 < Long name: Programme
00 72 00 6F < "
00 67 00 72 < "
00 61 00 6D < "
00 6D 00 65 < "
00 00 00 < "
18 < Unknown (0x18 = directory)
00 < "
----- < End of ItemID structure
----- < Start of ItemID structure
44 00 < ItemIDSize: 0x44 = 68 bytes
31 < Type indicator: 0x31 = file entry
00 < Flags
00 00 00 < File size
00 < "
1A 3F 59 < Last modification timestamp in DOS format
4F < "
10 00 < Attributes: 0x10 = FILE_ATTRIBUTE_DIRECTORY
54 < Short name: TESTOR~1
45 53 54 4F < "
52 7E 31 00 < "
00 < "
2C 00 < Extension size: 0x2C = 44 bytes
03 < Extension version: 0x03 = Windows XP
00 < "
04 00 < Unknown
EF < Unknown (0xBEEF)
BE < "
1A 3F 59 < Creation timestamp in DOS format
4F < "
1A 3F 59 < Last access timestamp in DOS format
4F < "
14 00 00 < Unknown
00 < "
54 00 65 < Long name: Testordner
00 73 00 74 < "
00 6F 00 72 < "
00 64 00 6E < "
00 65 00 72 < "
00 00 00 < "
18 < Unknown
00 < "
----- < End of ItemID structure
----- < Start of ItemID structure
48 00 < ItemIDSize: 0x48 = 72 bytes
32 < Type indicator: 0x32 = file entry
00 < Flags
00 12 01 < File size: 0x11200 = 70,144 bytes
00 < "
8E 38 00 < Last modification timestamp in DOS format
60 < "
20 00 < Attributes: 0x20 = FILE_ATTRIBUTE_ARCHIVE
6E < Short name: notepad.exe
6F 74 65 70 < "
61 64 2E 65 < "
78 65 00 < "
2E < Extension size: 0x2E = 46 bytes
00 < "
03 00 < Extension version: 0x03 = Windows XP
04 < Unknown
00 < "
EF BE < Unknown (0xBEEF)
1A < Creation timestamp in DOS format
3F 60 4F < "
1A < Last access timestamp in DOS format
3F 60 4F < "
14 < Unknown
00 00 00 < "
6E < Long name: notepad.exe
00 6F 00 74 < "
00 65 00 70 < "
00 61 00 64 < "
00 2E 00 65 < "
00 78 00 65 < "
00 00 00 < "
1A < Unknown (0x18 = file)
00 < "
----- < End of ItemID structure
00 00 < TerminalID: indicating the end of the structure
----- < End of ID list structure
===== < End of LinkTargetIDList
===== < Start of LinkInfo (HasLinkInfo indicates presence of this structure)
52 < LinkInfoSize: 0x52 = 82 bytes
00 00 00 < "
1C < LinkInfoHeaderSize: 0x1C = 28 = 'offsets to the optional fields are not specified'
00 00 00 < "
01 < LinkInfoFlags: 1 = VolumeID and LocalBasePath fields are present
00 00 00 < "
1C < VolumeIDOffset: 0x1C = 28 bytes
00 00 00 < "
2D < LocalBasePathOffset: 0x2D = 45 bytes
00 00 00 < "
00 < CommonNetworkRelativeLinkOffset: 0 because LinkInfoFlags does not indicate presence
00 00 00 < "
51 < CommonPathSuffixOffset: 0x51 = 81 bytes
00 00 00 < "
----- < Start of VolumeID structure
11 < VolumeIDSize: 0x11 = 17 bytes
00 00 00 < "
03 < DriveType: 0x3 = DRIVE_FIXED
00 00 00 < "
14 < DriveSerialNumber: 0x688E9914
99 8E 68 < "
10 < VolumeLabelOffset: 0x10 = 16 bytes
00 00 00 < "
00 < Volume label: empty string
----- < End of VolumeID structure
43 3A 5C 50 < LocalBasePath: C:\Programme\Testordner\notepad.exe
72 6F 67 72 < "
61 6D 6D 65 < "
5C 54 65 73 < "
74 6F 72 64 < "
6E 65 72 5C < "
6E 6F 74 65 < "
70 61 64 2E < "
65 78 65 00 < "
00 < CommonPathSuffix: empty string
===== < End of LinkInfo
===== < Start of RELATIVE_PATH structure (presence indicated by HasRelativePath)
29 00 < CountCharacters: 0x29 = 41 Unicode characters (IsUnicode is enabled)
2E < Relative path (not null-terminated): ..\..\..\Programme\Testordner\notepad.exe
00 2E 00 5C < "
00 2E 00 2E < "
00 5C 00 2E < "
00 2E 00 5C < "
00 50 00 72 < "
00 6F 00 67 < "
00 72 00 61 < "
00 6D 00 6D < "
00 65 00 5C < "
00 54 00 65 < "
00 73 00 74 < "
00 6F 00 72 < "
00 64 00 6E < "
00 65 00 72 < "
00 5C 00 6E < "
00 6F 00 74 < "
00 65 00 70 < "
00 61 00 64 < "
00 2E 00 65 < "
00 78 00 65 < "
00 < "
===== < End of RELATIVE_PATH structure
===== < Start of WORKING_DIR structure (presence indicated by HasWorkingDir)
17 00 < CountCharacters: 0x17 = 23 Unicode characters (IsUnicode is enabled)
43 < Working directory (not null-terminated): C:\Programme\Testordner
00 3A 00 5C < "
00 50 00 72 < "
00 6F 00 67 < "
00 72 00 61 < "
00 6D 00 6D < "
00 65 00 5C < "
00 54 00 65 < "
00 73 00 74 < "
00 6F 00 72 < "
00 64 00 6E < "
00 65 00 72 < "
00 < "
===== < End of WORKING_DIR structure
===== < Start of ExtraData
----- < Start of extra data block
10 00 00 < BlockSize: 0x10 = 16 bytes
00 < "
05 00 00 < BlockSignature: 0xA0000005 = This block is a SpecialFolderDataBlock
A0 < "
26 00 00 < SpecialFolderID: 0x26 = 38 = CSIDL_PROGRAM_FILES
00 < "
6F 00 00 < Offset: 0x6F = 111. Location of this special folder in IDList
00 < "
----- < End of extra data block
----- < Start of extra data block
60 00 00 < BlockSize: 0x60 = 96 bytes
00 < "
03 00 00 < BlockSignature: 0xA000000003 = This block is a TrackerDataBlock
A0 < "
58 00 00 < Length: must be >= 0x58
00 < "
00 00 00 < Version: must be 0
00 < "
6D 61 63 < MachineID (16 bytes): machinede10. NetBIOS name of the computer the link target is stored on.
68 69 6E 65 < "
64 65 31 30 < "
00 00 00 00 < "
00 < "
5C 09 DE < Droid: 2 GUIDs, used to find the link target with the Link Tracking service.
4B 85 9C 8E < "
47 93 20 9D < "
B9 5D 86 6D < "
FE D3 FC 9E < "
8A 08 CF E0 < "
11 94 8B 00 < "
15 5D 17 7D < "
6F < "
5C 09 DE < DroidBirth: 2 GUIDs, used to find the link target with the Link Tracking service.
4B 85 9C 8E < "
47 93 20 9D < "
B9 5D 86 6D < "
FE D3 FC 9E < "
8A 08 CF E0 < "
11 94 8B 00 < "
15 5D 17 7D < "
6F < "
----- < End of extra data block
00 00 00 < TerminalBlock: indicates end of structure
00 < "
===== < End of ExtraData
References
Microsoft’s official documentation of the LNK file format
MSDN page about shell links and shortcuts
Inofficial LNK file format documentation obtained by reverse engineering
Inofficial Windows Shell Item Format Specification
2 Comments
Thank you pretty much for an example dissection. It will be useful for my shortcut reader and writer completely written in .NET, since creating a link with .NET is a COM or p/invoke story at the moment.
Thank you for your work providing this information. I found it hard to find detailed and clear documentation from Microsoft on the LINKTARGETIDLIST structure.