public static MenuOrderRecord Deserialize(Stream stream) { MenuOrderRecord result = new MenuOrderRecord(); BinaryReader br = new BinaryReader(stream); long recordPosition = stream.Position; UInt32 lengthOfRecord = br.ReadUInt32(); try { result.Order = br.ReadInt32(); UInt16 subRecord0Size = br.ReadUInt16(); UInt16 flags = br.ReadUInt16(); result.RecordType = ((flags & 2) == 2) ? FavoritesNodeType.Url : FavoritesNodeType.Folder; bool isUnicode = ((flags & 4) == 4); UInt32 unknown1 = br.ReadUInt32(); UInt32 unknown2 = br.ReadUInt32(); UInt16 stringLengthOrFlags = br.ReadUInt16(); result.Name83 = Utilities.ReadZeroTerminatedString(stream, isUnicode ? Encoding.Unicode : Encoding.ASCII); if ((stream.Position & 1) > 0) { stream.Position++; } // jump to the position of the subRecord1Index word stream.Position = recordPosition + lengthOfRecord - 8; UInt32 subRecord1Index = br.ReadUInt16(); // index to subrecord1, which is where the long name is // calculate position of subRecord1 stream.Position = recordPosition + 8 + subRecord1Index; // read subrecord1 size UInt16 subRecord1Size = br.ReadUInt16(); // skip 18 bytes on xp, 36 bytes on vista if (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor > 0) { stream.Position += 18; } else { stream.Position += 36; } result.LongName = Utilities.ReadZeroTerminatedString(stream, Encoding.Unicode); result.DisplayName = result.LongName; if ((stringLengthOrFlags & 1) == 1) { string resourceString = Utilities.GetStringResource(Utilities.ReadZeroTerminatedString(stream, Encoding.Unicode)); if (resourceString != null && resourceString != "") { result.DisplayName = resourceString; } } // validate the record by checking if the subrecord sizes add up if ((subRecord1Size + subRecord1Index) != subRecord0Size) { throw new Exception("Invalid record format"); } //Console.WriteLine(""); //Console.WriteLine("flags : {0:x}", flags); //Console.WriteLine("flags2 : {0:x}", stringLengthOrFlags); //Console.WriteLine("longname : {0}", result.LongName); //Console.WriteLine("name83 : {0}", result.Name83); //Console.WriteLine("longname : {0}", result.LongName); } finally { stream.Seek(recordPosition + lengthOfRecord, SeekOrigin.Begin); } return(result); }
private static FavoritesNode LoadFolderNodeFromRegistry(FavoritesNode parent, string dirName, string displayName, RegistryKey registryKey, int order) { FavoritesNode result = new FavoritesNode(); result.parent = parent; result.order = order; result.displayName = displayName; result.systemName = dirName; result.nodeType = FavoritesNodeType.Folder; byte[] registryData = registryKey.GetValue("Order") as byte[]; if (registryData != null) { MemoryStream ms = new MemoryStream(registryData); BinaryReader br = new BinaryReader(ms); UInt32 headerId0 = br.ReadUInt32(); UInt32 headerId1 = br.ReadUInt32(); UInt32 totalSize = br.ReadUInt32(); UInt32 headerId2 = br.ReadUInt32(); UInt32 numberOfRecords = br.ReadUInt32(); if (headerId0 == 0x00000008 && headerId1 == 0x00000002 && headerId2 == 0x00000001) { //Console.WriteLine("================="); //Console.WriteLine("headerId0 : {0:x}", headerId0); //Console.WriteLine("headerId1 : {0:x}", headerId1); //Console.WriteLine("totalSize : {0:x}", totalSize); //Console.WriteLine("headerId2 : {0:x}", headerId2); //Console.WriteLine("numberOfRecords : {0:x}", numberOfRecords); for (uint t = 0; t < numberOfRecords; t++) { try { FavoritesNode childNode = null; MenuOrderRecord record = MenuOrderRecord.Deserialize(br.BaseStream); if (record.RecordType == FavoritesNodeType.Folder) { // apparently in the registry it always uses the display name RegistryKey childKey = registryKey.OpenSubKey(record.DisplayName); if (childKey != null) { childNode = LoadFolderNodeFromRegistry(result, record.LongName, record.DisplayName, childKey, record.Order); childKey.Close(); } else { childNode = LoadFolderNodeFromFileSystem(result, record.LongName, record.DisplayName, record.Order); } } else { childNode = FavoritesNode.LoadURLNodeFromFileSystem(result, Path.GetFileNameWithoutExtension(record.LongName), record.Order); } result.children.Add(childNode); } catch { } } result.children.Sort( delegate(FavoritesNode a, FavoritesNode b) { if (a.order < 0 && b.order < 0) { // both items are unordered.. sort the items according to their name return(string.Compare(a.displayName, b.displayName)); } else if (a.order < 0 || b.order < 0) { // one of the items is unordered. The negative one should go after the positive one. return(b.order - a.order); } // both items are ordered, sort normally return(a.order - b.order); } ); } } return(result); }