I'm trying to open a thumbscache.db file, I've tried to open it like any other database but no use. I've also looked for any API or support in C#. Kindly suggest if there is another way. BTW below is my approach so far.
1. Open it like any other db.
path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
path += @"\Microsoft\Windows\Explorer\thumbcache_1280.db";
datasource = "Data source = " + path;
SQLiteCommand cmd = new SQLiteCommand();
SQLiteConnection conn = new SQLiteConnection(datasource);
cmd.Connection = conn;
cmd.CommandText = "SELECT * FROM Filename";
conn.Open();
SQLiteDataAdapter sqda = new SQLiteDataAdapter(cmd);
DataTable dt = new DataTable();
sqda.Fill(dt);
dataGridView1.DataSource = dt;
conn.Close();
But this exception comes up.
2. Open it using ShellFile
ShellFile shellFile = ShellFile.FromFilePath(path);
Bitmap bitmap = shellFile.Thumbnail.ExtraLargeBitmap;
pbThumbs.Image = bitmap;
And instead of thumbscache it gives file thumb icon.
3. Opening as OLE Document using OpenMcdf
path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
path += @"\Microsoft\Windows\Explorer\thumbcache_1280.db";
CompoundFile cf = new CompoundFile(path);
CFStream foundStream = cf.RootStorage.GetStream("Filename");
byte[] temp = foundStream.GetData();
And this exception comes up.
Following is C# class to open thumbcache*.db files.
public class ThumbCache
{
private const int WindowsVista = 0x14;
private const int Windows7 = 0x15;
private const int Windows8 = 0x1A;
private const int Windows8v2 = 0x1C;
private const int Windows8v3 = 0x1E;
private const int Windows8_1 = 0x1F;
private const int Windows10 = 0x20;
private Stream stream;
private uint fileVersion;
private byte[] tempBytes = new byte[65536];
private uint[] entryOffsets;
public int ImageCount { get { return entryOffsets.Length; } }
public ThumbCache(string fileName)
{
stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
ReadFromStream(stream);
}
public ThumbCache(Stream stream)
{
ReadFromStream(stream);
}
~ThumbCache()
{
stream.Close();
}
private void ReadFromStream(Stream stream)
{
stream.Read(tempBytes, 0, 32);
string magic = Encoding.ASCII.GetString(tempBytes, 0, 4);
if (!magic.Equals("CMMM"))
throw new ApplicationException("This is not a valid ThumbCache file.");
fileVersion = BitConverter.ToUInt32(tempBytes, 4);
uint fileType = BitConverter.ToUInt32(tempBytes, 8);
uint firstEntryPtr = 0;
uint availableEntryPtr = 0;
if (fileVersion < Windows8v2)
{
firstEntryPtr = BitConverter.ToUInt32(tempBytes, 12);
availableEntryPtr = BitConverter.ToUInt32(tempBytes, 16);
}
else
{
firstEntryPtr = BitConverter.ToUInt32(tempBytes, 16);
availableEntryPtr = BitConverter.ToUInt32(tempBytes, 20);
}
stream.Seek(firstEntryPtr, SeekOrigin.Begin);
List<uint> entryOffsetList = new List<uint>();
try
{
uint entrySize;
while (stream.Position < stream.Length)
{
entryOffsetList.Add((uint)stream.Position);
stream.Read(tempBytes, 0, 8);
if ((tempBytes[0] != 'C') || (tempBytes[1] != 'M') || (tempBytes[2] != 'M') || (tempBytes[3] != 'M'))
break;
entrySize = BitConverter.ToUInt32(tempBytes, 4);
stream.Seek(entrySize - 8, SeekOrigin.Current);
}
}
catch { }
entryOffsets = entryOffsetList.ToArray();
}
public ThumbInfo GetImage(int imageIndex, bool needImage)
{
if (entryOffsets.Length == 0) return null;
if ((imageIndex < 0) || (imageIndex >= entryOffsets.Length)) return null;
return new ThumbInfo(stream, entryOffsets[imageIndex], tempBytes, fileVersion, needImage);
}
public Dictionary<string, string> GetMetadata(ThumbInfo info)
{
var dict = new Dictionary<string, string>();
if (entryOffsets.Length == 0) return dict;
if (info == null) return dict;
dict.Add("File offset", info.fileOffset.ToString());
dict.Add("Entry size", info.entrySize.ToString());
dict.Add("Entry hash", info.entryHash.ToString("X16"));
dict.Add("Filename length", info.fileNameLength.ToString());
dict.Add("Padding length", info.paddingLength.ToString());
dict.Add("Data length", info.dataLength.ToString());
dict.Add("Image width", info.imageWidth.ToString());
dict.Add("Image height", info.imageHeight.ToString());
dict.Add("Data checksum", info.dataChecksum.ToString("X16"));
dict.Add("Header checksum", info.headerChecksum.ToString("X16"));
return dict;
}
public class ThumbInfo
{
public Image image;
public long fileOffset;
public uint entrySize;
public ulong entryHash;
public uint fileNameLength;
public uint paddingLength;
public uint dataLength;
public ulong dataChecksum;
public ulong headerChecksum;
public uint imageWidth;
public uint imageHeight;
public ThumbInfo(Stream stream, long offset, byte[] tempBytes, uint fileVersion, bool needImage)
{
fileOffset = offset;
stream.Seek(fileOffset, SeekOrigin.Begin);
stream.Read(tempBytes, 0, 64);
int bytePtr = 0;
string magic = Encoding.ASCII.GetString(tempBytes, bytePtr, 4); bytePtr += 4;
if (!magic.Equals("CMMM"))
throw new ApplicationException("Incorrect format.");
entrySize = BitConverter.ToUInt32(tempBytes, bytePtr); bytePtr += 4;
entryHash = BitConverter.ToUInt64(tempBytes, bytePtr); bytePtr += 8;
if (fileVersion == WindowsVista)
{
bytePtr += 8; // wchar x 4
}
fileNameLength = BitConverter.ToUInt32(tempBytes, bytePtr); bytePtr += 4;
paddingLength = BitConverter.ToUInt32(tempBytes, bytePtr); bytePtr += 4;
dataLength = BitConverter.ToUInt32(tempBytes, bytePtr); bytePtr += 4;
if (fileVersion >= Windows8)
{
imageWidth = BitConverter.ToUInt32(tempBytes, bytePtr); bytePtr += 4;
imageHeight = BitConverter.ToUInt32(tempBytes, bytePtr); bytePtr += 4;
}
bytePtr += 4; // unknown
dataChecksum = BitConverter.ToUInt64(tempBytes, bytePtr); bytePtr += 8;
headerChecksum = BitConverter.ToUInt64(tempBytes, bytePtr); bytePtr += 8;
if (!needImage || dataLength == 0 || dataLength > 0x1000000)
return;
stream.Seek(fileOffset + entrySize - dataLength, SeekOrigin.Begin);
if (dataLength > tempBytes.Length)
tempBytes = new byte[dataLength];
stream.Read(tempBytes, 0, (int)dataLength);
using (var mstream = new MemoryStream(tempBytes))
{
image = new Bitmap(mstream);
}
}
}
}
Detailed solution here .
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With