Windows shell link file: Go parsing library

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.

Go source code to parse Windows shell link file

windows_lnk_file.go

// Code generated by kaitai-struct-compiler from a .ksy source file. DO NOT EDIT.

import (
	"github.com/kaitai-io/kaitai_struct_go_runtime/kaitai"
	"bytes"
	"io"
	"golang.org/x/text/encoding/charmap"
	"golang.org/x/text/encoding/unicode"
)


/**
 * 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.
 * @see <a href="https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-SHLLINK/[MS-SHLLINK].pdf">Source</a>
 */

type WindowsLnkFile_DriveTypes int
const (
	WindowsLnkFile_DriveTypes__Unknown WindowsLnkFile_DriveTypes = 0
	WindowsLnkFile_DriveTypes__NoRootDir WindowsLnkFile_DriveTypes = 1
	WindowsLnkFile_DriveTypes__Removable WindowsLnkFile_DriveTypes = 2
	WindowsLnkFile_DriveTypes__Fixed WindowsLnkFile_DriveTypes = 3
	WindowsLnkFile_DriveTypes__Remote WindowsLnkFile_DriveTypes = 4
	WindowsLnkFile_DriveTypes__Cdrom WindowsLnkFile_DriveTypes = 5
	WindowsLnkFile_DriveTypes__Ramdisk WindowsLnkFile_DriveTypes = 6
)
var values_WindowsLnkFile_DriveTypes = map[WindowsLnkFile_DriveTypes]struct{}{0: {}, 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}}
func (v WindowsLnkFile_DriveTypes) isDefined() bool {
	_, ok := values_WindowsLnkFile_DriveTypes[v]
	return ok
}

type WindowsLnkFile_WindowState int
const (
	WindowsLnkFile_WindowState__Normal WindowsLnkFile_WindowState = 1
	WindowsLnkFile_WindowState__Maximized WindowsLnkFile_WindowState = 3
	WindowsLnkFile_WindowState__MinNoActive WindowsLnkFile_WindowState = 7
)
var values_WindowsLnkFile_WindowState = map[WindowsLnkFile_WindowState]struct{}{1: {}, 3: {}, 7: {}}
func (v WindowsLnkFile_WindowState) isDefined() bool {
	_, ok := values_WindowsLnkFile_WindowState[v]
	return ok
}
type WindowsLnkFile struct {
	Header *WindowsLnkFile_FileHeader
	TargetIdList *WindowsLnkFile_LinkTargetIdList
	Info *WindowsLnkFile_LinkInfo
	Name *WindowsLnkFile_StringData
	RelPath *WindowsLnkFile_StringData
	WorkDir *WindowsLnkFile_StringData
	Arguments *WindowsLnkFile_StringData
	IconLocation *WindowsLnkFile_StringData
	_io *kaitai.Stream
	_root *WindowsLnkFile
	_parent kaitai.Struct
}
func NewWindowsLnkFile() *WindowsLnkFile {
	return &WindowsLnkFile{
	}
}

func (this WindowsLnkFile) IO_() *kaitai.Stream {
	return this._io
}

func (this *WindowsLnkFile) Read(io *kaitai.Stream, parent kaitai.Struct, root *WindowsLnkFile) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp1 := NewWindowsLnkFile_FileHeader()
	err = tmp1.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.Header = tmp1
	if (this.Header.Flags.HasLinkTargetIdList) {
		tmp2 := NewWindowsLnkFile_LinkTargetIdList()
		err = tmp2.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		this.TargetIdList = tmp2
	}
	if (this.Header.Flags.HasLinkInfo) {
		tmp3 := NewWindowsLnkFile_LinkInfo()
		err = tmp3.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		this.Info = tmp3
	}
	if (this.Header.Flags.HasName) {
		tmp4 := NewWindowsLnkFile_StringData()
		err = tmp4.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		this.Name = tmp4
	}
	if (this.Header.Flags.HasRelPath) {
		tmp5 := NewWindowsLnkFile_StringData()
		err = tmp5.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		this.RelPath = tmp5
	}
	if (this.Header.Flags.HasWorkDir) {
		tmp6 := NewWindowsLnkFile_StringData()
		err = tmp6.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		this.WorkDir = tmp6
	}
	if (this.Header.Flags.HasArguments) {
		tmp7 := NewWindowsLnkFile_StringData()
		err = tmp7.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		this.Arguments = tmp7
	}
	if (this.Header.Flags.HasIconLocation) {
		tmp8 := NewWindowsLnkFile_StringData()
		err = tmp8.Read(this._io, this, this._root)
		if err != nil {
			return err
		}
		this.IconLocation = tmp8
	}
	return err
}

/**
 * @see <a href="https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-SHLLINK/[MS-SHLLINK].pdf">Section 2.1</a>
 */
type WindowsLnkFile_FileHeader struct {
	LenHeader []byte
	LinkClsid []byte
	Flags *WindowsLnkFile_LinkFlags
	FileAttrs uint32
	TimeCreation uint64
	TimeAccess uint64
	TimeWrite uint64
	TargetFileSize uint32
	IconIndex int32
	ShowCommand WindowsLnkFile_WindowState
	Hotkey uint16
	Reserved []byte
	_io *kaitai.Stream
	_root *WindowsLnkFile
	_parent *WindowsLnkFile
	_raw_Flags []byte
}
func NewWindowsLnkFile_FileHeader() *WindowsLnkFile_FileHeader {
	return &WindowsLnkFile_FileHeader{
	}
}

func (this WindowsLnkFile_FileHeader) IO_() *kaitai.Stream {
	return this._io
}

func (this *WindowsLnkFile_FileHeader) Read(io *kaitai.Stream, parent *WindowsLnkFile, root *WindowsLnkFile) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp9, err := this._io.ReadBytes(int(4))
	if err != nil {
		return err
	}
	tmp9 = tmp9
	this.LenHeader = tmp9
	if !(bytes.Equal(this.LenHeader, []uint8{76, 0, 0, 0})) {
		return kaitai.NewValidationNotEqualError([]uint8{76, 0, 0, 0}, this.LenHeader, this._io, "/types/file_header/seq/0")
	}
	tmp10, err := this._io.ReadBytes(int(16))
	if err != nil {
		return err
	}
	tmp10 = tmp10
	this.LinkClsid = tmp10
	if !(bytes.Equal(this.LinkClsid, []uint8{1, 20, 2, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 70})) {
		return kaitai.NewValidationNotEqualError([]uint8{1, 20, 2, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 70}, this.LinkClsid, this._io, "/types/file_header/seq/1")
	}
	tmp11, err := this._io.ReadBytes(int(4))
	if err != nil {
		return err
	}
	tmp11 = tmp11
	this._raw_Flags = tmp11
	_io__raw_Flags := kaitai.NewStream(bytes.NewReader(this._raw_Flags))
	tmp12 := NewWindowsLnkFile_LinkFlags()
	err = tmp12.Read(_io__raw_Flags, this, this._root)
	if err != nil {
		return err
	}
	this.Flags = tmp12
	tmp13, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.FileAttrs = uint32(tmp13)
	tmp14, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.TimeCreation = uint64(tmp14)
	tmp15, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.TimeAccess = uint64(tmp15)
	tmp16, err := this._io.ReadU8le()
	if err != nil {
		return err
	}
	this.TimeWrite = uint64(tmp16)
	tmp17, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.TargetFileSize = uint32(tmp17)
	tmp18, err := this._io.ReadS4le()
	if err != nil {
		return err
	}
	this.IconIndex = int32(tmp18)
	tmp19, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.ShowCommand = WindowsLnkFile_WindowState(tmp19)
	tmp20, err := this._io.ReadU2le()
	if err != nil {
		return err
	}
	this.Hotkey = uint16(tmp20)
	tmp21, err := this._io.ReadBytes(int(10))
	if err != nil {
		return err
	}
	tmp21 = tmp21
	this.Reserved = tmp21
	if !(bytes.Equal(this.Reserved, []uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0})) {
		return kaitai.NewValidationNotEqualError([]uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, this.Reserved, this._io, "/types/file_header/seq/11")
	}
	return err
}

/**
 * Technically, a size of the header, but in reality, it's
 * fixed by standard.
 */

/**
 * 16-byte class identified (CLSID), reserved for Windows shell
 * link files.
 */

/**
 * Lower 32 bits of the size of the file that this link targets
 */

/**
 * Index of an icon to use from target file
 */

/**
 * Window state to set after the launch of target executable
 */

/**
 * @see <a href="https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-SHLLINK/[MS-SHLLINK].pdf">Section 2.1.1</a>
 */
type WindowsLnkFile_LinkFlags struct {
	IsUnicode bool
	HasIconLocation bool
	HasArguments bool
	HasWorkDir bool
	HasRelPath bool
	HasName bool
	HasLinkInfo bool
	HasLinkTargetIdList bool
	_unnamed8 uint64
	Reserved uint64
	KeepLocalIdListForUncTarget bool
	_unnamed11 uint64
	_io *kaitai.Stream
	_root *WindowsLnkFile
	_parent *WindowsLnkFile_FileHeader
}
func NewWindowsLnkFile_LinkFlags() *WindowsLnkFile_LinkFlags {
	return &WindowsLnkFile_LinkFlags{
	}
}

func (this WindowsLnkFile_LinkFlags) IO_() *kaitai.Stream {
	return this._io
}

func (this *WindowsLnkFile_LinkFlags) Read(io *kaitai.Stream, parent *WindowsLnkFile_FileHeader, root *WindowsLnkFile) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp22, err := this._io.ReadBitsIntBe(1)
	if err != nil {
		return err
	}
	this.IsUnicode = tmp22 != 0
	tmp23, err := this._io.ReadBitsIntBe(1)
	if err != nil {
		return err
	}
	this.HasIconLocation = tmp23 != 0
	tmp24, err := this._io.ReadBitsIntBe(1)
	if err != nil {
		return err
	}
	this.HasArguments = tmp24 != 0
	tmp25, err := this._io.ReadBitsIntBe(1)
	if err != nil {
		return err
	}
	this.HasWorkDir = tmp25 != 0
	tmp26, err := this._io.ReadBitsIntBe(1)
	if err != nil {
		return err
	}
	this.HasRelPath = tmp26 != 0
	tmp27, err := this._io.ReadBitsIntBe(1)
	if err != nil {
		return err
	}
	this.HasName = tmp27 != 0
	tmp28, err := this._io.ReadBitsIntBe(1)
	if err != nil {
		return err
	}
	this.HasLinkInfo = tmp28 != 0
	tmp29, err := this._io.ReadBitsIntBe(1)
	if err != nil {
		return err
	}
	this.HasLinkTargetIdList = tmp29 != 0
	tmp30, err := this._io.ReadBitsIntBe(16)
	if err != nil {
		return err
	}
	this._unnamed8 = tmp30
	tmp31, err := this._io.ReadBitsIntBe(5)
	if err != nil {
		return err
	}
	this.Reserved = tmp31
	tmp32, err := this._io.ReadBitsIntBe(1)
	if err != nil {
		return err
	}
	this.KeepLocalIdListForUncTarget = tmp32 != 0
	tmp33, err := this._io.ReadBitsIntBe(2)
	if err != nil {
		return err
	}
	this._unnamed11 = tmp33
	return err
}

/**
 * @see <a href="https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-SHLLINK/[MS-SHLLINK].pdf">Section 2.3</a>
 */
type WindowsLnkFile_LinkInfo struct {
	LenAll uint32
	All *WindowsLnkFile_LinkInfo_All
	_io *kaitai.Stream
	_root *WindowsLnkFile
	_parent *WindowsLnkFile
	_raw_All []byte
}
func NewWindowsLnkFile_LinkInfo() *WindowsLnkFile_LinkInfo {
	return &WindowsLnkFile_LinkInfo{
	}
}

func (this WindowsLnkFile_LinkInfo) IO_() *kaitai.Stream {
	return this._io
}

func (this *WindowsLnkFile_LinkInfo) Read(io *kaitai.Stream, parent *WindowsLnkFile, root *WindowsLnkFile) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp34, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.LenAll = uint32(tmp34)
	tmp35, err := this._io.ReadBytes(int(this.LenAll - 4))
	if err != nil {
		return err
	}
	tmp35 = tmp35
	this._raw_All = tmp35
	_io__raw_All := kaitai.NewStream(bytes.NewReader(this._raw_All))
	tmp36 := NewWindowsLnkFile_LinkInfo_All()
	err = tmp36.Read(_io__raw_All, this, this._root)
	if err != nil {
		return err
	}
	this.All = tmp36
	return err
}

/**
 * @see <a href="https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-SHLLINK/[MS-SHLLINK].pdf">Section 2.3</a>
 */
type WindowsLnkFile_LinkInfo_All struct {
	LenHeader uint32
	Header *WindowsLnkFile_LinkInfo_Header
	_io *kaitai.Stream
	_root *WindowsLnkFile
	_parent *WindowsLnkFile_LinkInfo
	_raw_Header []byte
	_f_localBasePath bool
	localBasePath []byte
	_f_volumeId bool
	volumeId *WindowsLnkFile_LinkInfo_VolumeIdSpec
}
func NewWindowsLnkFile_LinkInfo_All() *WindowsLnkFile_LinkInfo_All {
	return &WindowsLnkFile_LinkInfo_All{
	}
}

func (this WindowsLnkFile_LinkInfo_All) IO_() *kaitai.Stream {
	return this._io
}

func (this *WindowsLnkFile_LinkInfo_All) Read(io *kaitai.Stream, parent *WindowsLnkFile_LinkInfo, root *WindowsLnkFile) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp37, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.LenHeader = uint32(tmp37)
	tmp38, err := this._io.ReadBytes(int(this.LenHeader - 8))
	if err != nil {
		return err
	}
	tmp38 = tmp38
	this._raw_Header = tmp38
	_io__raw_Header := kaitai.NewStream(bytes.NewReader(this._raw_Header))
	tmp39 := NewWindowsLnkFile_LinkInfo_Header()
	err = tmp39.Read(_io__raw_Header, this, this._root)
	if err != nil {
		return err
	}
	this.Header = tmp39
	return err
}
func (this *WindowsLnkFile_LinkInfo_All) LocalBasePath() (v []byte, err error) {
	if (this._f_localBasePath) {
		return this.localBasePath, nil
	}
	this._f_localBasePath = true
	if (this.Header.Flags.HasVolumeIdAndLocalBasePath) {
		_pos, err := this._io.Pos()
		if err != nil {
			return nil, err
		}
		_, err = this._io.Seek(int64(this.Header.OfsLocalBasePath - 4), io.SeekStart)
		if err != nil {
			return nil, err
		}
		tmp40, err := this._io.ReadBytesTerm(0, false, true, true)
		if err != nil {
			return nil, err
		}
		this.localBasePath = tmp40
		_, err = this._io.Seek(_pos, io.SeekStart)
		if err != nil {
			return nil, err
		}
	}
	return this.localBasePath, nil
}
func (this *WindowsLnkFile_LinkInfo_All) VolumeId() (v *WindowsLnkFile_LinkInfo_VolumeIdSpec, err error) {
	if (this._f_volumeId) {
		return this.volumeId, nil
	}
	this._f_volumeId = true
	if (this.Header.Flags.HasVolumeIdAndLocalBasePath) {
		_pos, err := this._io.Pos()
		if err != nil {
			return nil, err
		}
		_, err = this._io.Seek(int64(this.Header.OfsVolumeId - 4), io.SeekStart)
		if err != nil {
			return nil, err
		}
		tmp41 := NewWindowsLnkFile_LinkInfo_VolumeIdSpec()
		err = tmp41.Read(this._io, this, this._root)
		if err != nil {
			return nil, err
		}
		this.volumeId = tmp41
		_, err = this._io.Seek(_pos, io.SeekStart)
		if err != nil {
			return nil, err
		}
	}
	return this.volumeId, nil
}

/**
 * @see <a href="https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-SHLLINK/[MS-SHLLINK].pdf">Section 2.3</a>
 */
type WindowsLnkFile_LinkInfo_Header struct {
	Flags *WindowsLnkFile_LinkInfo_LinkInfoFlags
	OfsVolumeId uint32
	OfsLocalBasePath uint32
	OfsCommonNetRelLink uint32
	OfsCommonPathSuffix uint32
	OfsLocalBasePathUnicode uint32
	OfsCommonPathSuffixUnicode uint32
	_io *kaitai.Stream
	_root *WindowsLnkFile
	_parent *WindowsLnkFile_LinkInfo_All
}
func NewWindowsLnkFile_LinkInfo_Header() *WindowsLnkFile_LinkInfo_Header {
	return &WindowsLnkFile_LinkInfo_Header{
	}
}

func (this WindowsLnkFile_LinkInfo_Header) IO_() *kaitai.Stream {
	return this._io
}

func (this *WindowsLnkFile_LinkInfo_Header) Read(io *kaitai.Stream, parent *WindowsLnkFile_LinkInfo_All, root *WindowsLnkFile) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp42 := NewWindowsLnkFile_LinkInfo_LinkInfoFlags()
	err = tmp42.Read(this._io, this, this._root)
	if err != nil {
		return err
	}
	this.Flags = tmp42
	tmp43, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.OfsVolumeId = uint32(tmp43)
	tmp44, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.OfsLocalBasePath = uint32(tmp44)
	tmp45, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.OfsCommonNetRelLink = uint32(tmp45)
	tmp46, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.OfsCommonPathSuffix = uint32(tmp46)
	tmp47, err := this._io.EOF()
	if err != nil {
		return err
	}
	if (!(tmp47)) {
		tmp48, err := this._io.ReadU4le()
		if err != nil {
			return err
		}
		this.OfsLocalBasePathUnicode = uint32(tmp48)
	}
	tmp49, err := this._io.EOF()
	if err != nil {
		return err
	}
	if (!(tmp49)) {
		tmp50, err := this._io.ReadU4le()
		if err != nil {
			return err
		}
		this.OfsCommonPathSuffixUnicode = uint32(tmp50)
	}
	return err
}

/**
 * @see <a href="https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-SHLLINK/[MS-SHLLINK].pdf">Section 2.3</a>
 */
type WindowsLnkFile_LinkInfo_LinkInfoFlags struct {
	Reserved1 uint64
	HasCommonNetRelLink bool
	HasVolumeIdAndLocalBasePath bool
	Reserved2 uint64
	_io *kaitai.Stream
	_root *WindowsLnkFile
	_parent *WindowsLnkFile_LinkInfo_Header
}
func NewWindowsLnkFile_LinkInfo_LinkInfoFlags() *WindowsLnkFile_LinkInfo_LinkInfoFlags {
	return &WindowsLnkFile_LinkInfo_LinkInfoFlags{
	}
}

func (this WindowsLnkFile_LinkInfo_LinkInfoFlags) IO_() *kaitai.Stream {
	return this._io
}

func (this *WindowsLnkFile_LinkInfo_LinkInfoFlags) Read(io *kaitai.Stream, parent *WindowsLnkFile_LinkInfo_Header, root *WindowsLnkFile) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp51, err := this._io.ReadBitsIntBe(6)
	if err != nil {
		return err
	}
	this.Reserved1 = tmp51
	tmp52, err := this._io.ReadBitsIntBe(1)
	if err != nil {
		return err
	}
	this.HasCommonNetRelLink = tmp52 != 0
	tmp53, err := this._io.ReadBitsIntBe(1)
	if err != nil {
		return err
	}
	this.HasVolumeIdAndLocalBasePath = tmp53 != 0
	tmp54, err := this._io.ReadBitsIntBe(24)
	if err != nil {
		return err
	}
	this.Reserved2 = tmp54
	return err
}

/**
 * @see <a href="https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-SHLLINK/[MS-SHLLINK].pdf">Section 2.3.1</a>
 */
type WindowsLnkFile_LinkInfo_VolumeIdBody struct {
	DriveType WindowsLnkFile_DriveTypes
	DriveSerialNumber uint32
	OfsVolumeLabel uint32
	OfsVolumeLabelUnicode uint32
	_io *kaitai.Stream
	_root *WindowsLnkFile
	_parent *WindowsLnkFile_LinkInfo_VolumeIdSpec
	_f_isUnicode bool
	isUnicode bool
	_f_volumeLabelAnsi bool
	volumeLabelAnsi string
}
func NewWindowsLnkFile_LinkInfo_VolumeIdBody() *WindowsLnkFile_LinkInfo_VolumeIdBody {
	return &WindowsLnkFile_LinkInfo_VolumeIdBody{
	}
}

func (this WindowsLnkFile_LinkInfo_VolumeIdBody) IO_() *kaitai.Stream {
	return this._io
}

func (this *WindowsLnkFile_LinkInfo_VolumeIdBody) Read(io *kaitai.Stream, parent *WindowsLnkFile_LinkInfo_VolumeIdSpec, root *WindowsLnkFile) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp55, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.DriveType = WindowsLnkFile_DriveTypes(tmp55)
	tmp56, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.DriveSerialNumber = uint32(tmp56)
	tmp57, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.OfsVolumeLabel = uint32(tmp57)
	tmp58, err := this.IsUnicode()
	if err != nil {
		return err
	}
	if (tmp58) {
		tmp59, err := this._io.ReadU4le()
		if err != nil {
			return err
		}
		this.OfsVolumeLabelUnicode = uint32(tmp59)
	}
	return err
}
func (this *WindowsLnkFile_LinkInfo_VolumeIdBody) IsUnicode() (v bool, err error) {
	if (this._f_isUnicode) {
		return this.isUnicode, nil
	}
	this._f_isUnicode = true
	this.isUnicode = bool(this.OfsVolumeLabel == 20)
	return this.isUnicode, nil
}
func (this *WindowsLnkFile_LinkInfo_VolumeIdBody) VolumeLabelAnsi() (v string, err error) {
	if (this._f_volumeLabelAnsi) {
		return this.volumeLabelAnsi, nil
	}
	this._f_volumeLabelAnsi = true
	tmp60, err := this.IsUnicode()
	if err != nil {
		return "", err
	}
	if (!(tmp60)) {
		_pos, err := this._io.Pos()
		if err != nil {
			return "", err
		}
		_, err = this._io.Seek(int64(this.OfsVolumeLabel - 4), io.SeekStart)
		if err != nil {
			return "", err
		}
		tmp61, err := this._io.ReadBytesTerm(0, false, true, true)
		if err != nil {
			return "", err
		}
		tmp62, err := kaitai.BytesToStr(tmp61, charmap.CodePage437.NewDecoder())
		if err != nil {
			return "", err
		}
		this.volumeLabelAnsi = tmp62
		_, err = this._io.Seek(_pos, io.SeekStart)
		if err != nil {
			return "", err
		}
	}
	return this.volumeLabelAnsi, nil
}

/**
 * @see <a href="https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-SHLLINK/[MS-SHLLINK].pdf">Section 2.3.1</a>
 */
type WindowsLnkFile_LinkInfo_VolumeIdSpec struct {
	LenAll uint32
	Body *WindowsLnkFile_LinkInfo_VolumeIdBody
	_io *kaitai.Stream
	_root *WindowsLnkFile
	_parent *WindowsLnkFile_LinkInfo_All
	_raw_Body []byte
}
func NewWindowsLnkFile_LinkInfo_VolumeIdSpec() *WindowsLnkFile_LinkInfo_VolumeIdSpec {
	return &WindowsLnkFile_LinkInfo_VolumeIdSpec{
	}
}

func (this WindowsLnkFile_LinkInfo_VolumeIdSpec) IO_() *kaitai.Stream {
	return this._io
}

func (this *WindowsLnkFile_LinkInfo_VolumeIdSpec) Read(io *kaitai.Stream, parent *WindowsLnkFile_LinkInfo_All, root *WindowsLnkFile) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp63, err := this._io.ReadU4le()
	if err != nil {
		return err
	}
	this.LenAll = uint32(tmp63)
	tmp64, err := this._io.ReadBytes(int(this.LenAll - 4))
	if err != nil {
		return err
	}
	tmp64 = tmp64
	this._raw_Body = tmp64
	_io__raw_Body := kaitai.NewStream(bytes.NewReader(this._raw_Body))
	tmp65 := NewWindowsLnkFile_LinkInfo_VolumeIdBody()
	err = tmp65.Read(_io__raw_Body, this, this._root)
	if err != nil {
		return err
	}
	this.Body = tmp65
	return err
}

/**
 * @see <a href="https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-SHLLINK/[MS-SHLLINK].pdf">Section 2.2</a>
 */
type WindowsLnkFile_LinkTargetIdList struct {
	LenIdList uint16
	IdList *WindowsShellItems
	_io *kaitai.Stream
	_root *WindowsLnkFile
	_parent *WindowsLnkFile
	_raw_IdList []byte
}
func NewWindowsLnkFile_LinkTargetIdList() *WindowsLnkFile_LinkTargetIdList {
	return &WindowsLnkFile_LinkTargetIdList{
	}
}

func (this WindowsLnkFile_LinkTargetIdList) IO_() *kaitai.Stream {
	return this._io
}

func (this *WindowsLnkFile_LinkTargetIdList) Read(io *kaitai.Stream, parent *WindowsLnkFile, root *WindowsLnkFile) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp66, err := this._io.ReadU2le()
	if err != nil {
		return err
	}
	this.LenIdList = uint16(tmp66)
	tmp67, err := this._io.ReadBytes(int(this.LenIdList))
	if err != nil {
		return err
	}
	tmp67 = tmp67
	this._raw_IdList = tmp67
	_io__raw_IdList := kaitai.NewStream(bytes.NewReader(this._raw_IdList))
	tmp68 := NewWindowsShellItems()
	err = tmp68.Read(_io__raw_IdList, nil, nil)
	if err != nil {
		return err
	}
	this.IdList = tmp68
	return err
}
type WindowsLnkFile_StringData struct {
	CharsStr uint16
	Str string
	_io *kaitai.Stream
	_root *WindowsLnkFile
	_parent *WindowsLnkFile
}
func NewWindowsLnkFile_StringData() *WindowsLnkFile_StringData {
	return &WindowsLnkFile_StringData{
	}
}

func (this WindowsLnkFile_StringData) IO_() *kaitai.Stream {
	return this._io
}

func (this *WindowsLnkFile_StringData) Read(io *kaitai.Stream, parent *WindowsLnkFile, root *WindowsLnkFile) (err error) {
	this._io = io
	this._parent = parent
	this._root = root

	tmp69, err := this._io.ReadU2le()
	if err != nil {
		return err
	}
	this.CharsStr = uint16(tmp69)
	tmp70, err := this._io.ReadBytes(int(this.CharsStr * 2))
	if err != nil {
		return err
	}
	tmp70 = tmp70
	tmp71, err := kaitai.BytesToStr(tmp70, unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM).NewDecoder())
	if err != nil {
		return err
	}
	this.Str = tmp71
	return err
}