private ShellLink(byte[] bytes, FileRecord record)
        {
            Path = record.FullName;

            HeaderSize = BitConverter.ToInt32(bytes, 0x00);

            if (HeaderSize == 0x4C)
            {
                #region SHELL_LINK_HEADER

                LinkCLSID = new Guid(NativeMethods.GetSubArray(bytes, 0x04, 0x10));
                LinkFlags = (LINK_FLAGS)BitConverter.ToUInt32(bytes, 0x14);
                FileAttributes = (FILEATTRIBUTE_FLAGS)BitConverter.ToUInt32(bytes, 0x18);
                CreationTime = DateTime.FromFileTimeUtc(BitConverter.ToInt64(bytes, 0x1C));
                AccessTime = DateTime.FromFileTimeUtc(BitConverter.ToInt64(bytes, 0x24));
                WriteTime = DateTime.FromFileTimeUtc(BitConverter.ToInt64(bytes, 0x2C));
                FileSize = BitConverter.ToUInt32(bytes, 0x34);
                IconIndex = BitConverter.ToInt32(bytes, 0x38);
                ShowCommand = (SHOWCOMMAND)BitConverter.ToUInt32(bytes, 0x3C);
                #region HotKey
                HotKey = new HOTKEY_FLAGS[2];
                HotKey[0] = (HOTKEY_FLAGS)bytes[0x40];
                HotKey[1] = (HOTKEY_FLAGS)bytes[0x41];
                #endregion HotKey

                int offset = 0x4C;

                #endregion SHELL_LINK_HEADER

                // I want to remove one layer of objects
                #region LINKTARGET_IDLIST

                if ((LinkFlags & LINK_FLAGS.HasLinkTargetIdList) == LINK_FLAGS.HasLinkTargetIdList)
                {
                    IdListSize = BitConverter.ToUInt16(bytes, offset);
                    IdList = new IdList(bytes, offset + 0x02, IdListSize);

                    offset += IdListSize + 0x02;
                }

                #endregion LINKTARGET_IDLIST

                #region LINKINFO

                if ((LinkFlags & LINK_FLAGS.HasLinkInfo) == LINK_FLAGS.HasLinkInfo)
                {
                    LinkInfoSize = BitConverter.ToUInt32(bytes, offset);
                    LinkInfoHeaderSize = BitConverter.ToUInt32(bytes, offset + 0x04);
                    LinkInfoFlags = (LINKINFO_FLAGS)BitConverter.ToUInt32(bytes, offset + 0x08);

                    if ((LinkInfoFlags & LINKINFO_FLAGS.VolumeIDAndLocalBasePath) == LINKINFO_FLAGS.VolumeIDAndLocalBasePath)
                    {
                        VolumeIdOffset = BitConverter.ToUInt32(bytes, offset + 0x0C);
                        VolumeId = new VolumeId(bytes, offset + (int)VolumeIdOffset);

                        LocalBasePathOffset = BitConverter.ToUInt32(bytes, offset + 0x10);
                        LocalBasePath = Encoding.Default.GetString(bytes, offset + (int)LocalBasePathOffset, (int)LinkInfoSize - (int)LocalBasePathOffset).Split('\0')[0];
                    }

                    if ((LinkInfoFlags & LINKINFO_FLAGS.CommonNetworkRelativeLinkAndPathSuffix) == LINKINFO_FLAGS.CommonNetworkRelativeLinkAndPathSuffix)
                    {
                        CommonNetworkRelativeLinkOffset = BitConverter.ToUInt32(bytes, offset + 0x14);
                        CommonNetworkRelativeLink = new CommonNetworkRelativeLink(bytes, offset + (int)CommonNetworkRelativeLinkOffset);

                        CommonPathSuffixOffset = BitConverter.ToUInt32(bytes, offset + 0x18);
                        CommonPathSuffix = Encoding.Default.GetString(bytes, offset + (int)CommonPathSuffixOffset, (int)LinkInfoSize - (int)CommonPathSuffixOffset).Split('\0')[0];
                    }

                    if (LinkInfoHeaderSize >= 0x24)
                    {
                        LocalBasePathOffsetUnicode = BitConverter.ToUInt32(bytes, offset + 0x1C);
                        LocalBasePathUnicode = Encoding.Unicode.GetString(bytes, offset + (int)LocalBasePathOffsetUnicode, (int)LinkInfoSize - (int)LocalBasePathOffsetUnicode).Split('\0')[0];

                        CommonPathSuffixOffsetUnicode = BitConverter.ToUInt32(bytes, offset + 0x20);
                        CommonPathSuffixUnicode = Encoding.Unicode.GetString(bytes, offset + (int)CommonPathSuffixOffsetUnicode, (int)LinkInfoSize - (int)CommonPathSuffixOffsetUnicode).Split('\0')[0];
                    }

                    offset += (int)LinkInfoSize;
                }

                #endregion LINKINFO

                #region STRING_DATA

                if ((LinkFlags & LINK_FLAGS.HasName) == LINK_FLAGS.HasName)
                {
                    NameSize = BitConverter.ToUInt16(bytes, offset);
                    Name = Encoding.Unicode.GetString(bytes, offset + 0x02, NameSize * 2);

                    offset += 2 + (NameSize * 2);
                }
                if ((LinkFlags & LINK_FLAGS.HasRelativePath) == LINK_FLAGS.HasRelativePath)
                {
                    RelativePathSize = BitConverter.ToUInt16(bytes, offset);
                    RelativePath = Encoding.Unicode.GetString(bytes, offset + 0x02, RelativePathSize * 2);

                    offset += 2 + (RelativePathSize * 2);
                }
                if ((LinkFlags & LINK_FLAGS.HasWorkingDir) == LINK_FLAGS.HasWorkingDir)
                {
                    WorkingDirectorySize = BitConverter.ToUInt16(bytes, offset);
                    WorkingDirectory = Encoding.Unicode.GetString(bytes, offset + 0x02, WorkingDirectorySize * 2);

                    offset += 2 + (WorkingDirectorySize * 2);
                }
                if ((LinkFlags & LINK_FLAGS.HasArguments) == LINK_FLAGS.HasArguments)
                {
                    CommandLineArgumentsSize = BitConverter.ToUInt16(bytes, offset);
                    CommandLineArguments = Encoding.Unicode.GetString(bytes, offset + 0x02, CommandLineArgumentsSize * 2);

                    offset += 2 + (CommandLineArgumentsSize * 2);
                }
                if ((LinkFlags & LINK_FLAGS.HasIconLocation) == LINK_FLAGS.HasIconLocation)
                {
                    IconLocationSize = BitConverter.ToUInt16(bytes, offset);
                    IconLocation = Encoding.Unicode.GetString(bytes, offset + 0x02, IconLocationSize * 2);

                    offset += 2 + (IconLocationSize * 2);
                }

                #endregion STRING_DATA

                #region EXTRA_DATA

                List<ExtraData> edList = new List<ExtraData>();

                int datalength = 0;

                do
                {
                    datalength = BitConverter.ToInt32(bytes, offset);

                    switch (BitConverter.ToUInt32(bytes, offset + 0x04))
                    {
                        case 0xA0000001:
                            edList.Add(new EnvironmentVariableDataBlock(bytes, offset));
                            break;
                        case 0xA0000002:
                            edList.Add(new ConsoleDataBlock(bytes, offset));
                            break;
                        case 0xA0000003:
                            edList.Add(new TrackerDataBlock(bytes, offset));
                            break;
                        case 0xA0000004:
                            edList.Add(new ConsoleFeDataBlock(bytes, offset));
                            break;
                        case 0xA0000005:
                            edList.Add(new SpecialFolderDataBlock(bytes, offset));
                            break;
                        case 0xA0000006:
                            edList.Add(new DarwinDataBlock(bytes, offset));
                            break;
                        case 0xA0000007:
                            edList.Add(new IconEnvironmentDataBlock(bytes, offset));
                            break;
                        case 0xA0000008:
                            edList.Add(new ShimDataBlock(bytes, offset));
                            break;
                        case 0xA0000009:
                            edList.Add(new PropertyStoreDataBlock(bytes, offset));
                            break;
                        case 0xA000000B:
                            edList.Add(new KnownFolderDataBlock(bytes, offset));
                            break;
                        case 0xA000000C:
                            edList.Add(new VistaAndAboveIDListDataBlock(bytes, offset));
                            break;
                    }

                    offset += datalength;

                } while (offset < bytes.Length - 0x04);

                ExtraData = edList.ToArray();

                #endregion EXTRA_DATA
            }
            else
            {
                throw new Exception("Invalid ShellLink Header.");
            }
        }