The AutomaticDestinations-ms File Format Explained
The format is not exotic once you have read it twice. An automaticDestinations-ms is an OLE Compound File, the same container that holds pre-2007 Office documents. Inside it, you get one stream per recently-used item, each holding a standard shell link, plus a single DestList stream that orders them and pins timestamps to each entry. That is the whole story. The rest of this post is the field-level detail you need when a parser misaligns and you have to confirm by hand what the bytes say.
The outer container is MS-CFB, nothing more
Every .automaticDestinations-ms opens with the MS-CFB header magic D0 CF 11 E0 A1 B1 1A E1. Sector size is 512 bytes for every Jump List I have inspected, which means the FAT, the directory chain, and the mini-stream (for entries under 4096 bytes) all behave the way they would in an old .doc. If you have a CFB parser already, point it at the file and you are halfway done.
What you read out of the directory is a flat list. There are no nested storages, no surprise sub-containers. One stream per recently-used target, plus a DestList. Stream names are lowercase hexadecimal integers: 1, 2, a, 1f, and so on. The stream name is also the entry ID. Hold on to it; it is what joins each LNK back to a DestList row.
Numbered streams are LNK, all the way down
Each numbered stream is a verbatim shell link as defined by [MS-SHLLINK]. That means the parser you already use for .lnk files on disk decodes them without modification: ShellLinkHeader, optional LinkTargetIDList, LinkInfo (with VolumeID, LocalBasePath, CommonNetworkRelativeLink), the StringData strings (NAME_STRING, RELATIVE_PATH, WORKING_DIR, COMMAND_LINE_ARGUMENTS, ICON_LOCATION), and the ExtraData blocks (TrackerDataBlock, PropertyStoreDataBlock, EnvironmentVariableDataBlock, KnownFolderDataBlock). The byte layout inside the stream is identical to a standalone shell link — the CFB layer adds nothing on top.
That symmetry is worth internalising. If you can read one, you can read both.
The DestList stream: 32-byte header, variable-length entries
DestList is what makes the bag of LNK streams into an ordered, dated MRU. It opens with a 32-byte header and then runs a sequence of variable-length records.
DestList header (32 bytes, little-endian)
offset size field
0x00 4 version (0x01..0x04 observed; Win7=1, Win10+=3/4)
0x04 4 number of entries
0x08 4 number of pinned entries
0x0C 4 unused / reserved (often a float; varies by version)
0x10 4 last entry ID issued
0x14 4 unused / reserved
0x18 4 last revision number
0x1C 4 unused / reserved
Each entry record after that header carries the metadata needed to reconstruct where the LNK came from:
DestList entry (variable length)
field size notes
checksum / reserved 8 version-dependent
NewVolumeID (GUID) 16 target volume
NewObjectID (GUID) 16 target object (file)
BirthVolumeID (GUID) 16 original volume
BirthObjectID (GUID) 16 original object
NetBIOS hostname 16 ASCII, NUL-padded
entry ID 4 matches the numbered stream name
reserved 4
access count 4 IEEE-754 float; sentinel = pinned
last access FILETIME 8 100-ns ticks since 1601-01-01 UTC
entry pin status / reserved 4 layout differs by version
name length (chars) 2 UTF-16LE code units
name 2*N UTF-16LE, not NUL-terminated
trailer 4 only on DestList v3/v4
Versions 3 and 4 (Windows 10 and later) bolt a small trailer onto each entry and shuffle a few reserved fields. The field names and meanings above stay stable, but exact offsets drift between versions. Branch on the header version before you touch entry parsing. Older parsers that hardcode v1 layout misread modern files silently — the entries decode, the timestamps are off, the hostname looks like junk, and no error is raised.
The access-count field carries the pinned flag
This trips people. The header says "number of pinned entries", but the per-entry pin marker is encoded into the access-count field itself. Unpinned entries store a normalised float counting opens. Pinned entries store a sentinel — historically 0xFFFFFFFF interpreted as a 32-bit float, which decodes as NaN. The exact sentinel and the position of any additional pin flag move around between DestList versions. Treat the count as opaque until you have checked the version.
Pinned entries are operationally interesting. They imply user intent — somebody right-clicked and chose "Pin to this list" — and they survive ordinary "clear recent items" resets. If a Jump List has been pruned but pinned entries remain, you still have something.
Practical parsing notes
- Endianness. Everything is little-endian, including the GUIDs (
Data1/Data2/Data3are little-endian;Data4is a byte array). The same convention Microsoft uses everywhere else. - FILETIME.
unix_seconds = (filetime / 10_000_000) - 11_644_473_600. Stay in UTC. Jump Lists carry no timezone information. - Hostname. The 16-byte NetBIOS name is the workstation that opened the file. On a domain that field is a gift — it correlates activity across hosts without needing every server's logs.
- Entry ID. The 4-byte
entry IDin each DestList row matches one of the hex stream names in the CFB directory. That is the join key. - Version skew. Win7 wrote v1. Win8/8.1 introduced v3. Win10 and Win11 commonly emit v3 or v4. Confirm the header first; do not assume.
- Ordering. DestList rows are not in MRU order on disk. Sort by
last access FILETIMEwhen you want the user's view of "most recent". Sort byentry IDif you want write order.
The original byte-level reverse engineering for DestList came from Yogesh Khatri and Mike Stevens. Eric Zimmerman's JLECmd is the canonical offline parser and the de-facto schema for output. Kacos2000's Jumplist-Browser PowerShell viewer is useful when you want to see the raw structures rather than a normalised view.
To poke at a real file without installing anything, drop one into the in-browser parser on the homepage. It runs a Rust DestList + LNK decoder compiled to WebAssembly, entirely client-side. For background on where these files come from and why they matter for an investigation, see the forensic primer.
Further reading
- Yogesh Khatri and Mike Stevens, "Jumping into the Past" — the original DestList reverse engineering paper. Still the best single reference for the field layout.
- Microsoft's [MS-CFB] specification on Microsoft Learn — for the container layer.
- Microsoft's [MS-SHLLINK] specification — for the LNK payload inside each numbered stream.
- The LNK parser and MFT parser for corroboration when the timeline matters.