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 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 currentKey = string.Empty; try { foreach (var registryKey in key.SubKeys) { currentKey = registryKey.KeyName; //get MRU key and read it in var mruVal = registryKey.Values.SingleOrDefault(t => t.ValueName == "MRUListEx"); var mruListOrder = new ArrayList(); if (mruVal != null) { var index = 0; var mruPos = 0; while (index < mruVal.ValueDataRaw.Length) { mruPos = BitConverter.ToInt32(mruVal.ValueDataRaw, index); index += 4; if (mruPos != -1) { mruListOrder.Add(mruPos); } } } foreach (var keyValue in registryKey.Values) { if (keyValue.ValueName == "MRUListEx") { continue; } bags = new List<ShellBag>(); var shellItemsRaw = new List<byte[]>(); var mru = (int) mruListOrder[int.Parse(keyValue.ValueName)]; DateTimeOffset? openedOn = null; if (mru == 0) { openedOn = registryKey.LastWriteTime; } try { var det = new StringBuilder(); var index = 0; while (index < keyValue.ValueDataRaw.Length) { var size = BitConverter.ToInt16(keyValue.ValueDataRaw, index); if (size == 0) { break; } var shellRaw = new byte[size]; Buffer.BlockCopy(keyValue.ValueDataRaw, index, shellRaw, 0, size); shellItemsRaw.Add(shellRaw); index += size; } ShellBag bag = null; foreach (var bytese in shellItemsRaw) { 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: bag = new ShellBag0X31(bytese); break; case 0x32: bag = new ShellBag0X32(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: {registryKey.KeyName}, Value name: {keyValue.ValueName}, Message: **** Unsupported ShellID: 0x{bytese[2]:x2}. Send this ID to [email protected] so support can be added!! ****"); Errors.Add( $"Key: {registryKey.KeyName}, Value name: {keyValue.ValueName}, Message: **** Unsupported ShellID: 0x{bytese[2]:x2}. Send this ID to [email protected] so support can be added!! ****"); break; } if (bag != null) { det.AppendLine(bag.ToString()); bags.Add(bag); } } var v = new ValuesOut(registryKey.KeyName, $"{GetAbsolutePathFromTargetIDs(bags)}", det.ToString(), keyValue.ValueName, mru, openedOn); valuesList.Add(v); } catch (Exception ex) { Errors.Add( $"Key: {registryKey.KeyName}, Value name: {keyValue.ValueName}, message: {ex.Message}"); } } } } catch (Exception ex) { Errors.Add($"Error processing OpenSavePidlMRU subkey {currentKey}: {ex.Message}"); } if (Errors.Count > 0) { AlertMessage = "Errors detected. See Errors information in lower right corner of plugin window"; } var v1 = valuesList.OrderBy(t => t.MruPosition); foreach (var source in v1.ToList()) { _values.Add(source); } }