I wrote earlier about my hack for syncing my browsing between my computer and mobile.
One of the most fiddly bits of implementing this was how to get the last visited page from Pocket Internet Explorer on my phone. In case this is useful to anyone, here is a quick description of how I did it.
I wrote the code to get the last visited page in C++. I couldn’t find any way to access the browser, or the address bar, programmatically.
The closest I could find is a set of Windows Internet Services API calls which let you have direct access to the browser cache used by Pocket Internet Explorer.
I wrote the code for Pocket Internet Explorer on Windows Mobile, but to the best of my knowledge it should work on regular Internet Explorer. I’ve not tried it because, let’s be honest, who uses Internet Explorer? 😉
The approach was to use FindFirstUrlCacheEntryEx and FindNextUrlCacheEntryEx to enumerate through the INTERNET_CACHE_ENTRY_INFO entries in the Internet cache.
Each INTERNET_CACHE_ENTRY_INFO item stores (amongst other information) the URL it was downloaded from, and the time the cache item was last accessed.
So I find the last page the user has visited by enumerating through the cache, and store the URL for the cache item with the latest last-accessed time.
Interesting snippets from the code
First step – prepare somewhere to store each Internet cache item while we look at it.
DWORD MAX_CACHE_ENTRY_SIZE = 2048; DWORD dwEntrySize = MAX_CACHE_ENTRY_SIZE; LPINTERNET_CACHE_ENTRY_INFO lpCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO) new char[dwEntrySize]; lpCacheEntry->dwStructSize = dwEntrySize;
Start the enumerating of the items by getting the first entry from the cache.
I use FindFirstUrlCacheEntryEx rather than FindFirstUrlCacheEntry as it gives the ability to filter the cache items we want to look at.
I filter for URLHISTORY_CACHE_ENTRY so that I don’t have to go through all the cookies, and cached scripts and images.
HANDLE hCacheDir = FindFirstUrlCacheEntryEx(NULL, 0, URLHISTORY_CACHE_ENTRY, 0, lpCacheEntry, &dwEntrySize, NULL, NULL, NULL);
If this returns ERROR_INSUFFICIENT_BUFFER, then I prepare more space for the cache entry (the dwEntrySize
value returned tells you how much space is required) and try again.
We need a space to store the time the item was last accessed, and the URL it was downloaded from.
FILETIME lastTime = lpCacheEntry->LastAccessTime; LPWSTR lastAccessedUrl = new TCHAR[lstrlen(lpCacheEntry->lpszSourceUrlName) + 1]; lstrcpy(lastAccessedUrl, lpCacheEntry->lpszSourceUrlName); lastAccessedUrl[lstrlen(lpCacheEntry->lpszSourceUrlName)] = '\0';
We’re now ready to start enumerating through all of the items in the Internet cache.
FindNextUrlCacheEntryEx(hCacheDir, lpCacheEntry, &dwEntrySize, NULL, NULL, NULL);
The space to allocate for the cache entries need to be handled as before – allocate MAX_CACHE_ENTRY_SIZE
space to start with, then increase it as needed if we get ERROR_INSUFFICIENT_BUFFER
back.
For each item in the Internet cache, we get the last accessed time and compare it with the latest one. If it is later, we replace the URL and timestamp we have for the latest visited page.
FILETIME nextTime = lpCacheEntry->LastAccessTime; if (CompareFileTime(&nextTime, &lastTime) == 1) { lastTime = lpCacheEntry->LastAccessTime; lastAccessedUrl = new TCHAR[lstrlen(lpCacheEntry->lpszSourceUrlName) + 1]; lstrcpy(lastAccessedUrl, lpCacheEntry->lpszSourceUrlName); lastAccessedUrl[lstrlen(lpCacheEntry->lpszSourceUrlName)] = '\0'; }
And you keep calling FindNextUrlCacheEntryEx
until it returns a ERROR_NO_MORE_ITEMS
error.
Other than that, it’s just cleaning up really.
You need to delete (lpCacheEntry);
after you finish looking at each Internet cache item, and close the Internet cache when you’ve finished everything using FindCloseUrlCache(hCacheDir);
.
There are probably a few bugs hiding in there, but it seems to do the trick.
Tags: cpp, FindFirstUrlCacheEntry, FindNextUrlCacheEntryEx, internet explorer, mobile, pocket internet explorer, windows