protected static FileInfoBaseStruct ReadFileInfoBaseStruct(byte[] buffer, int offset, out int nextOffset)
    {
        var fibs = new FileInfoBaseStruct
        {
            Length      = BitConverter.ToInt16(buffer, offset),
            ValueLength = BitConverter.ToInt16(buffer, offset + 2),
            Type        = BitConverter.ToInt16(buffer, offset + 4)
        };
        int len = FindLengthUnicodeSZ(buffer, offset + 6, offset + fibs.Length);

        fibs.Key = Encoding.Unicode.GetString(buffer, offset + 6, len * 2);
        // Padding
        fibs.ValueOffset = ((offset + 6 + (len + 1) * 2) + 3) & (~3);
        fibs.EndOffset   = offset + fibs.Length;
        nextOffset       = (fibs.EndOffset + 3) & (~3);
        return(fibs);
    }
    protected static IEnumerable <Tuple <uint, string, string> > ReadVersionInfoInternal(byte[] buffer, FileInfoBaseStruct fibs)
    {
        int sfiOrValOffset = (fibs.ValueOffset + fibs.ValueLength + 3) & (~3);

        while (sfiOrValOffset < fibs.Length)
        {
            int nextSfiOrValOffset;
            var sfiOrVal = ReadFileInfoBaseStruct(buffer, sfiOrValOffset, out nextSfiOrValOffset);
            if (sfiOrVal.Key == "StringFileInfo")
            {
                int stOffset = sfiOrVal.ValueOffset;
                while (stOffset < sfiOrVal.EndOffset)
                {
                    int  nextStOffset;
                    var  st          = ReadFileInfoBaseStruct(buffer, stOffset, out nextStOffset);
                    uint langCharset = uint.Parse(st.Key, NumberStyles.HexNumber);
                    int  striOffset  = st.ValueOffset;
                    while (striOffset < st.EndOffset)
                    {
                        int nextStriOffset;
                        var stri = ReadFileInfoBaseStruct(buffer, striOffset, out nextStriOffset);
                        // Here stri.ValueLength is in words!
                        int    len   = FindLengthUnicodeSZ(buffer, stri.ValueOffset, stri.ValueOffset + (stri.ValueLength * 2));
                        string value = Encoding.Unicode.GetString(buffer, stri.ValueOffset, len * 2);
                        yield return(Tuple.Create(langCharset, stri.Key, value));

                        striOffset = nextStriOffset;
                    }
                    stOffset = nextStOffset;
                }
            }
            else if (sfiOrVal.Key == "VarFileInfo")
            {
                int varOffset = sfiOrVal.ValueOffset;
                while (varOffset < sfiOrVal.EndOffset)
                {
                    int nextVarOffset;
                    var var = ReadFileInfoBaseStruct(buffer, varOffset, out nextVarOffset);
                    if (var.Key != "Translation")
                    {
                        throw new Exception(var.Key);
                    }
                    int langOffset = var.ValueOffset;
                    while (langOffset < var.EndOffset)
                    {
                        unchecked
                        {
                            // We invert the order suggested by the Var description!
                            uint high = (uint)BitConverter.ToInt16(buffer, langOffset);
                            uint low  = (uint)BitConverter.ToInt16(buffer, langOffset + 2);
                            uint lang = (high << 16) | low;
                            langOffset += 4;
                        }
                    }
                    varOffset = nextVarOffset;
                }
            }
            else
            {
                Debug.WriteLine("Unrecognized " + sfiOrVal.Key);
            }
            sfiOrValOffset = nextSfiOrValOffset;
        }
    }