public ShellBagCDBurn(byte[] rawBytes) { ShortName = string.Empty; PropertyStore = new PropertyStore(); ExtensionBlocks = new List <IExtensionBlock>(); FriendlyName = "CDBurn"; var index = 8; //reset index to after signature index += 4; //skip 4 unknown index += 4; //skip 4 unknown index += 4; //skip 4 unknown var chunks = new List <byte[]>(); while (index < rawBytes.Length) { var subshellitemdatasize = BitConverter.ToInt16(rawBytes, index); index += 2; if (subshellitemdatasize <= 0) { break; } if (subshellitemdatasize == 1) { //some kind of separator index += 2; } else { chunks.Add(rawBytes.Skip(index).Take(subshellitemdatasize).ToArray()); index += subshellitemdatasize; } } var oldIndex = index; //if (chunks.Count != 2) //{ // Debug.WriteLine(chunks.Count); //} foreach (var bytes in chunks) { index = 0; var typeIndicator = bytes[index]; index += 1; index += 1; //skip unknown empty value var filesize = BitConverter.ToInt32(rawBytes, index); index += 4; FileSize = filesize; var modDate = Utils.ExtractDateTimeOffsetFromBytes(bytes.Skip(index).Take(4).ToArray()); LastModificationTime = modDate; index += 4; index += 2; //skip 2 bytes for file attributes var len = 0; var shortName = string.Empty; //get position of beef0004 var beefPos = BitConverter.ToString(bytes).IndexOf("04-00-EF-BE", StringComparison.InvariantCulture) / 3; beefPos = beefPos - 4; //add header back for beef var strLen = beefPos - index; if (typeIndicator == 0x35) { //unicode var tempString = Encoding.Unicode.GetString(bytes, index, strLen - 2); shortName = tempString; index += strLen; } else { //ascii while (bytes[index + len] != 0x0) { len += 1; } var tempBytes = new byte[len]; Array.Copy(bytes, index, tempBytes, 0, len); index += len; shortName = Encoding.ASCII.GetString(tempBytes); } ShortName = shortName; while (bytes[index] == 0x0) { index += 1; } var extsize = BitConverter.ToInt16(bytes, index); var signature = BitConverter.ToUInt32(bytes, index + 4); //TODO does this need to check if its a 0xbeef?? regex? var block = Utils.GetExtensionBlockFromBytes(signature, bytes.Skip(index).ToArray()); ExtensionBlocks.Add(block); var beef0004 = block as Beef0004; if (beef0004 != null) { CreatedOnTime = beef0004.CreatedOnTime; LastAccessTime = beef0004.LastAccessTime; Value = beef0004.LongName; } else { Value = "!!! Unable to determine Value !!!"; } } if (oldIndex + 5 < rawBytes.Length) { index = oldIndex + 2; _extraBag = new ShellBag0X31(rawBytes.Skip(index).ToArray()); foreach (var ex in _extraBag.ExtensionBlocks) { ExtensionBlocks.Add(new BeefPlaceHolder(null)); } } }
public void ProcessValues(RegistryKey key) { _values.Clear(); Errors.Clear(); var valuesList = new List <ValuesOut>(); var vn = string.Empty; try { var fav = key.Values.SingleOrDefault(t => t.ValueName == "Favorites"); if (fav == null) { return; } var br = new BinaryReader(new MemoryStream(fav.ValueDataRaw)); var chunks = new List <byte[]>(); var shellItems = new List <byte[]>(); var unk = br.ReadByte(); // while (br.BaseStream.Position < br.BaseStream.Length) { var size = br.ReadInt32(); br.BaseStream.Seek(-4, SeekOrigin.Current); var b = br.ReadBytes(size); chunks.Add(b); var marker = br.ReadBytes(5); } foreach (var chunk in chunks) { var chunkstream = new BinaryReader(new MemoryStream(chunk)); var chunksize = chunkstream.ReadInt32(); while (chunkstream.BaseStream.Position < chunkstream.BaseStream.Length) { var siSize = chunkstream.ReadInt16(); chunkstream.BaseStream.Seek(-2, SeekOrigin.Current); var siBytes = chunkstream.ReadBytes(siSize); shellItems.Add(siBytes); } } var det = new StringBuilder(); bags = new List <ShellBag>(); ShellBag bag = null; foreach (var bytese in shellItems) { try { switch (bytese[2]) { case 0x00: bag = new ShellBag0X00(bytese); break; case 0x1f: bag = new ShellBag0X1F(bytese); break; case 0x2f: bag = new ShellBag0X2F(bytese); break; case 0x2e: bag = new ShellBag0X2E(bytese); break; case 0xb1: case 0x31: case 0x35: case 0x36: bag = new ShellItems.ShellBag0X31(bytese); break; case 0x32: bag = new ShellBag0X32(bytese); break; case 0x3a: bag = new ShellBag0X3A(bytese); break; case 0x71: bag = new ShellBag0X71(bytese); break; case 0x74: bag = new ShellBag0X74(bytese); break; case 0x40: bag = new ShellBag0X40(bytese); break; case 0x61: bag = new ShellBag0X61(bytese); break; case 0xc3: bag = new ShellBag0Xc3(bytese); break; default: det.AppendLine( $"Key: {key.KeyName}, Value name: {fav.ValueName}, Message: **** Unsupported ShellID: 0x{bytese[2]:x2}. Send this ID to [email protected] so support can be added!! ****"); Errors.Add( $"Key: {key.KeyName}, Value name: {fav.ValueName}, Message: **** Unsupported ShellID: 0x{bytese[2]:x2}. Send this ID to [email protected] so support can be added!! ****"); break; } } catch (Exception e) { Errors.Add($"Error processing Favorites value '{vn}': {e.Message}"); } if (bag != null) { det.AppendLine(bag.ToString()); bags.Add(bag); } } foreach (var shellBag in bags) { var exe = "(unknown)"; var ed = shellBag.ExtensionBlocks.SingleOrDefault(t => t is ExtensionBlocks.Beef001d); if (ed != null) { exe = ((Beef001d)ed).Executable; } var pp = shellBag.ExtensionBlocks.SingleOrDefault(t => t is Beef001e); var pt = "(unknown)"; if (pp != null) { pt = ((Beef001e)pp).PinType; } if (shellBag.FriendlyName == "Directory") { exe = "(Directory)"; pt = "(Directory)"; } var v = new ValuesOut(shellBag.Value, exe, pt); v.BatchKeyPath = key.KeyPath; v.BatchValueName = fav.ValueName; valuesList.Add(v); } } catch (Exception ex) { Errors.Add($"Error processing Favorites value '{vn}': {ex.Message}"); } if (Errors.Count > 0) { AlertMessage = "Errors detected. See Errors information in lower right corner of plugin window"; } var v1 = valuesList; foreach (var source in v1.ToList()) { _values.Add(source); } }