Windows shell link file: GraphViz block diagram (.dot) source

Windows .lnk files (AKA "shell link" file) are most frequently used in Windows shell to create "shortcuts" to another files, usually for purposes of running a program from some other directory, sometimes with certain preconfigured arguments and some other options.

This page hosts a formal specification of Windows shell link file using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

GraphViz block diagram source

windows_lnk_file.dot

digraph {
	rankdir=LR;
	node [shape=plaintext];
	subgraph cluster__windows_lnk_file {
		label="WindowsLnkFile";
		graph[style=dotted];

		windows_lnk_file__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
			<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
			<TR><TD PORT="header_pos">0</TD><TD PORT="header_size">76</TD><TD>FileHeader</TD><TD PORT="header_type">header</TD></TR>
			<TR><TD PORT="target_id_list_pos">76</TD><TD PORT="target_id_list_size">...</TD><TD>LinkTargetIdList</TD><TD PORT="target_id_list_type">target_id_list</TD></TR>
			<TR><TD PORT="info_pos">...</TD><TD PORT="info_size">...</TD><TD>LinkInfo</TD><TD PORT="info_type">info</TD></TR>
			<TR><TD PORT="name_pos">...</TD><TD PORT="name_size">...</TD><TD>StringData</TD><TD PORT="name_type">name</TD></TR>
			<TR><TD PORT="rel_path_pos">...</TD><TD PORT="rel_path_size">...</TD><TD>StringData</TD><TD PORT="rel_path_type">rel_path</TD></TR>
			<TR><TD PORT="work_dir_pos">...</TD><TD PORT="work_dir_size">...</TD><TD>StringData</TD><TD PORT="work_dir_type">work_dir</TD></TR>
			<TR><TD PORT="arguments_pos">...</TD><TD PORT="arguments_size">...</TD><TD>StringData</TD><TD PORT="arguments_type">arguments</TD></TR>
			<TR><TD PORT="icon_location_pos">...</TD><TD PORT="icon_location_size">...</TD><TD>StringData</TD><TD PORT="icon_location_type">icon_location</TD></TR>
		</TABLE>>];
		subgraph cluster__link_target_id_list {
			label="WindowsLnkFile::LinkTargetIdList";
			graph[style=dotted];

			link_target_id_list__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="len_id_list_pos">0</TD><TD PORT="len_id_list_size">2</TD><TD>u2le</TD><TD PORT="len_id_list_type">len_id_list</TD></TR>
				<TR><TD PORT="id_list_pos">2</TD><TD PORT="id_list_size">len_id_list</TD><TD>WindowsShellItems</TD><TD PORT="id_list_type">id_list</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__string_data {
			label="WindowsLnkFile::StringData";
			graph[style=dotted];

			string_data__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="chars_str_pos">0</TD><TD PORT="chars_str_size">2</TD><TD>u2le</TD><TD PORT="chars_str_type">chars_str</TD></TR>
				<TR><TD PORT="str_pos">2</TD><TD PORT="str_size">(chars_str * 2)</TD><TD>str(UTF-16LE)</TD><TD PORT="str_type">str</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__link_info {
			label="WindowsLnkFile::LinkInfo";
			graph[style=dotted];

			link_info__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="len_all_pos">0</TD><TD PORT="len_all_size">4</TD><TD>u4le</TD><TD PORT="len_all_type">len_all</TD></TR>
				<TR><TD PORT="all_pos">4</TD><TD PORT="all_size">(len_all - 4)</TD><TD>All</TD><TD PORT="all_type">all</TD></TR>
			</TABLE>>];
			subgraph cluster__volume_id_body {
				label="WindowsLnkFile::LinkInfo::VolumeIdBody";
				graph[style=dotted];

				volume_id_body__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="drive_type_pos">0</TD><TD PORT="drive_type_size">4</TD><TD>u4le→DriveTypes</TD><TD PORT="drive_type_type">drive_type</TD></TR>
					<TR><TD PORT="drive_serial_number_pos">4</TD><TD PORT="drive_serial_number_size">4</TD><TD>u4le</TD><TD PORT="drive_serial_number_type">drive_serial_number</TD></TR>
					<TR><TD PORT="ofs_volume_label_pos">8</TD><TD PORT="ofs_volume_label_size">4</TD><TD>u4le</TD><TD PORT="ofs_volume_label_type">ofs_volume_label</TD></TR>
					<TR><TD PORT="ofs_volume_label_unicode_pos">12</TD><TD PORT="ofs_volume_label_unicode_size">4</TD><TD>u4le</TD><TD PORT="ofs_volume_label_unicode_type">ofs_volume_label_unicode</TD></TR>
				</TABLE>>];
				volume_id_body__inst__is_unicode [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">id</TD><TD BGCOLOR="#E0FFE0">value</TD></TR>
					<TR><TD>is_unicode</TD><TD>ofs_volume_label == 20</TD></TR>
				</TABLE>>];
				volume_id_body__inst__volume_label_ansi [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="volume_label_ansi_pos">(ofs_volume_label - 4)</TD><TD PORT="volume_label_ansi_size">...</TD><TD>str(cp437)</TD><TD PORT="volume_label_ansi_type">volume_label_ansi</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__all {
				label="WindowsLnkFile::LinkInfo::All";
				graph[style=dotted];

				all__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="len_header_pos">0</TD><TD PORT="len_header_size">4</TD><TD>u4le</TD><TD PORT="len_header_type">len_header</TD></TR>
					<TR><TD PORT="header_pos">4</TD><TD PORT="header_size">(len_header - 8)</TD><TD>Header</TD><TD PORT="header_type">header</TD></TR>
				</TABLE>>];
				all__inst__volume_id [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="volume_id_pos">(header.ofs_volume_id - 4)</TD><TD PORT="volume_id_size">...</TD><TD>VolumeIdSpec</TD><TD PORT="volume_id_type">volume_id</TD></TR>
				</TABLE>>];
				all__inst__local_base_path [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="local_base_path_pos">(header.ofs_local_base_path - 4)</TD><TD PORT="local_base_path_size">...</TD><TD></TD><TD PORT="local_base_path_type">local_base_path</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__volume_id_spec {
				label="WindowsLnkFile::LinkInfo::VolumeIdSpec";
				graph[style=dotted];

				volume_id_spec__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="len_all_pos">0</TD><TD PORT="len_all_size">4</TD><TD>u4le</TD><TD PORT="len_all_type">len_all</TD></TR>
					<TR><TD PORT="body_pos">4</TD><TD PORT="body_size">(len_all - 4)</TD><TD>VolumeIdBody</TD><TD PORT="body_type">body</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__link_info_flags {
				label="WindowsLnkFile::LinkInfo::LinkInfoFlags";
				graph[style=dotted];

				link_info_flags__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="reserved1_pos">0</TD><TD PORT="reserved1_size">6b</TD><TD>b6</TD><TD PORT="reserved1_type">reserved1</TD></TR>
					<TR><TD PORT="has_common_net_rel_link_pos">0:6</TD><TD PORT="has_common_net_rel_link_size">1b</TD><TD>BitsType1(BigBitEndian)</TD><TD PORT="has_common_net_rel_link_type">has_common_net_rel_link</TD></TR>
					<TR><TD PORT="has_volume_id_and_local_base_path_pos">0:7</TD><TD PORT="has_volume_id_and_local_base_path_size">1b</TD><TD>BitsType1(BigBitEndian)</TD><TD PORT="has_volume_id_and_local_base_path_type">has_volume_id_and_local_base_path</TD></TR>
					<TR><TD PORT="reserved2_pos">1</TD><TD PORT="reserved2_size">3</TD><TD>b24</TD><TD PORT="reserved2_type">reserved2</TD></TR>
				</TABLE>>];
			}
			subgraph cluster__header {
				label="WindowsLnkFile::LinkInfo::Header";
				graph[style=dotted];

				header__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
					<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
					<TR><TD PORT="flags_pos">0</TD><TD PORT="flags_size">4</TD><TD>LinkInfoFlags</TD><TD PORT="flags_type">flags</TD></TR>
					<TR><TD PORT="ofs_volume_id_pos">4</TD><TD PORT="ofs_volume_id_size">4</TD><TD>u4le</TD><TD PORT="ofs_volume_id_type">ofs_volume_id</TD></TR>
					<TR><TD PORT="ofs_local_base_path_pos">8</TD><TD PORT="ofs_local_base_path_size">4</TD><TD>u4le</TD><TD PORT="ofs_local_base_path_type">ofs_local_base_path</TD></TR>
					<TR><TD PORT="ofs_common_net_rel_link_pos">12</TD><TD PORT="ofs_common_net_rel_link_size">4</TD><TD>u4le</TD><TD PORT="ofs_common_net_rel_link_type">ofs_common_net_rel_link</TD></TR>
					<TR><TD PORT="ofs_common_path_suffix_pos">16</TD><TD PORT="ofs_common_path_suffix_size">4</TD><TD>u4le</TD><TD PORT="ofs_common_path_suffix_type">ofs_common_path_suffix</TD></TR>
					<TR><TD PORT="ofs_local_base_path_unicode_pos">20</TD><TD PORT="ofs_local_base_path_unicode_size">4</TD><TD>u4le</TD><TD PORT="ofs_local_base_path_unicode_type">ofs_local_base_path_unicode</TD></TR>
					<TR><TD PORT="ofs_common_path_suffix_unicode_pos">24</TD><TD PORT="ofs_common_path_suffix_unicode_size">4</TD><TD>u4le</TD><TD PORT="ofs_common_path_suffix_unicode_type">ofs_common_path_suffix_unicode</TD></TR>
				</TABLE>>];
			}
		}
		subgraph cluster__link_flags {
			label="WindowsLnkFile::LinkFlags";
			graph[style=dotted];

			link_flags__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="is_unicode_pos">0</TD><TD PORT="is_unicode_size">1b</TD><TD>BitsType1(BigBitEndian)</TD><TD PORT="is_unicode_type">is_unicode</TD></TR>
				<TR><TD PORT="has_icon_location_pos">0:1</TD><TD PORT="has_icon_location_size">1b</TD><TD>BitsType1(BigBitEndian)</TD><TD PORT="has_icon_location_type">has_icon_location</TD></TR>
				<TR><TD PORT="has_arguments_pos">0:2</TD><TD PORT="has_arguments_size">1b</TD><TD>BitsType1(BigBitEndian)</TD><TD PORT="has_arguments_type">has_arguments</TD></TR>
				<TR><TD PORT="has_work_dir_pos">0:3</TD><TD PORT="has_work_dir_size">1b</TD><TD>BitsType1(BigBitEndian)</TD><TD PORT="has_work_dir_type">has_work_dir</TD></TR>
				<TR><TD PORT="has_rel_path_pos">0:4</TD><TD PORT="has_rel_path_size">1b</TD><TD>BitsType1(BigBitEndian)</TD><TD PORT="has_rel_path_type">has_rel_path</TD></TR>
				<TR><TD PORT="has_name_pos">0:5</TD><TD PORT="has_name_size">1b</TD><TD>BitsType1(BigBitEndian)</TD><TD PORT="has_name_type">has_name</TD></TR>
				<TR><TD PORT="has_link_info_pos">0:6</TD><TD PORT="has_link_info_size">1b</TD><TD>BitsType1(BigBitEndian)</TD><TD PORT="has_link_info_type">has_link_info</TD></TR>
				<TR><TD PORT="has_link_target_id_list_pos">0:7</TD><TD PORT="has_link_target_id_list_size">1b</TD><TD>BitsType1(BigBitEndian)</TD><TD PORT="has_link_target_id_list_type">has_link_target_id_list</TD></TR>
				<TR><TD PORT="_unnamed8_pos">1</TD><TD PORT="_unnamed8_size">2</TD><TD>b16</TD><TD PORT="_unnamed8_type">_unnamed8</TD></TR>
				<TR><TD PORT="reserved_pos">3</TD><TD PORT="reserved_size">5b</TD><TD>b5</TD><TD PORT="reserved_type">reserved</TD></TR>
				<TR><TD PORT="keep_local_id_list_for_unc_target_pos">3:5</TD><TD PORT="keep_local_id_list_for_unc_target_size">1b</TD><TD>BitsType1(BigBitEndian)</TD><TD PORT="keep_local_id_list_for_unc_target_type">keep_local_id_list_for_unc_target</TD></TR>
				<TR><TD PORT="_unnamed11_pos">3:6</TD><TD PORT="_unnamed11_size">2b</TD><TD>b2</TD><TD PORT="_unnamed11_type">_unnamed11</TD></TR>
			</TABLE>>];
		}
		subgraph cluster__file_header {
			label="WindowsLnkFile::FileHeader";
			graph[style=dotted];

			file_header__seq [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
				<TR><TD BGCOLOR="#E0FFE0">pos</TD><TD BGCOLOR="#E0FFE0">size</TD><TD BGCOLOR="#E0FFE0">type</TD><TD BGCOLOR="#E0FFE0">id</TD></TR>
				<TR><TD PORT="len_header_pos">0</TD><TD PORT="len_header_size">4</TD><TD></TD><TD PORT="len_header_type">len_header</TD></TR>
				<TR><TD PORT="link_clsid_pos">4</TD><TD PORT="link_clsid_size">16</TD><TD></TD><TD PORT="link_clsid_type">link_clsid</TD></TR>
				<TR><TD PORT="flags_pos">20</TD><TD PORT="flags_size">4</TD><TD>LinkFlags</TD><TD PORT="flags_type">flags</TD></TR>
				<TR><TD PORT="file_attrs_pos">24</TD><TD PORT="file_attrs_size">4</TD><TD>u4le</TD><TD PORT="file_attrs_type">file_attrs</TD></TR>
				<TR><TD PORT="time_creation_pos">28</TD><TD PORT="time_creation_size">8</TD><TD>u8le</TD><TD PORT="time_creation_type">time_creation</TD></TR>
				<TR><TD PORT="time_access_pos">36</TD><TD PORT="time_access_size">8</TD><TD>u8le</TD><TD PORT="time_access_type">time_access</TD></TR>
				<TR><TD PORT="time_write_pos">44</TD><TD PORT="time_write_size">8</TD><TD>u8le</TD><TD PORT="time_write_type">time_write</TD></TR>
				<TR><TD PORT="target_file_size_pos">52</TD><TD PORT="target_file_size_size">4</TD><TD>u4le</TD><TD PORT="target_file_size_type">target_file_size</TD></TR>
				<TR><TD PORT="icon_index_pos">56</TD><TD PORT="icon_index_size">4</TD><TD>s4le</TD><TD PORT="icon_index_type">icon_index</TD></TR>
				<TR><TD PORT="show_command_pos">60</TD><TD PORT="show_command_size">4</TD><TD>u4le→WindowState</TD><TD PORT="show_command_type">show_command</TD></TR>
				<TR><TD PORT="hotkey_pos">64</TD><TD PORT="hotkey_size">2</TD><TD>u2le</TD><TD PORT="hotkey_type">hotkey</TD></TR>
				<TR><TD PORT="reserved_pos">66</TD><TD PORT="reserved_size">10</TD><TD></TD><TD PORT="reserved_type">reserved</TD></TR>
			</TABLE>>];
		}
	}
	windows_lnk_file__seq:header_type -> file_header__seq [style=bold];
	windows_lnk_file__seq:target_id_list_type -> link_target_id_list__seq [style=bold];
	windows_lnk_file__seq:info_type -> link_info__seq [style=bold];
	windows_lnk_file__seq:name_type -> string_data__seq [style=bold];
	windows_lnk_file__seq:rel_path_type -> string_data__seq [style=bold];
	windows_lnk_file__seq:work_dir_type -> string_data__seq [style=bold];
	windows_lnk_file__seq:arguments_type -> string_data__seq [style=bold];
	windows_lnk_file__seq:icon_location_type -> string_data__seq [style=bold];
	link_target_id_list__seq:len_id_list_type -> link_target_id_list__seq:id_list_size [color="#404040"];
	link_target_id_list__seq:id_list_type -> windows_shell_items__seq [style=bold];
	string_data__seq:chars_str_type -> string_data__seq:str_size [color="#404040"];
	link_info__seq:len_all_type -> link_info__seq:all_size [color="#404040"];
	link_info__seq:all_type -> all__seq [style=bold];
	volume_id_body__seq:ofs_volume_label_type -> volume_id_body__inst__is_unicode [color="#404040"];
	volume_id_body__seq:ofs_volume_label_type -> volume_id_body__inst__volume_label_ansi:volume_label_ansi_pos [color="#404040"];
	all__seq:len_header_type -> all__seq:header_size [color="#404040"];
	all__seq:header_type -> header__seq [style=bold];
	header__seq:ofs_volume_id_type -> all__inst__volume_id:volume_id_pos [color="#404040"];
	all__inst__volume_id:volume_id_type -> volume_id_spec__seq [style=bold];
	header__seq:ofs_local_base_path_type -> all__inst__local_base_path:local_base_path_pos [color="#404040"];
	volume_id_spec__seq:len_all_type -> volume_id_spec__seq:body_size [color="#404040"];
	volume_id_spec__seq:body_type -> volume_id_body__seq [style=bold];
	header__seq:flags_type -> link_info_flags__seq [style=bold];
	file_header__seq:flags_type -> link_flags__seq [style=bold];
}