/// <summary> /// Resets the Stream position to the beginning and clears the fields /// </summary> private void Reset() { Stream.Seek(0, SeekOrigin.Begin); ShellLinkHeader = new Structs.ShellLinkHeader(); LinkTargetIdList = new Structs.LinkTargetIDList(); LinkInfo = new Structs.LinkInfo(); StringData = new Structs.StringData(); }
/// <summary> /// Parses the LinkInfo /// </summary> /// <exception cref="LinkInfoException">Thrown if LinkInfo is not proper</exception> private void ParseLinkInfo() { LinkInfo = new Structs.LinkInfo { Header = Stream.ReadStruct <Structs.LinkInfoHeader>() }; if (LinkInfo.Header.HeaderSize >= 0x24) { LinkInfo.HeaderOptional = Stream.ReadStruct <Structs.LinkInfoHeaderOptional>(); } else { if (LinkInfo.Header.HeaderSize != 0x1C) { throw new LinkInfoException("LinkInfo.HeaderSize must be 0x1C", nameof(LinkInfo.Header.HeaderSize)); } } // Subtract all offsets that start at the beginning of LinkInfo from this var startOffset = LinkInfo.Header.HeaderSize; var linkInfoBody = new byte[LinkInfo.Header.Size - startOffset]; Stream.Read(linkInfoBody, 0, linkInfoBody.Length); var pinnedBuffer = linkInfoBody.GetGCHandle(); if (LinkInfo.Header.Flags.HasFlag(Enums.LinkInfoFlags.VolumeIdAndLocalBasePath)) { LinkInfo.VolumeId = new Structs.LinkInfoVolumeId { Header = pinnedBuffer.ReadStruct <Structs.LinkInfoVolumeIdHeader>(LinkInfo.Header.VolumeIdOffset - startOffset) }; if (LinkInfo.VolumeId.Header.Size <= 0x10) { throw new LinkInfoException("LinkInfo.VolumeId.Header.Size is not greater than 0x10", nameof(LinkInfo.VolumeId.Header.Size)); } if (LinkInfo.VolumeId.Header.VolumeLabelOffset >= LinkInfo.VolumeId.Header.Size) { throw new LinkInfoException( "LinkInfo.VolumeId.Header.VolumeLabelOffset is not less than LinkInfo.VolumeId.Header.Size", nameof(LinkInfo.VolumeId.Header.VolumeLabelOffset)); } if (LinkInfo.VolumeId.VolumeLabelOffsetUnicode >= LinkInfo.VolumeId.Header.Size) { throw new LinkInfoException( "LinkInfo.VolumeId.VolumeLabelOffsetUnicode is not less than LinkInfo.VolumeId.Header.Size", nameof(LinkInfo.VolumeId.VolumeLabelOffsetUnicode)); } if (LinkInfo.VolumeId.Header.VolumeLabelOffset == 0x14) { LinkInfo.VolumeId.VolumeLabelOffsetUnicode = pinnedBuffer.ReadStruct <uint>( (uint)Marshal.OffsetOf <Structs.LinkInfoVolumeId>("VolumeLabelOffsetUnicode")); } if (LinkInfo.VolumeId.VolumeLabelOffsetUnicode > 0) { LinkInfo.VolumeId.Data = Marshal.PtrToStringUni(IntPtr.Add(pinnedBuffer.AddrOfPinnedObject(), (int)LinkInfo.VolumeId.VolumeLabelOffsetUnicode)); } else { LinkInfo.VolumeId.Data = Marshal.PtrToStringAnsi(IntPtr.Add(pinnedBuffer.AddrOfPinnedObject(), (int)LinkInfo.VolumeId.Header.VolumeLabelOffset)); } if (LinkInfo.HeaderOptional.LocalBasePathOffsetUnicode > 0) { LinkInfo.LocalBasePath = Marshal.PtrToStringUni(IntPtr.Add(pinnedBuffer.AddrOfPinnedObject(), (int)(LinkInfo.HeaderOptional.LocalBasePathOffsetUnicode - startOffset))); } else { LinkInfo.LocalBasePath = Marshal.PtrToStringAnsi(IntPtr.Add(pinnedBuffer.AddrOfPinnedObject(), (int)(LinkInfo.Header.LocalBasePathOffset - startOffset))); } if (LinkInfo.HeaderOptional.CommonPathSuffixOffsetUnicode > 0) { LinkInfo.CommonPathSuffix = Marshal.PtrToStringUni(IntPtr.Add(pinnedBuffer.AddrOfPinnedObject(), (int)(LinkInfo.HeaderOptional.CommonPathSuffixOffsetUnicode - startOffset))); } else { LinkInfo.CommonPathSuffix = Marshal.PtrToStringAnsi(IntPtr.Add(pinnedBuffer.AddrOfPinnedObject(), (int)(LinkInfo.Header.CommonPathSuffixOffset - startOffset))); } } if (LinkInfo.Header.Flags.HasFlag(Enums.LinkInfoFlags.CommonNetworkRelativeLinkAndPathSuffix)) { var commonNetworkRelativeLinkStartOffset = LinkInfo.Header.CommonNetworkRelativeLinkOffset - startOffset; LinkInfo.CommonNetworkRelativeLink.Header = pinnedBuffer.ReadStruct <Structs.CommonNetworkRelativeLinkHeader>( commonNetworkRelativeLinkStartOffset); if (LinkInfo.CommonNetworkRelativeLink.Header.Size < 0x14) { throw new LinkInfoException("LinkInfo.CommonNetworkRelativeLink.Header.Size is less than 0x14", nameof(LinkInfo.CommonNetworkRelativeLink.Header.Size)); } LinkInfo.CommonNetworkRelativeLink.NetName = Marshal.PtrToStringAnsi(IntPtr.Add(pinnedBuffer.AddrOfPinnedObject(), (int)(commonNetworkRelativeLinkStartOffset + LinkInfo.CommonNetworkRelativeLink.Header.NetNameOffset))); if (LinkInfo.CommonNetworkRelativeLink.Header.NetNameOffset > 0x14) { LinkInfo.CommonNetworkRelativeLink.HeaderOptional = pinnedBuffer.ReadStruct <Structs.CommonNetworkRelativeLinkHeaderOptional>( (uint) (commonNetworkRelativeLinkStartOffset + Marshal.SizeOf <Structs.CommonNetworkRelativeLinkHeader>())); LinkInfo.CommonNetworkRelativeLink.NetNameUnicode = Marshal.PtrToStringUni(IntPtr.Add(pinnedBuffer.AddrOfPinnedObject(), (int)(commonNetworkRelativeLinkStartOffset + LinkInfo.CommonNetworkRelativeLink.HeaderOptional.NetNameOffsetUnicode))); if (LinkInfo.CommonNetworkRelativeLink.HeaderOptional.DeviceNameOffsetUnicode > 0) { LinkInfo.CommonNetworkRelativeLink.DeviceNameUnicode = Marshal.PtrToStringUni(IntPtr.Add(pinnedBuffer.AddrOfPinnedObject(), (int)(commonNetworkRelativeLinkStartOffset + LinkInfo.CommonNetworkRelativeLink.HeaderOptional.DeviceNameOffsetUnicode))); } } if ( LinkInfo.CommonNetworkRelativeLink.Header.Flags.HasFlag( Enums.CommonNetworkRelativeLinkFlags.ValidDevice)) { if (LinkInfo.CommonNetworkRelativeLink.Header.DeviceNameOffset == 0) { throw new LinkInfoException( "ValidDevice flag cannot be set when LinkInfo.CommonNetworkRelativeLink.Header.DeviceNameOffset is equal to 0", nameof(LinkInfo.CommonNetworkRelativeLink.Header.DeviceNameOffset)); } LinkInfo.CommonNetworkRelativeLink.DeviceName = Marshal.PtrToStringAnsi(IntPtr.Add(pinnedBuffer.AddrOfPinnedObject(), (int)(commonNetworkRelativeLinkStartOffset + LinkInfo.CommonNetworkRelativeLink.Header.DeviceNameOffset))); } else { if (LinkInfo.CommonNetworkRelativeLink.Header.DeviceNameOffset > 0) { throw new LinkInfoException( "LinkInfo.CommonNetworkRelativeLink.Header.DeviceNameOffset must be 0 if ValidDevice flag is not set", nameof(LinkInfo.CommonNetworkRelativeLink.Header.DeviceNameOffset)); } } if ( LinkInfo.CommonNetworkRelativeLink.Header.Flags.HasFlag( Enums.CommonNetworkRelativeLinkFlags.ValidNetType)) { if ( !Enum.IsDefined(typeof(Enums.NetworkProviderType), LinkInfo.CommonNetworkRelativeLink.Header.NetProviderType)) { throw new LinkInfoException("Valid NetProviderType must be set if ValidNetType flag is set", nameof(LinkInfo.CommonNetworkRelativeLink.Header.NetProviderType)); } } else { if (LinkInfo.CommonNetworkRelativeLink.Header.NetProviderType != 0) { throw new LinkInfoException( "LinkInfo.CommonNetworkRelativeLink.Header.NetProviderType must be 0 if ValidNetType flag is set", nameof(LinkInfo.CommonNetworkRelativeLink.Header.NetProviderType)); } } } pinnedBuffer.Free(); }