/// <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();
        }
Beispiel #2
0
        /// <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();
        }