Click here to Skip to main content
Click here to Skip to main content

Internet Explorer Favorites, deconstructed

By , 24 Dec 2007
 

Download Favorites2XBEL.zip - visual studio 2008 solution - 20 KB

Download Favorites2XBELvs2005.zip - visual studio 2005 solution - 20 KB

Introduction

This article contains the information I have gathered on how and where Internet Explorer stores its bookmarks, or 'Favorites' in Microsoft terms.

Background

In my quest to write the ultimate bookmark synchronizer I ran into a problem: Microsoft doesn't offer an API to access the explorer bookmarks structure. While a large part of the bookmark information is available in easy to read formats, the order in which the bookmarks appear in the favorites menu is stored in a binary format in the registry. A search on the internet reveals a few people that have decoded (part of) this structure, and I wanted to add my findings here.

How to start

IE favorites are stored in a directory structure below the 'favorites' folder. This folder can be found by reading the 'Favorites' value in the registry key HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders. Alternatively, in .NET you can call Environment.GetFolderPath(Environment.SpecialFolder.Favorites) to retrieve the path. The favorites folder contains '.URL' files, optionally arranged in a directory structure that reflects the menu structure of your IE favorites.

URL files

URL files (extension: .url) are good old .INI files that contain the target address of a favorite. The name of the url file without the extension is how the bookmark appears in the favorites menu. Here is the content of a bookmark to the codeproject site:
[DEFAULT]
BASEURL=http://www.codeproject.com/
[InternetShortcut]
URL=http://www.codeproject.com/
IDList=
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,2

As you can see, the codeproject address is stored twice in this URL. However, only the second one is used when visiting a favorite site. The first one (key BASEURL, section DEFAULT) merely stores the original address of the page when it was added as a favorite. Any subsequent edits of the favorite will only modify the key URL, section InternetShortCut.

Ordering

Now for the tricky part: IE stores the menu order of the URLs and folders in a totally different way, namely the registry. This adventure starts at the registry-key HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\MenuOrder\Favorites. This key contains a binary type (REG_BINARY) value 'Order', which is a kind of table that contains ordered records that point to URL files or folders. For every favorites sub-folder on the filesystem there's also a corresponding registry key below the "..\MenuOrder\Favorites" key, each of which contains another 'Order' table. The following screenshots clearly demonstrate the mirroring of the favorites' filesystem structure and the registry structure.

favorites filesystem structure

favorites registry structure

Order table format

An order table is a binary format table. Its basic structure is as follows:
MenuOrderTable = MenuOrderTableHeader,  { MenuOrderRecord }
MenuOrderRecord = MenuOrderRecordHeader, SubRecord0, Filler
SubRecord0 = SubRecord0Header, "short folder or url filename and various other information", SubRecord1
SubRecord1 = SubRecord1Header, "long folder or url filename and various other information"
(note that {..} means: repeat zero or more times)
The exact binary format is given in the following tables:

MenuOrderTable
Field length Field type Value Description
4 UInt32 0x00000008 Header ID, always 8
4 UInt32 0x00000002 Header ID, always 2
4 UInt32 x Total length of the payload that follows, including the 4 bytes of this field
4 UInt32 0x00000001 Unknown, always 1
4 UInt32 NumberOfRecords The number of MenuOrder records that follow
NumberOfRecords * n MenuOrderRecord See below 'NumberOfRecords' times the MenuOrderRecord structure

MenuOrderRecord
Field length Field type Value Description
4 UInt32 x Total length of this record upto and including the filler bytes. Also includes the 4 bytes of this field
4 Int32 ordernumber Number that determines the display order of this entry, or -5 when the entry is unordered
variable SubRecord0 See below SubRecord that contains the type, length, name of the menuorder entry
6 byte[6] 0 filler, all zero

SubRecord0
Field length Field type Value Description
2 UInt16 x Total length of this record, including the 2 bytes of this field
2 UInt16 Flags:
Bit 0 : 1 => it's a folder, 0 otherwise
Bit 1 : 1 => it's an URL, 0 otherwise
Bit 2 : 1 => short 8.3 filename is stored in unicode format, 0 => short name is stored using ASCII
4 UInt32 ? Unknown
4 UInt32 ? Might be the 'last visited' date, is updated everytime you visit this link. Unknown encoding.
2 UInt16 0x20, 0x10 or 0x11 Flags:
Bit 0 : 1 => the long filename in SubRecord1 is followed by a string that points to a resource string
Bit 4 : 1 => it's a folder, 0 otherwise
Bit 5 : 1 => it's an URL, 0 otherwise
variable (even number) zero-terminated ascii or unicode string, depending on the Flags Zero-terminated 8.3 style folder name or url name. This field is padded with zeros to contain an even number of bytes.
variable SubRecord1 See below SubRecord that contains the long unicode name of this menuorder entry

SubRecord1
Field length Field type Value Description
2 UInt16 x Total length of this record, including the 2 bytes of this field
36 on vista
18 on XP/2003
byte[] ? Unknown purpose
variable zero-terminated unicode string variable long name of the folder or URL
variable zero-terminated unicode string variable optional field: examine bit 0 of the second 'flags' field in SubRecord0 to see if this field is present or not.
This string points to a resource string located in a DLL, and is formatted like this: @shell32.dll,-12693
2 UInt16 variable location (byte-index) of SubRecord1 within SubRecord0

How to use

When reading the above information, you are probably only interested in the following bits of information:

  • is it a folder or URL
  • the ordering number
  • the long filename

Caveat

Please note that this information is the result of reverse engineering.. I have only verified these structures on XP and Vista. You should also be aware of the structure differences between Vista and XP: on Vista, the 'unknown' byte array in SubRecord1 has a different size than on XP.

The code

I have condensed the information above into a class called FavoritesNode that allows you to load and examine the internet favorites of the current user. FavoritesNode implements IList<FavoritesNode>, so it's actually a tree of sorts. Every node in this tree is either a 'folder' or 'url'.

How to use

The following example shows how you would load the favorites and print the top-level bookmarks:

    ...
    using CodeProject.IEFavDecon;
    ...
    FavoritesNode node = FavoritesNode.LoadRoot();

    foreach(FavoritesNode child in node)
    {
        if(child.NodeType == FavoritesNodeType.Url)
        {
            Console.WriteLine("Name: {0}, Url: {0}", child.DisplayName, child.Url);
        }
    }

XBEL: XML Bookmark Exchange Language

The project in the attached zip does something slightly more useful: it loads your favorites and writes them to an XBEL formatted XML file (which is the bookmark format that Microsoft should have been using by now). Once you have your bookmarks in XML format its easy to transform them into webpages, import or export them, merge, sort, etcetera.
As an example, the main program file contains a commented-out section that shows how you can apply a stylesheet to transform the generated XML bookmarks into a nice indented HTML file.

Other resources

The following links contain bits and pieces on this subject that were very helpful during my research:

History

  • Dec 19, 2007 : Initial release
  • Dec 22, 2007 : Added sample code, updated text & resource links
  • Dec 24, 2007 : Added vs2005 version of the solution

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

jpmik
Architect
Netherlands Netherlands
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Layout  Per page   
Generalworks fine in W7 64, IE9, .NET 4.0, VS 2010 Pro ... thanks again !memberBillWoodruff11 Jun '11 - 3:38 
I used the modification suggested here by Adrian Alexander.
 
Great to see you are still here responding to questions !
 
best, Bill
"Reason is the natural order of truth; but imagination is the organ of
meaning." C.S. Lewis

GeneralGreat article, but no thanks to LoadFolderNodeFromRegistry [modified]memberAdrian Alexander15 Feb '11 - 11:47 
I appreciate that you've shared your code for importing IE favorites.   However, it looks like the LoadFolderNodeFromRegistry method has issues under Windows 7.   The order of menu items isn't so important for my purposes, though, so I only use LoadFolderNodeFromFileSystem and have deleted all registry-related code.
 
Again, thanks for sharing!
 

 
-- Modified Tuesday, February 15, 2011 5:54 PM
GeneralRe: Great article, but no thanks to LoadFolderNodeFromRegistrymemberjpmik15 Feb '11 - 12:00 
Thanks,
 
For the people that do need the ordering on Windows7, the solution for that can be found a few comments lower, under "SubRecord1 byte array length changes for Win7"
GeneralMy vote of 5membergggustafson8 Aug '10 - 3:14 
usable
General[BUG] "Order" reg key does not have to exist for every fav entry - nested processing stopsmembermcjoxp9 Jul '10 - 0:29 
Your statement - " For every favorites sub-folder on the filesystem there's also a corresponding registry key below the "..\MenuOrder\Favorites" key, each of which contains another 'Order' table." - is not always true.
 
From my testing it seems that the "Order" reg key never appears for new empty fav folders, fav folders with one bookmark or originally imported/created fav folders whose bookmarks order has never been manually changed. In fact it appears that the non-presence of the "Order" key is the default system behaviour and it it only manifests itself for a fav folder when the user has initiated a manual ordering. Another interesting thing happened when I created a new fav folder in IE8; the folder name did not appear in the MenuOrder reg at all until I had added at least two bookmarks to it!
 
The upshot is that Favorites2XBEL is failing to continue with further processing of folders and bookmarks (and their nested children) when the "Order" reg key is not present for the folder being examined. Perhaps when the "Order" key is not present, the code can default to whatever there is in the "Environment.SpecialFolder.Favorites" directory.
 
Please confirm this behaviour. I am running IE8 under Win7 64.
 
Cheers,
 
Mark.
GeneralRe: [BUG] "Order" reg key does not have to exist for every fav entry - nested processing stopsmemberjpmik9 Jul '10 - 7:05 
Confirmed, I also noticed this yesterday when I ran Favorites2XBEL on a VirtualBox image of Windows 7 (32 bit) that contained a 'fresh' explorer with the default microsoft links. The registry keys only appeared after I reordered or added new bookmarks. Your suggestion seems like a good way to fix this problem, perhaps I'll give it a go if Holland doesn't win the World cup this weekend Smile | :)
GeneralRe: [BUG] "Order" reg key does not have to exist for every fav entry - nested processing stopsmembermcjoxp9 Jul '10 - 7:28 
Thanks for the prompt reply JP. And yes, good luck to the Netherlands. Apparently it's been a long time between drinks! Smile | :)
 
Mark
GeneralSubRecord1 byte array length changes for Win7membermcjoxp6 Jul '10 - 22:06 
I'm running Win7 64bit and it seems that the byte array (of unknown purpose) in SubRecord1 now has a length of 40 bytes instead of the 36 for Vista. You will get a StackOverflow error if you run it as is on Win7.
 
Can anyone pls chk if this byte length changes with Vista 64 or Win7 32? Oh and thanks for a great and informative article.
 
Cheers,
 
Mark
GeneralRe: SubRecord1 byte array length changes for Win7memberjpmik7 Jul '10 - 8:53 
Hi, thanks for your update. Just tested it: I can confirm the field is 40 bytes on both Win7 64bit and Win64 32 bit. Testing for Win7 should be done like this:
 
   if (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 1)
   {
       stream.Position += 40;
   } 
   else ....

GeneralRe: SubRecord1 byte array length changes for Win7memberAdrian Alexander15 Feb '11 - 17:32 
First, to clarify, we are referring to this piece of code in the MenuOrderRecord.Deserialize method:
 
// skip 18 bytes on xp, 36 bytes on vista
if ( Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor > 0 )
      stream.Position += 18;
else
      stream.Position += 36;
 

 
To replace the above code, I came up with this:
 
// skip 18 bytes on xp and below, 36 bytes on vista, 40 bytes on win7 and up
if ( Environment.OSVersion.Version.Major <= 5 )
      stream.Position += 18;
else if ( Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor == 0 )
      stream.Position += 36;
else
      stream.Position += 40;
 
So does it look alright?
QuestionAn easy program?memberMember 697482111 Mar '10 - 7:49 
Very useful info. I'm trying to export my ie favourties to firefox while retaining the right order. It would be useful to have a downloadable program instead of visual studio code as I've never compiled a program before and don't even know what language this is written in. There must be plenty of others who would benefit from this.
QuestionCreate a URL Shortcut [modified]membervb.philip7 Dec '08 - 2:46 
Great example, I wasn't aware of the XBEL format. I wrote my own VB.NET utility for moving Favorites around different PCs by using the Windows Script Host. The Script Host has routines for creating shortcut url files to disk. Instead of creating a list, like the XBEL file I create the actual favorite file. I typically run my program from a flash drive to capture the favorites for moving to another PC.
 
I like your approach of using the XBEL file because it's managed code where using the Windows Script Host is not in .NET. I need to expand on your solution by providing functionality to create the favorites on a PC from the XBEL file and also to capture the Favorites image icon if there is one.
 
-phil
 
modified on Sunday, December 7, 2008 9:25 AM

QuestionHow to create a custom favorite entry?memberdebussyster17 Jul '08 - 23:31 
I want to create a favorite by special name and url,and set it the first item in the top menu.how to do that?thanks
GeneralDate format...memberslickvguy22 May '08 - 16:32 
I've started looking into this matter,and while I've only spent a few hours investigating, I've learned quite a bit. Your tables are not always correct. After an import, I see many records in the registry that have the long filename BEFORE the short, and at the location where the short name would be. If you alter anything in that favorite folder, it will re-write the data, and then it'll be like the table in your article.
 
Seems simple now, but after trying to figure out what the date format was in the registry...it's the FAT32 format! Doh! 2 bytes for year/month/day and 2 bytes for the time. Search the net for the exact format - it's well-known. The date format in the Netscape bookmark file is of course Unix UTC format.
 
Unsurprisingly, Microsoft does not use the 3 date fields in the Netscape bookmark file format as they were intended. You'd think "Last_Visit" would be pretty clear. Wrong. Last visit gets put in the "Date Accessed" field, which has nothing to do with visiting the favorite's URL! It has to do with the .url itself. Ridiculous. Date Modified (Windows) is the field that shows you when you "last visited" a particular site.
 
There are many inconsistencies in how various routines in IE and XP use the Favorites registry key and the .url files. Still trying to make (some) sense of it.
 
Thanks for your efforts.
QuestionBut IE is a P.O.S. so what difference does it make?memberclintonG24 Dec '07 - 9:37 
The Favorites should be stored in the file system as XML and IE8 should make it possible to rapidly load and unload XML fragments as collections to make it possible for those of us who have collections consisting of tens of thousands of Favorites to actually use and manage Favorites efficiently.
 
EVERYBODY knows this including the greasy stinking filthy pieces of dog sh!t at Microsoft who knew this all the way back at IE5 when many of us developers begged them to change the way IE functioned in this regard but the filthy pieces of sh!t refused and the filthy pieces of sh!t have continued to go out of their way to make life miserable for everybody.
QuestionLooks nice... 2005 possible?memberGeorge Bush24 Dec '07 - 8:24 
I've been looking for ways to do this; unfortunately, I don't have VS2008. Any chance of a 2005 version? Thanks...
AnswerRe: Looks nice... 2005 possible?memberJean-Paul Mikkers24 Dec '07 - 8:31 
Sure! I don't think I used any 2008 or .NET 3.5 specific constructs, so it should compile without changes on VS2005. I'll give it a shot and upload it as a separate zip. Thanks for the suggestion.
GeneralThanks, nice work !memberBillWoodruff22 Dec '07 - 17:17 
Hi Jean-Paul,
 
Very well done article. I personally "hate" the two ways you can re-order the Favorite folders in IE7 : either using drag-and-drop in the clunky dialog that pops up when you choose 'Organize Favorites' from the 'Favorites' menu, or directly in the 'Favorites drop-down menu through drag-and-drop.
 
A glaring omission, to me, in MS's two ways of arranging Favorites is that you can only apply sort-by-name to a selected folder, not the whole collection of Favorites.
 
It would be nice to see you take your ability to parse the Favorites folders and data and then construct a TreeView interface where you could visually drag and drop without the tedious scrolling driven by "bumping" your item-to-drag against the top or bottom border of the dialog or drop-down, then save the results back Smile | :) And in your spare time you could throw in some nice ways of sorting them, also Smile | :)
 
thanks ! Bill
"The greater the social and cultural distances between people, the more magical the light that can spring from their contact." Milan Kundera in Testaments Trahis

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130516.1 | Last Updated 24 Dec 2007
Article Copyright 2007 by jpmik
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid