private static string GetKey(VersionItemMode mode, BinaryReader rdr, out VersionItemMode newMode) { newMode = mode; // these strings are null-terminated var retval = rdr.ReadSZString(); if (mode != VersionItemMode.StringFileInfoOrVarFileInfo) { return(retval); } switch (retval) { case "StringFileInfo": newMode = VersionItemMode.StringFileInfo; break; case "VarFileInfo": newMode = VersionItemMode.VarFileInfo; break; default: throw new ResourceDataException("Invalid Key Name"); } return(retval); }
private static VersionItemMode GetNextMode(VersionItemMode mode) { switch (mode) { case VersionItemMode.Root: return(VersionItemMode.StringFileInfoOrVarFileInfo); case VersionItemMode.StringFileInfo: return(VersionItemMode.StringTable); case VersionItemMode.StringTable: return(VersionItemMode.String); case VersionItemMode.String: return(VersionItemMode.None); case VersionItemMode.VarFileInfo: return(VersionItemMode.Var); case VersionItemMode.Var: return(VersionItemMode.None); default: throw new ResourceDataException("GetNextMode, invalid mode"); } }
private VersionItem GetFirstItem(VersionItem parent, VersionItemMode mode) { if (parent.Mode == mode) { return(parent); } foreach (var item in parent.Children) { if (item.Mode == mode) { return(item); } var match = GetFirstItem(item, mode); if (match != null) { return(match); } } return(null); }
private static VersionItem RecurseItem(VersionItemMode mode, BinaryReader rdr) { Int64 initPos = rdr.BaseStream.Position; VersionItem item = new VersionItem(mode); item.Length = rdr.ReadUInt16(); item.ValueLength = rdr.ReadUInt16(); item.Type = rdr.ReadUInt16(); item.Key = GetKey(mode, rdr, out item._mode); rdr.Align4(); mode = item.Mode; List <VersionItem> children = new List <VersionItem>(); while (rdr.BaseStream.Position < initPos + item.Length) { switch (mode) { case Mode.Root: if (item.Value == null) { Byte[] ffiBytes = rdr.ReadBytes(item.ValueLength); // this is where FixedFileInfo goes /*Byte[] padding2 = */ rdr.Align4(); if (ffiBytes.Length >= 52) // 52 == 0x34 { VSFixedFileInfo ffi = new VSFixedFileInfo(ffiBytes); if (ffi.Signature != 0xFEEF04BD) { throw new InvalidOperationException("Unrecognised VS_VERSIONINFO Signature"); } Dictionary <String, String> ffiDict = FfiToDict(ffi); item.Value = ffiDict; } else { throw new InvalidOperationException("Unexpected VS_FIXEDFILEINFO length"); } } goto default; case Mode.String: Byte[] bytes = rdr.ReadBytes(item.ValueLength * 2); String s = Encoding.Unicode.GetString(bytes.SubArray(0, bytes.Length - 2)); // miss out the null terminator item.Value = s; break; case Mode.Var: Byte[] data = rdr.ReadBytes(item.ValueLength); // wValueLength = size in bytes item.Value = data; // data is a DWORD array indicating the language and code page combinations supported by this file. // The low-order word of each DWORD must contain a Microsoft language identifier, and the high-order word must contain the IBM code page number. // Either high-order or low-order word can be zero, indicating that the file is language or code page independent. // ms-help://MS.MSDNQTR.v90.en/winui/winui/windowsuserinterface/resources/versioninformation/versioninformationreference/versioninformationstructures/var.htm break; default: VersionItem child = RecurseItem(GetNextMode(mode), rdr); children.Add(child); break; } // the reader was corrupted before entering the third String of the first StringTable of the StringFileInfo // so let's see if padding here helps rdr.Align4(); } rdr.Align4(); item.Children = children.ToArray(); return(item); }
internal VersionItem(VersionItemMode mode) { _mode = mode; }