QL-Win/QuickLook · error · InvalidDataException

The specified file does not appear to be an OLE Compound Fil

Error message

The specified file does not appear to be an OLE Compound File (invalid header).

What it means

Thrown by CompoundFileExtractor.ExtractToDirectory when the file exists but its first 8 bytes do not match the OLE Compound File magic header D0 CF 11 E0 A1 B1 1A E1. The file is therefore not a structured-storage / OLE container and cannot be opened via IStorage.

Source

Thrown at QuickLook.Plugin/QuickLook.Plugin.ArchiveViewer/CompoundFileBinary/CompoundFileExtractor.cs:58

    {
        if (!Directory.Exists(destinationDirectory))
        {
            Directory.CreateDirectory(destinationDirectory);
        }

        // Ensure the compound file exists
        if (!File.Exists(compoundFilePath))
            throw new FileNotFoundException("Compound file not found.", compoundFilePath);

        // Validate magic header for OLE compound file: D0 CF 11 E0 A1 B1 1A E1
        byte[] magicHeader = [0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1];
        byte[] header = new byte[8];
        using (FileStream fs = new(compoundFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
        {
            int read = fs.Read(header, 0, header.Length);
            if (read < header.Length || !header.SequenceEqual(magicHeader))
            {
                throw new InvalidDataException("The specified file does not appear to be an OLE Compound File (invalid header).");
            }
        }

        // Open the compound file as an IStorage implementation wrapped by DisposableIStorage.
        using DisposableIStorage storage = new(compoundFilePath, STGM.DIRECT | STGM.READ | STGM.SHARE_EXCLUSIVE, IntPtr.Zero);
        IEnumerator<STATSTG> enumerator = storage.EnumElements();

        // Enumerate all elements (streams and storages) at the root of the compound file.
        while (enumerator.MoveNext())
        {
            STATSTG entryStat = enumerator.Current;

            // STGTY_STREAM indicates the element is a stream (treat as a file).
            if (entryStat.type == (int)STGTY.STGTY_STREAM)
            {
                ExtractStreamToDirectory(storage, entryStat.pwcsName, destinationDirectory);
            }
            // STGTY_STORAGE indicates the element is a nested storage (treat as a directory).

View on GitHub (pinned to cb5d9c429c)

Solutions

  1. Validate the OLE magic header before calling the extractor.
  2. If the file is a modern Office format (.docx etc.), route to a zip-based extractor instead.
  3. Detect format by extension + magic bytes and dispatch to the correct parser.
  4. Catch InvalidDataException and report the file as unsupported for compound-file extraction.

Example fix

// before
CompoundFileExtractor.ExtractToDirectory(path, dest);

// after
static bool IsOle(string p)
{
    using var fs = File.OpenRead(p);
    var h = new byte[8]; fs.Read(h, 0, 8);
    return h[0]==0xD0 && h[1]==0xCF && h[2]==0x11 && h[3]==0xE0
        && h[4]==0xA1 && h[5]==0xB1 && h[6]==0x1A && h[7]==0xE1;
}
if (!IsOle(path))
    throw new InvalidDataException($"{path} is not an OLE Compound File.");
CompoundFileExtractor.ExtractToDirectory(path, dest);
Defensive patterns

Strategy: validation

Validate before calling

// Validate the OLE Compound File magic header before extraction.
static readonly byte[] OleMagic = [0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1];
public static bool IsOleCompoundFile(string path)
{
    try
    {
        using var fs = File.OpenRead(path);
        var h = new byte[8];
        return fs.Read(h, 0, 8) == 8 && h.SequenceEqual(OleMagic);
    }
    catch { return false; }
}

Try / catch

try { CompoundFileExtractor.ExtractToDirectory(path, dest); }
catch (InvalidDataException ex) when (ex.Message.Contains("OLE Compound File"))
{
    // Not an OLE file; route to a zip-based extractor if it's a modern Office file.
}

Prevention

When it happens

Trigger: Calling ExtractToDirectory on a file that is not an OLE compound file: a .docx (which is a zip), a raw binary, a text file, or a file with a .cfb/.doc extension that is actually a newer XML/zip-based format.

Common situations: Modern Office files (.docx/.xlsx/.pptx) are zip, not OLE — users expect old .doc but pass new formats; a file renamed to look like a compound file; legacy .doc that is actually RTF or plain text; a corrupt OLE file whose header is overwritten.

Related errors


AI-assisted analysis of QL-Win/QuickLook@cb5d9c429c (2026-08-13). Data as JSON: /api/errors/b2077f20095ea971. Report an issue: GitHub.