|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Visual Basic Internet Routines FindFirstUrlCacheEntry: Obtain the Contents of the IE Cache |
|
Posted: | Monday October 4, 1999 |
Updated: | Monday December 26, 2011 |
Applies to: | VB4-32, VB5, VB6 |
Developed with: | VB6, Windows NT4 |
OS restrictions: | Internet Explorer |
Author: | VBnet - Randy Birch |
Related: |
FindFirstUrlCacheEntry: Obtain the Contents of the IE Cache FindFirstUrlCacheEntry: Delete the IE Cache CoCreateInstance: Delete the IE History Cache |
Prerequisites |
Internet Explorer for full functionality. Other browsers do not use the Windows Internet cache for local file storage . |
|
Here
is the first entry in manipulating Windows' Internet cache - retrieving visited files and cookies using the FindFirst/FindNextUrlCacheEntry
APIs. Thanks go out to CCRP buddies Brad and Ramon for assistance on this routine.
While, as VB developers, we are familiar with passing C structures as VB user-defined types to API methods, these structures usually contained all the data returned, and so were defined with strings of fixed-lengths. The URL cache APIs however are variable-size structures - each call will result in data types differing in size - so the application must allocate sufficient data space for the successful call prior to calling. This involves using LocalAlloc, LocalFree, as well as CopyMemory to set up pointers to the allocated memory space. To use the Find URL APIs, a call is made passing a type of 0 length. The call fails with ERROR_INSUFFICIENT_BUFFER, and the APIs dwBuffer member contains the size of the structure needed to retrieve the data. Memory is allocated to this buffer using LocalAlloc, and the pointer to this memory is passed in place of the structure (a non-typical use of UDT-based APIs to VB programmers). One the call succeeds, CopyMemory is used again to move the memory buffer into a VB user-defined type, and then the string information is extracted using lstrlenA and lstrcpyA. Finally the memory pointer is freed with LocalFree. This process is repeated for each cache entry while the handle to the Find method remains valid. Once the last entry has been retrieved, FindNextUrlCacheEntry returns 0, and the loop terminates. So what can you do with this info? First is the obvious experimentation to see how different URLs and cache items are categorized (i.e. what XXX_CACHE_ENTRY type they correspond to. Second is the ability to programmatically delete all or selected items from the cache (not demonstrated in this example). And finally, it provides the ability to extend this into a personal parental 'Net Nanny', whereby the visited links could be loaded to a list for viewing or saving to a file, providing a means to monitor your child's Internet activity. |
BAS Module Code |
Place the following code into the general declarations area of a bas module: |
|
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved. ' Some pages may also contain other copyrights by the author. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Distribution: You can freely use this code in your own ' applications, but you may not reproduce ' or publish this code on any web site, ' online service, or distribute as source ' on any media without express permission. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Public Const ERROR_CACHE_FIND_FAIL As Long = 0 Public Const ERROR_CACHE_FIND_SUCCESS As Long = 1 Public Const ERROR_FILE_NOT_FOUND As Long = 2 Public Const ERROR_ACCESS_DENIED As Long = 5 Public Const ERROR_INSUFFICIENT_BUFFER As Long = 122 Public Const MAX_PATH As Long = 260 Public Const MAX_CACHE_ENTRY_INFO_SIZE As Long = 4096 Public Const LMEM_FIXED As Long = &H0 Public Const LMEM_ZEROINIT As Long = &H40 Public Const LPTR As Long = (LMEM_FIXED Or LMEM_ZEROINIT) Public Const NORMAL_CACHE_ENTRY As Long = &H1 Public Const EDITED_CACHE_ENTRY As Long = &H8 Public Const TRACK_OFFLINE_CACHE_ENTRY As Long = &H10 Public Const TRACK_ONLINE_CACHE_ENTRY As Long = &H20 Public Const STICKY_CACHE_ENTRY As Long = &H40 Public Const SPARSE_CACHE_ENTRY As Long = &H10000 Public Const COOKIE_CACHE_ENTRY As Long = &H100000 Public Const URLHISTORY_CACHE_ENTRY As Long = &H200000 Public Const URLCACHE_FIND_DEFAULT_FILTER As Long = NORMAL_CACHE_ENTRY Or _ COOKIE_CACHE_ENTRY Or _ URLHISTORY_CACHE_ENTRY Or _ TRACK_OFFLINE_CACHE_ENTRY Or _ TRACK_ONLINE_CACHE_ENTRY Or _ STICKY_CACHE_ENTRY Public Type FILETIME dwLowDateTime As Long dwHighDateTime As Long End Type Public Type INTERNET_CACHE_ENTRY_INFO dwStructSize As Long lpszSourceUrlName As Long lpszLocalFileName As Long CacheEntryType As Long dwUseCount As Long dwHitRate As Long dwSizeLow As Long dwSizeHigh As Long LastModifiedTime As FILETIME ExpireTime As FILETIME LastAccessTime As FILETIME LastSyncTime As FILETIME lpHeaderInfo As Long dwHeaderInfoSize As Long lpszFileExtension As Long dwExemptDelta As Long End Type Public Declare Function FindFirstUrlCacheEntry Lib "wininet" _ Alias "FindFirstUrlCacheEntryA" _ (ByVal lpszUrlSearchPattern As String, _ lpFirstCacheEntryInfo As Any, _ lpdwFirstCacheEntryInfoBufferSize As Long) As Long Public Declare Function FindNextUrlCacheEntry Lib "wininet" _ Alias "FindNextUrlCacheEntryA" _ (ByVal hEnumHandle As Long, _ lpNextCacheEntryInfo As Any, _ lpdwNextCacheEntryInfoBufferSize As Long) As Long Public Declare Function FindCloseUrlCache Lib "wininet" _ (ByVal hEnumHandle As Long) As Long Public Declare Sub CopyMemory Lib "kernel32" _ Alias "RtlMoveMemory" _ (pDest As Any, _ pSource As Any, _ ByVal dwLength As Long) Public Declare Function lstrcpyA Lib "kernel32" _ (ByVal RetVal As String, ByVal Ptr As Long) As Long Public Declare Function lstrlenA Lib "kernel32" _ (ByVal Ptr As Any) As Long Public Declare Function LocalAlloc Lib "kernel32" _ (ByVal uFlags As Long, _ ByVal uBytes As Long) As Long Public Declare Function LocalFree Lib "kernel32" _ (ByVal hMem As Long) As Long |
Form Code |
To a form, add a combo (Combo1), an command button (Command1), a list (List1), a textbox (Text1) and a label (Label1). Add the following code: |
|
Option Explicit Private Sub Form_Load() With Combo1 .AddItem "Normal Entry" .ItemData(.NewIndex) = &H1 .AddItem "Edited Entry (IE5)" .ItemData(.NewIndex) = &H8 .AddItem "Offline Entry" .ItemData(.NewIndex) = &H10 .AddItem "Online Entry" .ItemData(.NewIndex) = &H20 .AddItem "Stick Entry" .ItemData(.NewIndex) = &H40 .AddItem "Sparse Entry (n/a)" .ItemData(.NewIndex) = &H10000 .AddItem "Cookies" .ItemData(.NewIndex) = &H100000 .AddItem "Visited History" .ItemData(.NewIndex) = &H200000 .AddItem "Default Filter" .ItemData(.NewIndex) = URLCACHE_FIND_DEFAULT_FILTER .ListIndex = 0 End With End Sub Private Sub Command1_Click() Dim numEntries As Long Dim cacheType As Long cacheType = Combo1.ItemData(Combo1.ListIndex) Label1.Caption = "Working ..." Label1.Refresh List1.Clear List1.Visible = False numEntries = GetCacheURLList(cacheType) List1.Visible = True Label1.Caption = Format$(numEntries, "###,###,###,##0") & "files found" End Sub Private Sub List1_Click() Text1.Text = List1.List(List1.ListIndex) End Sub Private Function GetCacheURLList(cacheType As Long) As Long Dim ICEI As INTERNET_CACHE_ENTRY_INFO Dim hFile As Long Dim cachefile As String Dim nCount As Long Dim dwBuffer As Long Dim pntrICE As Long 'Like other APIs, calling FindFirstUrlCacheEntry or 'FindNextUrlCacheEntry with an insufficient buffer will 'cause the API to fail, and its dwBuffer points to the 'correct size required for a successful call. dwBuffer = 0 'Call to determine the required buffer size hFile = FindFirstUrlCacheEntry(vbNullString, ByVal 0, dwBuffer) 'both conditions should be met by the first call If (hFile = ERROR_CACHE_FIND_FAIL) And _ (Err.LastDllError = ERROR_INSUFFICIENT_BUFFER) Then 'The INTERNET_CACHE_ENTRY_INFO data type is a 'variable-length type. It is necessary to allocate 'memory for the result of the call and pass the 'pointer to this memory location to the API. pntrICE = LocalAlloc(LMEM_FIXED, dwBuffer) 'allocation successful If pntrICE Then 'set a Long pointer to the memory location CopyMemory ByVal pntrICE, dwBuffer, 4 'and call the first find API again passing the 'pointer to the allocated memory hFile = FindFirstUrlCacheEntry(vbNullString, ByVal pntrICE, dwBuffer) 'hfile should = 1 (success) If hFile <> ERROR_CACHE_FIND_FAIL Then 'now just loop through the cache Do 'the pointer has been filled, so move the 'data back into a ICEI structure CopyMemory ICEI, ByVal pntrICE, Len(ICEI) 'CacheEntryType is a long representing the type of 'entry returned, and should match our passed param. If (ICEI.CacheEntryType And cacheType) Then 'extract the string from the memory location 'pointed to by the lpszSourceUrlName member 'and add to a list cachefile = GetStrFromPtrA(ICEI.lpszSourceUrlName) List1.AddItem cachefile nCount = nCount + 1 End If 'free the pointer and memory associated 'with the last-retrieved file Call LocalFree(pntrICE) 'and again repeat the procedure, this time calling 'FindNextUrlCacheEntry with a buffer size set to 0. 'This will cause the call to once again fail, 'returning the required size as dwBuffer dwBuffer = 0 Call FindNextUrlCacheEntry(hFile, ByVal 0, dwBuffer) 'allocate and assign the memory to the pointer pntrICE = LocalAlloc(LMEM_FIXED, dwBuffer) CopyMemory ByVal pntrICE, dwBuffer, 4 'and call again with the valid parameters. 'If the call fails (no more data), the loop exits. 'If the call is successful, the Do portion of the 'loop is executed again, extracting the data from 'the returned type Loop While FindNextUrlCacheEntry(hFile, ByVal pntrICE, dwBuffer) End If 'hFile End If 'pntrICE End If 'hFile 'clean up by closing the find handle, as 'well as calling LocalFree again to be safe Call LocalFree(pntrICE) Call FindCloseUrlCache(hFile) GetCacheURLList = nCount End Function Private Function GetStrFromPtrA(ByVal lpszA As Long) As String GetStrFromPtrA = String$(lstrlenA(ByVal lpszA), 0) Call lstrcpyA(ByVal GetStrFromPtrA, ByVal lpszA) End Function |
Comments |
Save the project, run, select a cache type to view, and hit Get Cache. Note too that some defined cache types are not yet implemented in Windows, or have specific version requirements.. |
|
|
|
|||||
|
|||||
|
|||||
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |