The shell item is the unit Windows uses to remember a place, and the registry keeps it in more than one family of keys - Shellbags, RecentDocs, the OpenSave and LastVisited MRUs, TypedPaths, RunMRU and the search box. This page takes the item apart byte by byte, then sets out what each family can and cannot prove. A shell view is not the same thing as a person.
Open a folder in Explorer, switch it to Details view, sort by date, resize the window. Close it. Opened again a month later, it returns exactly as it was left. That memory is the feature, and Shellbags are where it lives.
It is a convenience feature with no security purpose whatsoever, which is precisely what makes it evidence. Windows is not recording navigation for any benefit but the user's own, so it does not stop, it does not ask, and it keeps the record for folders that no longer exist: a USB stick removed years ago, a network share that was mapped once, a folder deleted the same afternoon it was made.
A path is how a person names a file. It is not how Windows' shell
names anything. The shell keeps a namespace that is larger than the
filesystem - This PC, Control Panel, a phone attached over MTP, a
vendor's own tree grafted in beside them - and most of what is in it has
no path to have. So the shell names things with an ID list —
a PIDL, short for pointer to an identifier list — and a
shell item is one entry in one.
An item begins with two bytes of size and one byte of type, and after that it is whatever the owner of that corner of the namespace decided to put there. There is no schema. That is why this one machine holds a dozen different type bytes, why their sizes run from 14 bytes to over 9,000, and why every parser that reads them needs a fallback rather than a table - the next Windows feature to add a namespace extension adds a shell item layout with it, and does not publish one.
A list is a chain, read outside in: the desktop, then This PC, then a volume, then each folder, then the thing. Each link is an item of some type, and the type changes along the way - a GUID at the root, a drive string at the volume, a name for each folder after it. A Shellbag value is a chain of exactly one link, because the key it sits under supplies the rest; the ComDlg32 keys further down this page store the whole chain in one value.
A shell item is not a reference to the object. It is what the shell wrote down about the object at the moment it looked, and it stays exactly that after the object is gone. The name, the size and the timestamps in a bag are what that folder looked like then - readable long after the folder was deleted, and after the volume it lived on was reformatted or thrown away.
Shell items are not one artifact. They are the unit a dozen different records are built from, and each record keeps them for its own reason: Explorer remembering how a folder looked, a file dialog remembering where it last pointed, a shortcut remembering what it opens. This section names every one of those records and what each proves, before the rest of the page takes the item itself apart.
MRU stands for most recently used. An MRU key is a short list kept in the registry: a set of numbered values, each holding one remembered entry, plus one extra value that records the order in which they were last used. A new entry takes the next free number. Using an old entry again does not move or rewrite it - only the order value changes. Three ways of recording that order occur:
MRUList - a string of letters, each naming a value (a,
b, c ...), newest first. Used by RunMRU and by the
dialog keys of Windows XP.MRUListEx - an array of 4-byte little-endian value numbers, newest first,
ending in 0xFFFFFFFF. Used by Shellbags, RecentDocs, the ComDlg32
PIDL keys and WordWheelQuery.TypedPaths,
url1 is always the newest.Whatever the scheme, the key carries one timestamp: its last-write time, which belongs to the change that put the newest entry on top. Every other entry in the list has a position, not a date. The order value is decoded byte by byte in MRUListEx: the access order, and every MRU key is compared side by side in the MRU family.
Paths below sit under NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\Explorer
unless another hive is named. Three of the keys are listed although they hold no shell item,
because they live beside the ones that do and are read together with them.
| Record | Where it lives | What one entry holds | What it shows |
|---|---|---|---|
Shellbags: BagMRU | UsrClass.dat: Local Settings\Software\Microsoft\Windows\Shell\BagMRU, plus three older trees (all four keys) | One shell item per value. The nesting of the numbered subkeys rebuilds the path, one link per level, and NodeSlot points at the matching Bags entry. | A folder was displayed - in an Explorer window or a file dialog - including folders on drives, phones and shares long since gone. |
Shellbags: Bags | The sibling key, ...\Shell\Bags\<NodeSlot> | View settings only: view mode, icon size, sort column, window placement. No path and no shell item. | How the folder was shown, and - through its Shell or ComDlg subkey - whether Explorer or a file dialog wrote it (a bag is a view). |
RecentDocs | RecentDocs, with one subkey per file extension | A file name in UTF-16, followed by a shell link to the shortcut Windows made in the Recent folder. | A document or folder was opened through something that reports to the shell. |
OpenSavePidlMRU | ComDlg32\OpenSavePidlMRU\<extension> | A complete shell item list, from the root down to the file. | A file was chosen in a common Open or Save dialog - chosen, not necessarily read. |
LastVisitedPidlMRU | ComDlg32\LastVisitedPidlMRU | A program name in UTF-16, then the shell item list of the folder its dialog was last in. | Which program used a dialog, and where it was pointing. |
CIDSizeMRU | ComDlg32\CIDSizeMRU | A program name and a window size. No shell item and no path. | That the program opened a common dialog - nothing about a file or folder. |
TypedPaths | TypedPaths | A path typed as plain text. No shell item. | Deliberate navigation through the address bar. |
RunMRU | RunMRU | A command line as text. No shell item. | A command was typed into the Run box - not that it ran. |
WordWheelQuery | WordWheelQuery | A search term in UTF-16. No shell item. | A search was typed into Explorer's search box. |
.lnk shortcut | The LinkTargetIDList of every shortcut file | The target's full shell item list, in exactly the format mapped below. | What the shortcut opened, even after the target moved or vanished (the LNK anatomy). |
| Jump Lists | *.automaticDestinations-ms in the user's Recent folder: a DestList stream plus one LNK-format stream per entry | A shell item list inside every entry. | Files and folders opened by one specific application (the Jump List anatomy). |
OpenSaveMRU, LastVisitedMRU | ComDlg32 on Windows XP | Plain path strings, ordered by MRUList. | The pre-Vista form of the two dialog keys above, replaced by the PIDL keys from Vista on. |
The third byte of every item is its class type. The high bits choose a
family and the low bits are flags within it: 0x31 is the file-entry family
(0x30) with the directory flag (0x01) set, and 0x32 is
the same family with the file flag (0x02). The rows below cover every type
documented in the libyal Windows Shell Item format specification, the standard public
reference for structures Microsoft never published. Table 2 further
down counts which of them the reference system actually carries.
| Type | Family | What identifies the object | Where it is met |
|---|---|---|---|
0x1F | Root folder | A shell folder GUID - This PC, Network, the Recycle Bin, the user's folder - and a one-byte sort index. | The first link of almost every list: the top of the namespace. |
0x20-0x2F | Volume | A drive string such as C:\ when flag 0x01 is set; a GUID when it is not, as in 0x2E. Flag 0x08 marks removable media. Values seen: 0x23, 0x25, 0x29, 0x2A, 0x2E, 0x2F. | A drive letter, fixed or removable - the link that ties a folder to a volume that may no longer exist. |
0x30-0x3F | File entry | An 8.3 short name, a DOS timestamp and attributes, then the BEEF0004 extension with the long name, two more timestamps and, on NTFS, the MFT reference. Flags: 0x01 directory, 0x02 file, 0x04 Unicode names, 0x80 class identifier. Values seen: 0x30, 0x31, 0x32, 0x35, 0x36, 0xB1. | Every folder and file on a filesystem path (the BEEF0004 block). |
0x40-0x4F, 0xC3 | Network location | A UNC path or network name. Low bits: 0x01 domain or workgroup, 0x02 server, 0x03 share, 0x06 Microsoft Windows Network, 0x07 Entire Network. Values seen: 0x41, 0x42, 0x46, 0x47, 0x4C, 0xC3. | Browsing the network and its shares, including shares unmapped long ago. |
0x61 | URI | A URL; an FTP site carries further sub-items for its folders. | An FTP or web location opened through the shell. |
0x71 | Control Panel item | The GUID of one Control Panel applet. | A Control Panel page opened through the namespace. |
0x01 | Control Panel category | Twelve bytes: the signature 0x39DE2184 and a category number - System and Security, Programs, User Accounts and so on. | A Control Panel category view. |
0x74 | Delegate folder | An inner item, usually a file entry, followed by the delegate class GUID 5e591a74-df96-48d3-8d67-1733bcee28ba and the GUID of the folder that owns it. | Folders a namespace extension serves on behalf of the filesystem, such as the user's own files folder. |
0x00 | Signature-typed items | Nothing in the type byte. A four-byte signature after it says what the item is: 0x23FEBBEE for a users property view holding a known-folder GUID, GFSI for the Games folder, signatures for MTP devices and Control Panel .cpl files. | Phones and cameras attached over MTP, library and user views, Control Panel applets. |
| No fixed type | Compressed folder | Recognised by position, after the file entry of a .zip archive: the archived entry's sizes, compression method and CRC-32. | Browsing inside a ZIP archive in Explorer, where the shell invents folders the archive never stored. |
Anything outside these families is undocumented. On the reference system that means
0x79 and 0x7E, which Crow-Eye keeps through the fallback described
under one shell item, byte by byte rather than discarding.
Six real items, read out of the reference system's BagMRU and redrawn here. The tabs are item types, not versions of one thing: a root, a volume, a folder, a file, an item the parser does not recognise, and the extension block that carries the timestamps, on its own. The same structure appears inside .lnk files and Jump Lists, which is why decoding it is not registry work at all.
This tree holds 859 values across 12 item type bytes. 833 of them fall inside a range parse_shell_item_id() has a branch for; the other 26 reach the fallback, which keeps a plausible name and records the type as unknown. Every one of the 859 is a one-item list - a shell item followed by a two-byte end-of-list marker - which is why the last field of every map here is that marker.
Structure is real and measured. Names are replaced with a placeholder of the same byte length, so every offset still adds up and nothing here identifies the machine it came from.
The same fields as a table. Both are drawn from one definition, so the map and the table cannot disagree with each other.
Table 1| Offset | Size | Field | What it is |
|---|
Where these figures come from. The shell item dissected here was read out of a live Windows 11 system's UsrClass.dat - the reference system - captured through a Volume Shadow Copy. The folder names are replaced by placeholders of the same length, so every offset in the item still adds up.
The map above offers six tabs, and they are not six unrelated things. Four of them are the links of one path, spread across registry keys rather than laid end to end in bytes, and three of them contain the fourth. Hover a box or a line to read what it is; click a box to open that view in the map above.
Everything above is one item of one type. A type byte is not a label on the same structure - it decides what the rest of the item is, and the families have almost nothing in common past the size and the type itself. One carries a GUID and no name. One carries a drive string and no times. One carries another item inside it. The table is measured off this tree rather than listed from documentation, so the counts are what is there.
Table 2| Type | Values | Identified by | Carries a name | Carries times | Size | Crow-Eye records |
|---|---|---|---|---|---|---|
0x31 folder | 766 | an 8.3 short name and a long name | 704 of 766 | all 766 | 70-289 B | filesystem |
0x1F root | 52 | a known-folder GUID | 32 of 52 | 24 of 52 | 22-1101 B | special_folder |
0x32 file | 11 | an 8.3 short name and a long name | all 11 | all 11 | 104-180 B | filesystem |
0x74 delegate | 10 | another shell item, nested inside this one | all 10 | all 10 | 132-162 B | unknown (fallback) |
0x00 | 9 | nothing the shell documents | 8 of 9 | none | 34-1175 B | unknown (fallback) |
0x71 | 3 | a Control Panel GUID | 1 of 3 | none | 32-9215 B | unknown (fallback) |
0x01 | 2 | nothing - fourteen bytes, and no name in any of them | none | none | 14 B | unknown (fallback) |
0x2F volume | 2 | a drive string, C:\ | none | none | 27 B | drive |
0x37 | 1 | an 8.3 short name and a long name | all 1 | none | 118 B | filesystem |
0x3E | 1 | an 8.3 short name and a long name | all 1 | none | 134 B | filesystem |
0x79 | 1 | undocumented | all 1 | all 1 | 788 B | unknown (fallback) |
0x7E | 1 | undocumented | all 1 | none | 134 B | unknown (fallback) |
All 10 of the 0x74 delegate items in this tree carry an extension block with times in it and a name that reads cleanly, and all 10 fall outside every range parse_shell_item_id() dispatches on, so Crow-Eye records the type as unknown and takes the name only because the item genuinely carries one. That gap is a limit of the parser, not of the artifact, and the page says so rather than drawing a coverage it does not have.
5 of the 12 types above have a byte map in the tabs earlier on this page. The other 7 - 0x00, 0x01, 0x37, 0x3E, 0x71, 0x79, 0x7E - do not, because there is nothing decoded to draw: 4 of them are a single value, 1 carries nothing that reads as a name, and none of them has a published field map. A map of undocumented bytes would be a picture of a guess.
The table above is a census of one tree, and a census is not a specification. These exist and would appear in another capture.
| Type | What it is | Note |
|---|---|---|
0x35 | Directory entry, Unicode names | The file-entry family with both the directory flag and the Unicode flag set: a folder whose names are stored in UTF-16. |
0x40-0x4F | Network location | A UNC path. The parser has a branch for the whole range and records it as network; nothing in this tree exercises it. |
0xC3 | Network share | A share reached by name. Evidence that a share was browsed rather than merely mapped. |
A Shellbag value is a shell item ID list - the same structure Windows
writes inside a .lnk shortcut, and the same one it passes around internally to
mean "this thing in the shell namespace". The registry is storing it, not describing it. To
the hive it is a REG_BINARY blob and nothing more, which is why decoding it lives
in Crow-Eye's shared binary parser beside the LNK code rather than in the registry parser.
That sharing is the point: an examiner who understands one has understood the other. A shell item in a Jump List, a shell item in a shortcut and a shell item in a Shellbag are the same bytes with the same meanings. Explained in full: Jump Lists
These are the folder entry's bytes again - the same definition the map above is drawn from, so the two cannot disagree - but grouped the way a reader walking a list sees them rather than field by field. Five regions: the size that finds the next item, a fixed header, the first variable-length field, the extension block, and the two bytes that end the list.
Click any byte, or any row of the table below, to read the region it belongs to.
| Offset | Size | Region | This value |
|---|---|---|---|
0x00 | 2 | Item size | 92, and the value is 94 bytes - the difference is the terminator |
0x02 | 12 | Fixed header | 12 bytes: type, file size, a DOS timestamp and the attribute word |
0x0E | 10 | Short name, then alignment | 9 bytes including its null terminator, then 1 of padding |
0x18 | 68 | BEEF0004 extension block | 68 bytes, located by its signature at 0x1C |
0x5C | 2 | End of list | two bytes of zero |
The arithmetic closes: 2 bytes of size, 12 of fixed header, 10 of name and padding and 68 of extension block gives 92, which is what the size field reads - and the value is 94, so the last two bytes are the list terminator. A misread of that first field raises no error. It produces a walk that lands in the middle of the next item and returns names that are fragments of two folders.
The fixed part of a file entry carries an 8.3 short name and a DOS timestamp with two-second resolution. Neither is much use. The extension block that follows carries the real name in UTF-16, the created and accessed times, and on many systems the folder's MFT reference.
Its signature is 0xBEEF0004, and where it lands inside an
item is not fixed - it sits after the short name, whose length varies, which is why it is
found by searching for the signature rather than by counting. The map above shows where it
falls in each of the items it draws. It carries a version word that decides
where the long name starts.
That offset is not fixed: it moved between Windows XP, Vista, 7 and 8. A parser that hardcodes
one of them reads a name that begins a few bytes into itself on every other version, and
returns something that still looks like a name.
Later versions store the folder's MFT entry number and sequence number in the extension block. When present it ties a Shellbag directly to a file system record, which survives a rename. It is absent on older systems and on non-NTFS volumes, and a number read out of a block that does not contain one is a number that points at an unrelated file.
Each BagMRU key holds numbered values - the shell items - and one called
MRUListEx: a list of four-byte indices, most recent first, terminated by
0xFFFFFFFF. On the reference system the sample key's order runs
8, 0, 9, 7, 6, 3, 5, 4, 1, 2.
The numbers on the values are allocation order. The MRU list is visit order. They are not the same, and reporting the values in numeric order silently reorders the user's history into the order Windows happened to allocate slots. Entry 8 here was touched most recently despite whatever its slot number suggests.
A shellbag is one MRU key among several, and the shell item taken apart above turns up inside four of the others. They are usually listed together as if they were one artifact with several names. They are not. What separates them is not how they order themselves - two of them do not order the same way at all - but what a single value contains, and that is what decides which sentence a row can support.
Three of the columns below need a word first. Ordering says how the key records which entry was used last: MRUListEx is the modern form, a list of 4-byte little-endian value numbers in most-recent-first order terminated by 0xFFFFFFFF; MRUList is the older form that does the same job with single letters; and none means the key keeps no order at all, so its values can only be read as a set. What one value holds is the payload - a shell item, a plain string, or a structure of its own - and it is what decides what a row supports, the sentence a single entry can honestly be used to write.
| Key | Entries | Ordering | What one value holds | What a row supports |
|---|---|---|---|---|
RunMRU | 2 | MRUList | A command line as REG_SZ, with a trailing \1 Windows appends and Crow-Eye strips. | Somebody typed this into the Run box. Not that it ran, and not that it existed. |
TypedPaths | 17 | none | A path as REG_SZ, under a value named url1, url2 and so on. | A path was typed into Explorer's address bar - deliberate navigation, as against clicking through folders. |
WordWheelQuery | 2 | MRUListEx | A search term as REG_BINARY: a bare UTF-16 string and its terminator. Binary, and not a shell item. | A term was typed into Explorer's search box, in this user's session. |
RecentDocs | 0 - empty here | none | A file name in UTF-16 followed by a shell link, grouped into a subkey per file extension. | A document was opened by something that reports to the shell. |
OpenSavePidlMRU | 43 subkeys | MRUListEx | A shell item list - the same structure mapped above, chained from a root down to the file - in a subkey named for the extension. | A file was chosen in a common Open or Save dialog. Chosen, not necessarily read: a Save dialog writes this for a file that was never created. |
LastVisitedPidlMRU | 21 | MRUListEx | An application name in UTF-16, then a shell item list for the folder that program's dialog was last in. | Which program opened a dialog, and where it was pointing. The one key in this family that links a program to a place. |
CIDSizeMRU | 22 | MRUListEx | An application name in UTF-16, then a fixed-size window placement record. No path anywhere in it. | That program opened a common dialog, and how big its window was. Nothing about a file, a folder or a drive. |
RecentDocs exists on the reference system and holds nothing. An empty key is a finding - it is what a cleared history looks like, and it is not the same as a key that was never there.
MRUListEx is an array of four-byte indices, most recent first, closed by 0xFFFFFFFF. On the reference system LastVisitedPidlMRU opens 1, 4, 20, 19, 5, 18…, so the value named 1 was the last one used.
RunMRU is older and uses MRUList: a string of letters rather than numbers, and its values are named a, b, c to match. Here it reads ba, which is 2 entries in use order.
TypedPaths has no ordering value at all. Its values are named url1 to url17 and the number is the order - url1 is the most recent, and Windows renumbers the rest down when a new path arrives. A parser that goes looking for an MRUListEx here finds none and reports the key as unordered, which is the one case where numeric order is the right answer.
WordWheelQuery is REG_BINARY and holds a bare UTF-16 string - no size field, no type byte, nothing to walk. CIDSizeMRU is REG_BINARY and holds a window size. Reaching for the shell item reader because a value is binary reads a size out of the first two letters of whatever somebody searched for, and then walks that far into the next field.
An MRU key has a single last-write time and no per-entry time anywhere. It dates the newest entry, and it dates nothing else: the other nineteen values under the same key were written earlier, by an unknown amount. Crow-Eye stores it as key_last_write and leaves access_date empty rather than assigning the key's time to whichever entry the ordering value happens to name first - which would be an invention and would look exactly like evidence.
The same values as a table. Names are replaced with a placeholder of the same byte length, so every size field still points where it pointed.
Table 5| Offset | Size | Field | What it is |
|---|
Each table below is one tab in Crow-Eye, and each has an Anatomy button that opens its own section here. Its Charts button opens the User Activity dashboard, where it shares one timeline with every other shell-item and registry user-activity source. Shellbags have the rest of this page: start there.
Explorer's list of the files and folders this user recently opened, kept once overall and once per file extension. The value data starts with the item's name and is followed by the shell item of the shortcut Explorer wrote into the Recent folder.
| Field | Detail |
|---|---|
| Key | NTUSER\Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs, plus one subkey per extension (.docx, .pdf, ...) and Folder |
| Values | Numbered binary values; MRUListEx holds their order, most recent first |
| Timestamp | Only the key's (or subkey's) last-write time, which is when its most recent entry was written. Every other entry has no time of its own. |
| Proves | A file or folder with that name was opened through the shell by this user |
| Does not prove | The full path (the name only; the path is in the matching LNK in Recent), when older entries were opened, or that the file still exists |
| In Crow-Eye | Table RecentDocs: subkey, decoded name, MRU position, key last-write, user |
| On the User Activity dashboard | Source RecentDocs, dated by the key write time, so a subkey's entries share one day |
Value 0 is not the newest entry. The names are allocation slots; only MRUListEx says what was opened most recently.
Files chosen in the common Open and Save dialogs, by any program that uses them. Vista and later store a shell item ID list per entry; XP stored plain strings under OpenSaveMRU.
| Field | Detail |
|---|---|
| Key | NTUSER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU, one subkey per extension plus * (all types) |
| Values | Numbered binary values, each a shell item ID list naming the chosen file; MRUListEx orders them |
| Timestamp | The subkey's last-write time: when its most recent entry was chosen |
| Proves | This user selected that file in an Open or Save dialog |
| Does not prove | Which program showed the dialog (see LastVisitedPidlMRU), or that a save completed |
| In Crow-Eye | Table OpenSaveMRU: full path, file name, extension, drive, key time, MRU position |
| On the User Activity dashboard | Source OpenSaveMRU; a file on another drive or a share counts in the removable / network insights |
For each program that used a common dialog: the program's executable name and the folder the dialog was last in. Crow-Eye's table is called LastSaveMRU.
| Field | Detail |
|---|---|
| Key | NTUSER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedPidlMRU |
| Values | Numbered binary values: a UTF-16 executable name, then the shell item ID list of the folder; MRUListEx orders them |
| Timestamp | The key's last-write time: the most recent entry |
| Proves | That program opened a common dialog, and where the dialog last was |
| Does not prove | Which file was opened or saved - pair it with OpenSavePidlMRU |
| In Crow-Eye | Table LastSaveMRU: application, folder path and name, drive, key time |
| On the User Activity dashboard | Source LastSaveMRU (LastVisited) |
Paths typed or pasted into the Explorer address bar.
| Field | Detail |
|---|---|
| Key | NTUSER\Software\Microsoft\Windows\CurrentVersion\Explorer\TypedPaths |
| Values | url1 to url25, strings; url1 is the most recent |
| Timestamp | The key's last-write time, which belongs to url1 |
| Proves | The user typed that path into Explorer - a deliberate act, not a side effect |
| Does not prove | That the path existed or opened |
| In Crow-Eye | Table TypedPaths |
| On the User Activity dashboard | Source TypedPaths |
Commands typed into the Run box (Win+R).
| Field | Detail |
|---|---|
| Key | NTUSER\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU |
| Values | a, b, c, ... strings ending in \1; MRUList is a string of those letters, most recent first |
| Timestamp | The key's last-write time: when the first command in MRUList was typed |
| Proves | The user typed that command - cmd, powershell, a UNC path, regedit |
| Does not prove | That it ran successfully |
| In Crow-Eye | Table RunMRU: command, MRU position, key time |
| On the User Activity dashboard | Source RunMRU |
Terms typed into the Explorer search box (Windows 7 and later).
| Field | Detail |
|---|---|
| Key | NTUSER\Software\Microsoft\Windows\CurrentVersion\Explorer\WordWheelQuery |
| Values | Numbered values holding UTF-16 search terms; MRUListEx orders them |
| Timestamp | The key's last-write time: the most recent search |
| Proves | The user searched their files for that term |
| Does not prove | Searches made from the Start menu or the taskbar on Windows 10 and later, which are kept elsewhere |
| In Crow-Eye | Table WordWheelQuery |
| On the User Activity dashboard | Source Search |
Programs that opened a common Open/Save dialog, with the dialog's window size. No path at all.
| Field | Detail |
|---|---|
| Key | NTUSER\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\CIDSizeMRU |
| Values | Numbered binary values: a UTF-16 executable name, then window placement data; MRUListEx orders them |
| Timestamp | The key's last-write time: the most recent program |
| Proves | That program ran and showed a dialog for this user |
| Does not prove | Which file or folder |
| In Crow-Eye | Table cid_size_mru |
| On the User Activity dashboard | Source CIDSizeMRU |
The items pinned to the taskbar, stored by Explorer as a list of shell items.
| Field | Detail |
|---|---|
| Key | NTUSER\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband, value Favorites |
| Values | One binary value: a sequence of shell items, one per pinned shortcut, plus pinned Store apps by app ID |
| Timestamp | The key's last-write time: when the pins last changed |
| Proves | What is pinned now |
| Does not prove | When each item was pinned, or that it was ever launched from the taskbar (see FeatureUsage) |
| In Crow-Eye | One row of system_configuration (setting Favorites) |
| On the User Activity dashboard | Source Taskbar pins: the one row is split into one item per pin |
One subkey for every volume and network share this user's Explorer mounted - removable drives included - and the list of shares typed into Map Network Drive.
| Field | Detail |
|---|---|
| Keys | NTUSER\Software\Microsoft\Windows\CurrentVersion\Explorer\MountPoints2 (subkeys named by volume GUID {...}, drive letter, or share ##server#share); ...\Explorer\Map Network Drive MRU (strings ordered by MRUList) |
| Timestamp | Each subkey's last-write time, close to the last time this user's session mounted it |
| Proves | This user's session saw that volume or share - the per-user link a USB device history lacks |
| Does not prove | Which files were used; tie the volume GUID to a device through MountedDevices in SYSTEM |
| In Crow-Eye | Table MountPoints2 (Map Network Drive MRU rows included) |
| On the User Activity dashboard | Source MountPoints2; shares count in the network insight, other volumes in the removable one |
Explained in full: what was plugged in
Where each known folder - Desktop, Documents, Downloads - actually points for this user.
| Field | Detail |
|---|---|
| Key | NTUSER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders (and the machine-wide copy in SOFTWARE) |
| Values | One REG_EXPAND_SZ per folder, such as %USERPROFILE%\Desktop |
| Timestamp | None that belongs to a folder |
| Proves | A redirection: Documents on another drive, on a network share, or inside OneDrive |
| Does not prove | Any use of the folder |
| In Crow-Eye | Table user_shell_folders |
| On the User Activity dashboard | Source User Shell Folders, undated: listed under All items |
If Documents points at D:\ or a share, the paths in RecentDocs and the dialog MRUs point there too. Read this table before concluding that files were copied off the system drive.
Three registrations that make Explorer run code, read from three tables.
| Field | Detail |
|---|---|
| shell_open_command | Software\Classes\<ProgID>\shell\open\command (HKCU and HKLM): the command that runs when a file of that type is opened. A per-user entry overrides the machine's - a well-known way to make a file type launch something else |
| shell_icon_overlay_identifiers | SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers: CLSIDs of icon overlay handlers (OneDrive, Dropbox, TortoiseGit), each a DLL Explorer loads |
| shell_service_object_delay_load | ...\CurrentVersion\ShellServiceObjectDelayLoad: CLSIDs Explorer loads when it starts |
| Timestamp | None per entry |
| Proves | What Explorer will load or run; an unexpected DLL path or command line is a persistence lead |
| Does not prove | That it has run |
| In Crow-Eye | Tables shell_open_command, shell_icon_overlay_identifiers, shell_service_object_delay_load |
| On the User Activity dashboard | Source Shell extensions, undated |
A shellbag is written when a shell view of a container is created, or when its settings change. Explorer hosts shell views. So does every common File Open and Save dialog, inside whatever program opened it, and so do Windows' own broker processes - two of the programs this capture records as having used a dialog are PickerHost.exe and OpenWith.exe, which nobody launches. None of that requires a person to navigate anywhere, and in BagMRU none of it looks any different.
Windows records the difference itself, one level over. A BagMRU key carries a NodeSlot number naming a subkey of the Bags tree beside it, and that subkey holds the view settings - filed under Shell when an Explorer window made the view, and under ComDlg when a common dialog did. On the reference system 799 of 859 items resolve to a bag that way. The other 60 are keys that have never been given a view of their own, and Crow-Eye leaves the columns empty on those rather than guessing.
| View kind | Bags | What made it |
|---|---|---|
Shell | 574 | an Explorer window, and nothing else |
Shell and ComDlg | 224 | both - the same container reached through a window and through a dialog |
ComDlg | 3 | only ever a File Open or Save dialog, hosted inside some other program |
227 of the 801 bags on this machine carry a dialog's view - more than a quarter of them. A report that reads every row as somebody browsing is wrong about a quarter of its rows, and there is nothing in the row itself to say which quarter.
3 of the bags on the reference system have a ComDlg view and no Shell view at all: the container was shown inside another program's file dialog and never in an Explorer window. Every one of them is a search result - Generic.SearchResults, Pictures.SearchResults - which is not a folder at all. Nobody opened a directory; a program's Open dialog showed a list of matches, and Windows kept the view settings for it.
Nor is everything with a bag a directory. Sorted by the view class Windows recorded against it, this tree holds 17 CompressedFolder views - a zip file opened as though it were a folder - 49 storage-provider views, which are a cloud provider's namespace rather than a path on disk, 15 search-result views and 3 control panel pages. A control panel page is not a folder anybody walked to.
What a row does support, then: a container with that name was rendered as a shell view under that account, by some process running as that account, at some point. Whether a person chose it is a separate question, and it needs a separate artifact.
Crow-Eye stores the answer it can: node_slot is the number on the key, and bag_views is which subkeys the bag actually has. For the program's name, ComDlg32\LastVisitedPidlMRU records which executable last used a dialog in which folder, and Crow-Eye parses it into LastSaveMRU with an application column. On the reference capture that column names twenty programs, two of which - PickerHost.exe and OpenWith.exe - are Windows' own brokers, launched by no one. UserAssist, RecentDocs, Jump Lists and Prefetch say what was running at the time; the key's own last-write time says when. Those are what answer who, and a Shellbag on its own does not.
It records that a container was rendered as a shell view. It says nothing about whether any file in it was opened, copied or run, and nothing about how long anything was looked at: a folder shown once by accident and a folder worked in for a week are identical rows.
Every date in the shell item was copied from the file system when the item was written. The time of the visit is the last-written timestamp of the registry key holding the item. Confusing the two produces a timeline that is confidently wrong by whatever the gap between them happens to be.
Shellbags are written when a view is closed or settings change, not on every visit. A folder opened and closed without the shell deciding to persist anything leaves nothing. Explorer alternatives and command-line navigation leave nothing at all.
What it does prove, and what nothing else proves as well: a container with that name existed on this machine at some point, and a shell view of it was created under that user account - by some process running as that account, which is not necessarily a person and not necessarily Explorer. For removable media and network shares that are long gone, the Shellbag may be the only record they were ever attached. Which process, and how to tell
Both hives, both trees: UsrClass.dat and NTUSER.DAT, per user
profile. The decoding is registry_binary_parser, shared with the LNK and Jump
List parsers because a shell item is a shell item wherever it is stored.
Four BagMRU trees, each read together with its sibling Bags key,
which holds the view settings for the slots the tree points at. On a live system the
UsrClass.dat trees are reached through the merged Software\Classes view; on an
image, UsrClass.dat is opened directly and the same keys sit under
Local Settings\... with no Classes prefix. An absent tree reads
as empty, not as an error, because most systems carry only one or two of the four.
| Key | Hive | What it holds |
|---|---|---|
Local Settings\Software\Microsoft\Windows\Shell\BagMRU | UsrClass.dat | The Shellbag tree from Windows 7 onward, and the one that carries nearly every bag on a modern system - folders opened in Explorer, including on drives and shares removed long ago. |
Local Settings\Software\Microsoft\Windows\ShellNoRoam\BagMRU | UsrClass.dat | The local, non-roaming tree inside UsrClass.dat. Rarely populated on Windows 7 and later, which makes a bag found here worth a second look rather than an assumption. |
Software\Microsoft\Windows\Shell\BagMRU | NTUSER.DAT | The roaming tree used before Windows 7 moved Shellbags into UsrClass.dat. On a modern system it holds a small set - typically desktop and a few shell namespace views. |
Software\Microsoft\Windows\ShellNoRoam\BagMRU | NTUSER.DAT | The local tree of the XP and Vista era, where folders on local and removable drives were recorded. A collection that takes only NTUSER.DAT from an older system still gets these. |
The same four keys appear in the registry anatomy's full key list. Every key Crow-Eye reads for user activity
Deleted Shellbags are carved out of the hive's freed cells and written with the key path reconstructed where the parent chain survives - and left blank where it does not, because a guessed path on a recovered artifact is worse than no path. The registry internals guide covers how that carving works and why most recovered keys cannot be placed at all: of the 533 keys carved from free space on the reference system, 384 - 72.0 per cent - resolve to no parent, and each is recorded with an empty path rather than a guessed one.
Each row below records a change that alters what a reader may conclude, not only how the bytes are arranged. A parser written against one Windows release returns nothing against another, and does so without raising an error.
Table 7| Windows | What changed | What it means for a reader |
|---|---|---|
| XP | Shellbags kept in NTUSER.DAT under Software\Microsoft\Windows\Shell | One hive holds everything. Roaming profiles carried bags between machines. |
| Vista | Shell and ShellNoRoam split | Two trees to walk instead of one; missing the second loses local-only folders. |
| 7 and later | Moved to UsrClass.dat under Local Settings\Software\Microsoft\Windows\Shell | A collection that grabs only NTUSER.DAT gets almost no Shellbags on any modern Windows. UsrClass.dat is a separate file and is routinely forgotten. |
| 8 and later | BEEF0004 gains an MFT file reference and the block version climbs | The long name moves. A fixed offset reads a name out of the middle of a timestamp and returns plausible text. |
| Version | Long name at | Ships with |
|---|---|---|
| 3 | offset 12 | Windows XP and Vista |
| 7 | offset 26 | Windows 7 and 8, adds an 8-byte MFT reference |
| 8 | offset 30 | Windows 8.1 |
| 9 | offset 34 | Windows 10 and 11 - the version in the map above |
The preceding sections describe what intact shell items support. This section describes them after an attempt to remove or evade it, which is the condition in which it is frequently encountered. In most rows the attempt leaves a trace of its own.
Table 9| Technique | What is done | What survives |
|---|---|---|
| Deleting the bag | The key is removed and the parent's MRUListEx is rewritten. | The freed cell usually survives. A carve of UsrClass.dat recovers unlinked bag keys with their names and timestamps intact - see the internals guide. |
| Wiping UsrClass.dat | The file is deleted or replaced while logged out. | A hive with almost no free space and a very recent creation time is itself the anomaly. Compare the bag count against the machine's age. |
| Never opening Explorer | Using only a command line leaves no bags. | This is why an absence proves nothing - but it is a weaker claim than it looks. Shellbags record shell views, and Explorer is the commonest host of one rather than the only one: a program's Open or Save dialog writes them too. "They never opened Explorer" is not the same as "they left no bags". |
| Timestomping the folder | The folder's own times are changed before the visit. | The bag copies what Explorer saw. Compare against $FILE_NAME in the MFT, which is far harder to change. |
The Charts button on any of the shell-item and registry
user-activity tabs — Shellbags, the MRUs, UserAssist, BAM and DAM, FeatureUsage, the
Compatibility Assistant, file associations, camera / microphone use and the rest, 28 tabs in all —
opens one window, User Activity: Shell Items & Registry, over
registry_data.db. Every source shares one timeline, so
where the user went, what they opened and what they ran read together. The tab the window was opened
from is highlighted, not filtered; Show only narrows the view to that source on request. The
colour language is the artifact source.
| Source | What it records | Colour |
|---|---|---|
| Shellbags (BagMRU) | Folders browsed, with the folder's own embedded FAT times | #4aa8ff |
| RecentDocs | Files & folders recently opened, per extension | #39d353 |
| OpenSaveMRU | Files an Open/Save dialog touched | #fbbf24 |
| LastSaveMRU (LastVisited) | Which program used a dialog, in which folder | #22d3ee |
| TypedPaths | Paths typed into the Explorer address bar | #a78bfa |
| RunMRU | Commands typed into the Run box | #f43f5e |
| Search | Terms typed into the Explorer search box | #94a3b8 |
| CIDSizeMRU | Programs that opened a common dialog (no path) | #fb923c |
| Taskbar pins | Items pinned to the taskbar | #e879f9 |
| MountPoints2 | Volumes and shares this user mounted | #2dd4bf |
| Office MRU | Documents opened in Office, trusted documents | #f97316 |
| TypedURLs | Addresses typed into the IE address bar | #818cf8 |
| RDPClientMRU | Remote Desktop hosts | #fda4af |
| RecentApps | Recently used apps (early Windows 10) | #a3e635 |
| App MRUs | PuTTY, WinSCP, WinRAR, 7-Zip and others | #facc15 |
| Regedit last key | The last key open in Registry Editor | #cbd5e1 |
| UserAssist | Programs run through Explorer, with run and focus counts | #f472b6 |
| BAM | Last run of each program, per account | #ff6b6b |
| DAM | Last run, on Modern Standby devices | #c4b5fd |
| Camera / mic / location | When each app last used them | #fb7185 |
| MUICache | Programs the shell handled (no time) | #67e8f9 |
| User Shell Folders | Where known folders point (no time) | #86efac |
| Shell extensions | Open commands, overlay handlers, delay-load objects (no time) | #fca5a5 |
| FeatureUsage | Taskbar counters (key time only) | #fde047 |
| Compatibility Assistant | Programs the PCA saw run (key time only) | #7dd3fc |
| File associations | Programs used per file type (key time only) | #d9f99d |
| ProgramsCache | The Start menu's cached program list (no time) | #e2e8f0 |
Each source table carries a different set of columns; the dashboard normalises every row to one shape — target, path, item type, drive or share, and the best-available time.
Shell-item timing is coarser than an execution artifact's. Most of the MRUs carry only one registry key-write time — the moment their most-recent entry was written — plus an MRU position, which is the only true record of order. Shellbags are the rich exception: each bag embeds the folder's own FAT created / modified / accessed times, so shellbag rows spread across the timeline while a source like RunMRU collapses onto a single day. The dashboard shows MRU order alongside time rather than pretending every row has an independent timestamp.
Left — one source strip per source that has a dated item (a cell per day, source = colour; sources with no time of their own are listed under All items); click a day for the drill-down: items-by-hour (stacked by source), a by-source breakdown, the top places, and a shell-item list (time · source · target · path · MRU order). Right — the overview: totals, an Insights card, the most-visited places and most-referenced files, and a Volumes & shares (device history) card.
Click a day to fill the drill-down, or an item in the list for its full profile: its target and full path, source and item type, drive or share, MRU position, the user, and every timestamp the record carries. For a shellbag the profile lays the embedded FAT created / modified / accessed times against the registry write time, and shows the MFT reference and size. Filters: search, a source, a location and a volume selector, and a date dropdown.