/// <summary> /// Retrieves information about a cache entry. /// </summary> /// <param name="url">URL to be retrieved</param> /// <returns>information about an entry in the Internet cache</returns> public static INTERNET_CACHE_ENTRY_INFO GetUrlCacheEntryInfo(string url) { IntPtr buffer = IntPtr.Zero; UInt32 structSize; bool apiResult = GetUrlCacheEntryInfo(url, buffer, out structSize); try { buffer = Marshal.AllocHGlobal((int)structSize); apiResult = GetUrlCacheEntryInfo(url, buffer, out structSize); if (apiResult == true) { return((INTERNET_CACHE_ENTRY_INFO) Marshal.PtrToStructure(buffer, typeof(INTERNET_CACHE_ENTRY_INFO))); } } finally { if (buffer.ToInt32() > 0) { try { Marshal.FreeHGlobal(buffer); } catch { } } } INTERNET_CACHE_ENTRY_INFO ret = new INTERNET_CACHE_ENTRY_INFO(); ret.lpszLocalFileName = null; return(ret); }
private void DeleteUrlCacheEntryIfUrlMatches(INTERNET_CACHE_ENTRY_INFO entry) { string cacheEntryName = Marshal.PtrToStringUni(entry.lpszSourceUrlName); if (cacheEntrySuffixes != null) { foreach (string suffix in cacheEntrySuffixes) { if (cacheEntryName.EndsWith(suffix)) { goto Match; } } return; } Match: Logger.LogAction(String.Format("Deleting '{0}'", cacheEntryName)); if (!DeleteUrlCacheEntry(entry.lpszSourceUrlName)) { int err = Marshal.GetLastWin32Error(); if (err != ERROR_FILE_NOT_FOUND) { ThrowExceptionForLastWin32Error(); } } }
static public void Start() { int neededBytes = 0; FindFirstUrlCacheEntry(null, IntPtr.Zero, ref neededBytes); if (Marshal.GetLastWin32Error() != 0x103) { int bufferByteSize = neededBytes; IntPtr bufferPtr = Marshal.AllocHGlobal(bufferByteSize); try { bool successful; IntPtr hEnum = FindFirstUrlCacheEntry(null, bufferPtr, ref neededBytes); do { INTERNET_CACHE_ENTRY_INFO cacheItem = (INTERNET_CACHE_ENTRY_INFO)Marshal.PtrToStructure(bufferPtr, typeof(INTERNET_CACHE_ENTRY_INFO)); string tmp = cacheItem.lpszSourceUrlName.ToLower(); tmp = tmp.Substring(tmp.IndexOf("@") + 1); if (tmp.IndexOf("?") > 0) { tmp = tmp.Substring(0, tmp.IndexOf("?")); } string sHash = GetSHA1Hash(tmp, (tmp.Length + 1) * 2); byte[] bHashData = (byte[])Registry.CurrentUser.OpenSubKey(IE_KEY).GetValue(sHash, null); if (bHashData != null) { if (!visited.Contains(tmp)) { DecryptCredential(tmp, sHash, bHashData.Length, bHashData); visited = visited + tmp + " "; } } else { tmp = tmp + "/"; string sHash2 = GetSHA1Hash(tmp, (tmp.Length + 1) * 2); byte[] bHashData2 = (byte[])Registry.CurrentUser.OpenSubKey(IE_KEY).GetValue(sHash2, null); if ((bHashData2 != null) && !visited.Contains(tmp)) { DecryptCredential(tmp, sHash2, bHashData2.Length, bHashData2); visited = visited + tmp + " "; } } neededBytes = bufferByteSize; successful = FindNextUrlCacheEntry(hEnum, bufferPtr, ref neededBytes); if ((successful || (Marshal.GetLastWin32Error() != 0x103)) && (!successful && (neededBytes > bufferByteSize))) { bufferByteSize = neededBytes; IntPtr fgfg = new IntPtr(bufferByteSize); bufferPtr = Marshal.ReAllocHGlobal(bufferPtr, fgfg); successful = true; } }while (successful); } finally { Marshal.FreeHGlobal(bufferPtr); } } }
/// <summary> /// More friendly wrapper for the Retrieve/ReadUrlCacheEntryStream APIs. /// </summary> /// <param name="url"></param> /// <returns></returns> public static string RetrieveUrlCacheEntryContents(string url) { IntPtr buffer = IntPtr.Zero; INTERNET_CACHE_ENTRY_INFO info = new INTERNET_CACHE_ENTRY_INFO(); UInt32 structSize; IntPtr hStream = IntPtr.Zero; RetrieveUrlCacheEntryStream(url, buffer, out structSize, 0, 0); CheckLastError(url, true); try { buffer = Marshal.AllocHGlobal((int)structSize); hStream = RetrieveUrlCacheEntryStream(url, buffer, out structSize, 0, 0); CheckLastError(url, true); info = (INTERNET_CACHE_ENTRY_INFO)Marshal.PtrToStructure(buffer, typeof(INTERNET_CACHE_ENTRY_INFO)); uint streamSize = info.dwSizeLow; IntPtr outBuffer = Marshal.AllocHGlobal((int)streamSize); try { IntPtr result = ReadUrlCacheEntryStream(hStream, 0, outBuffer, out streamSize, 0); CheckLastError(url, false); return(Marshal.PtrToStringAnsi(outBuffer)); } finally { if (outBuffer.ToInt32() > 0) { try { Marshal.FreeHGlobal(outBuffer); } catch { } } } } finally { if (buffer.ToInt32() > 0) { try { Marshal.FreeHGlobal(buffer); } catch { } } if (hStream != IntPtr.Zero) { UInt32 dwReserved = 0; UnlockUrlCacheEntryStream(hStream, dwReserved); } } }
/// <summary> /// More friendly wrapper for the Retrieve/ReadUrlCacheEntryStream APIs. /// </summary> /// <param name="url"></param> /// <returns></returns> public static string RetrieveUrlCacheEntryContents(string url) { IntPtr buffer = IntPtr.Zero; INTERNET_CACHE_ENTRY_INFO info = new INTERNET_CACHE_ENTRY_INFO(); UInt32 structSize; IntPtr hStream = IntPtr.Zero; RetrieveUrlCacheEntryStream(url, buffer, out structSize, 0, 0); CheckLastError(url, true); try { buffer = Marshal.AllocHGlobal((int)structSize); hStream = RetrieveUrlCacheEntryStream(url, buffer, out structSize, 0, 0); CheckLastError(url, true); info = (INTERNET_CACHE_ENTRY_INFO)Marshal.PtrToStructure(buffer, typeof(INTERNET_CACHE_ENTRY_INFO)); uint streamSize = info.dwSizeLow; IntPtr outBuffer = Marshal.AllocHGlobal((int)streamSize); try { IntPtr result = ReadUrlCacheEntryStream(hStream, 0, outBuffer, out streamSize, 0); CheckLastError(url, false); return Marshal.PtrToStringAnsi(outBuffer); } finally { if (outBuffer.ToInt32() > 0) { try { Marshal.FreeHGlobal(outBuffer); } catch { } } } } finally { if (buffer.ToInt32() > 0) { try { Marshal.FreeHGlobal(buffer); } catch { } } if (hStream != IntPtr.Zero) { UInt32 dwReserved = 0; UnlockUrlCacheEntryStream(hStream, dwReserved); } } }
private static void ForEachCacheEntry(long groupId, string searchPattern, int flags, CacheEntryAction action) { int cacheEntryInfoBufferSize = 0; IntPtr cacheEntryInfoBuffer = IntPtr.Zero; IntPtr enumHandle = IntPtr.Zero; try { for (;;) { enumHandle = FindFirstUrlCacheEntryEx(searchPattern, 0, flags, groupId, cacheEntryInfoBuffer, ref cacheEntryInfoBufferSize, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); int err = Marshal.GetLastWin32Error(); if (enumHandle != IntPtr.Zero) { break; } if (err == ERROR_NO_MORE_ITEMS || err == ERROR_FILE_NOT_FOUND) { return; } if (err != ERROR_INSUFFICIENT_BUFFER) { ThrowExceptionForLastWin32Error(); } cacheEntryInfoBuffer = Marshal.ReAllocCoTaskMem(cacheEntryInfoBuffer, cacheEntryInfoBufferSize); } for (;;) { INTERNET_CACHE_ENTRY_INFO entry = (INTERNET_CACHE_ENTRY_INFO) Marshal.PtrToStructure(cacheEntryInfoBuffer, typeof(INTERNET_CACHE_ENTRY_INFO)); action(entry); // Get next entry. bool returnValue = FindNextUrlCacheEntryEx(enumHandle, cacheEntryInfoBuffer, ref cacheEntryInfoBufferSize, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); int err = Marshal.GetLastWin32Error(); if (!returnValue) { if (err == ERROR_NO_MORE_ITEMS || err == ERROR_FILE_NOT_FOUND) { return; } if (err != ERROR_INSUFFICIENT_BUFFER) { ThrowExceptionForLastWin32Error(); } cacheEntryInfoBuffer = Marshal.ReAllocCoTaskMem(cacheEntryInfoBuffer, cacheEntryInfoBufferSize); } } } finally { Marshal.FreeCoTaskMem(cacheEntryInfoBuffer); if (enumHandle != IntPtr.Zero) { FindCloseUrlCache(enumHandle); } } }
/// <summary> /// Return the local (cached) file representing the given URL. /// </summary> /// <param name="url">URL to be retrieved</param> /// <returns>he path to the local file, or null if no local file.</returns> public static string GetUrlCacheEntryFile(string url) { INTERNET_CACHE_ENTRY_INFO info = GetUrlCacheEntryInfo(url); return(info.lpszLocalFileName); }
private void DeleteUrlCacheEntryIfUrlMatches(INTERNET_CACHE_ENTRY_INFO entry) { string cacheEntryName = Marshal.PtrToStringUni(entry.lpszSourceUrlName); if (cacheEntrySuffixes != null) { foreach (string suffix in cacheEntrySuffixes) { if (cacheEntryName.EndsWith(suffix)) goto Match; } return; } Match: Logger.LogAction((LogFunction log) => { log("Deleting '{0}'", cacheEntryName); }); if (!DeleteUrlCacheEntry(entry.lpszSourceUrlName)) { int err = Marshal.GetLastWin32Error(); if (err != ERROR_FILE_NOT_FOUND) ThrowExceptionForLastWin32Error(); } }
/// <summary> /// Friendly wrapper around the FindUrlCacheEntry APIs that gets a list of the entries /// matching the given pattern. /// </summary> /// <param name="urlPattern">The pattern, which is a regular expression applied by this method, since I've never /// seen any evidence that the first parameter to the FindFirstUrlCacheEntry API actually works.</param> /// <returns></returns> public static ArrayList FindUrlCacheEntries(string urlPattern) { ArrayList results = new ArrayList(); IntPtr buffer = IntPtr.Zero; UInt32 structSize; IntPtr hEnum = FindFirstUrlCacheEntry(null, buffer, out structSize); try { if (hEnum == IntPtr.Zero) { int lastError = Marshal.GetLastWin32Error(); if (lastError == Win32API.ERROR_INSUFFICIENT_BUFFER) { buffer = Marshal.AllocHGlobal((int)structSize); hEnum = FindFirstUrlCacheEntry(urlPattern, buffer, out structSize); } else if (lastError == Win32API.ERROR_NO_MORE_ITEMS) { return(results); } } INTERNET_CACHE_ENTRY_INFO result = (INTERNET_CACHE_ENTRY_INFO)Marshal.PtrToStructure(buffer, typeof(INTERNET_CACHE_ENTRY_INFO)); try { if (Regex.IsMatch(result.lpszSourceUrlName, urlPattern, RegexOptions.IgnoreCase)) { results.Add(result); } } catch (ArgumentException ae) { throw new ApplicationException("Invalid regular expression, details=" + ae.Message); } if (buffer != IntPtr.Zero) { try { Marshal.FreeHGlobal(buffer); } catch { } buffer = IntPtr.Zero; structSize = 0; } while (true) { long nextResult = FindNextUrlCacheEntry(hEnum, buffer, out structSize); if (nextResult != 1) { int lastError = Marshal.GetLastWin32Error(); if (lastError == Win32API.ERROR_INSUFFICIENT_BUFFER) { buffer = Marshal.AllocHGlobal((int)structSize); nextResult = FindNextUrlCacheEntry(hEnum, buffer, out structSize); } else if (lastError == Win32API.ERROR_NO_MORE_ITEMS) { break; } } result = (INTERNET_CACHE_ENTRY_INFO)Marshal.PtrToStructure(buffer, typeof(INTERNET_CACHE_ENTRY_INFO)); if (Regex.IsMatch(result.lpszSourceUrlName, urlPattern, RegexOptions.IgnoreCase)) { results.Add(result); } if (buffer != IntPtr.Zero) { try { Marshal.FreeHGlobal(buffer); } catch { } buffer = IntPtr.Zero; structSize = 0; } } } finally { if (hEnum != IntPtr.Zero) { FindCloseUrlCache(hEnum); } if (buffer != IntPtr.Zero) { try { Marshal.FreeHGlobal(buffer); } catch { } } } return(results); }
//private static void getUrlEntriesInHistory(TextWriter writer) public static List <string> getUrlEntriesInHistory(string sourceUrlFilter, string fileExtensionFilter) { List <string> filesList = new List <string>(); IntPtr buffer = IntPtr.Zero; UInt32 structSize; const string urlPattern = "Visited:"; //This call will fail but returns the size required in structSize //to allocate necessary buffer IntPtr hEnum = FindFirstUrlCacheEntry(null, buffer, out structSize); try { if (hEnum == IntPtr.Zero) { int lastError = Marshal.GetLastWin32Error(); if (lastError == Hresults.ERROR_INSUFFICIENT_BUFFER) { //Allocate buffer buffer = Marshal.AllocHGlobal((int)structSize); //Call again, this time it should succeed //hEnum = FindFirstUrlCacheEntry(urlPattern, buffer, out structSize); hEnum = FindFirstUrlCacheEntry(null, buffer, out structSize); } else if (lastError == Hresults.ERROR_NO_MORE_ITEMS) { Console.Error.WriteLine("No entries in IE's history cache"); //return; return(filesList); } else if (lastError != Hresults.ERROR_SUCCESS) { Console.Error.WriteLine("Unable to fetch entries from IE's history cache"); //return; return(filesList); } } INTERNET_CACHE_ENTRY_INFO result = (INTERNET_CACHE_ENTRY_INFO)Marshal.PtrToStructure(buffer, typeof(INTERNET_CACHE_ENTRY_INFO)); //writer.WriteLine(result.lpszSourceUrlName); string fileUrl = result.lpszSourceUrlName.Substring(result.lpszSourceUrlName.LastIndexOf('@') + 1); if (fileUrl.Contains(sourceUrlFilter) && fileUrl.EndsWith(fileExtensionFilter)) { //Console.WriteLine(fileUrl); filesList.Add(fileUrl); } // Free the buffer if (buffer != IntPtr.Zero) { try { Marshal.FreeHGlobal(buffer); } catch { } buffer = IntPtr.Zero; structSize = 0; } //Loop through all entries, attempt to find matches while (true) { long nextResult = FindNextUrlCacheEntry(hEnum, buffer, out structSize); if (nextResult != 1) //TRUE { int lastError = Marshal.GetLastWin32Error(); if (lastError == Hresults.ERROR_INSUFFICIENT_BUFFER) { buffer = Marshal.AllocHGlobal((int)structSize); nextResult = FindNextUrlCacheEntry(hEnum, buffer, out structSize); } else if (lastError == Hresults.ERROR_NO_MORE_ITEMS) { break; } } result = (INTERNET_CACHE_ENTRY_INFO)Marshal.PtrToStructure(buffer, typeof(INTERNET_CACHE_ENTRY_INFO)); //writer.WriteLine(result.lpszSourceUrlName); fileUrl = result.lpszSourceUrlName.Substring(result.lpszSourceUrlName.LastIndexOf('@') + 1); if (fileUrl.Contains(sourceUrlFilter) && fileUrl.EndsWith(fileExtensionFilter)) { //Console.WriteLine(fileUrl); filesList.Add(fileUrl); } if (buffer != IntPtr.Zero) { try { Marshal.FreeHGlobal(buffer); } catch { } buffer = IntPtr.Zero; structSize = 0; } } } finally { if (hEnum != IntPtr.Zero) { FindCloseUrlCache(hEnum); } if (buffer != IntPtr.Zero) { try { Marshal.FreeHGlobal(buffer); } catch { } } } return(filesList); }
/// <summary> /// UrlCache functionality is taken from: /// Scott McMaster ([email protected]) /// CodeProject article /// /// There were some issues with preparing URLs /// for RegExp to work properly. This is /// demonstrated in AllForms.SetupCookieCachePattern method /// /// urlPattern: /// . Dump the entire contents of the cache. /// Cookie: Lists all cookies on the system. /// Visited: Lists all of the history items. /// Cookie:.*\.example\.com Lists cookies from the example.com domain. /// http://www.example.com/example.html$: Lists the specific named file if present /// \.example\.com: Lists any and all entries from *.example.com. /// \.example\.com.*\.gif$: Lists the .gif files from *.example.com. /// \.js$: Lists the .js files in the cache. /// </summary> /// <param name="urlPattern"></param> /// <returns></returns> public static ArrayList FindUrlCacheEntries(string urlPattern) { ArrayList results = new ArrayList(); IntPtr buffer = IntPtr.Zero; UInt32 structSize; //This call will fail but returns the size required in structSize //to allocate necessary buffer IntPtr hEnum = FindFirstUrlCacheEntry(null, buffer, out structSize); try { if (hEnum == IntPtr.Zero) { int lastError = Marshal.GetLastWin32Error(); if (lastError == ERROR_INSUFFICIENT_BUFFER) { //Allocate buffer buffer = Marshal.AllocHGlobal((int)structSize); //Call again, this time it should succeed hEnum = FindFirstUrlCacheEntry(urlPattern, buffer, out structSize); } else if (lastError == ERROR_NO_MORE_ITEMS) { return(results); } } INTERNET_CACHE_ENTRY_INFO result = (INTERNET_CACHE_ENTRY_INFO)Marshal.PtrToStructure(buffer, typeof(INTERNET_CACHE_ENTRY_INFO)); try { if (Regex.IsMatch(result.lpszSourceUrlName, urlPattern, RegexOptions.IgnoreCase)) { results.Add(result); } } catch (ArgumentException ae) { throw new ApplicationException("Invalid regular expression, details=" + ae.Message); } if (buffer != IntPtr.Zero) { try { Marshal.FreeHGlobal(buffer); } catch { } buffer = IntPtr.Zero; structSize = 0; } //Loop through all entries, attempt to find matches while (true) { long nextResult = FindNextUrlCacheEntry(hEnum, buffer, out structSize); if (nextResult != 1) //TRUE { int lastError = Marshal.GetLastWin32Error(); if (lastError == ERROR_INSUFFICIENT_BUFFER) { buffer = Marshal.AllocHGlobal((int)structSize); nextResult = FindNextUrlCacheEntry(hEnum, buffer, out structSize); } else if (lastError == ERROR_NO_MORE_ITEMS) { break; } } result = (INTERNET_CACHE_ENTRY_INFO)Marshal.PtrToStructure(buffer, typeof(INTERNET_CACHE_ENTRY_INFO)); if (Regex.IsMatch(result.lpszSourceUrlName, urlPattern, RegexOptions.IgnoreCase)) { results.Add(result); } if (buffer != IntPtr.Zero) { try { Marshal.FreeHGlobal(buffer); } catch { } buffer = IntPtr.Zero; structSize = 0; } } } finally { if (hEnum != IntPtr.Zero) { FindCloseUrlCache(hEnum); } if (buffer != IntPtr.Zero) { try { Marshal.FreeHGlobal(buffer); } catch { } } } return(results); }
private void DeleteUrlCacheEntryIfUrlMatches(INTERNET_CACHE_ENTRY_INFO entry) { string cacheEntryName = Marshal.PtrToStringUni(entry.lpszSourceUrlName); if (cacheEntrySuffixes != null) { foreach (string suffix in cacheEntrySuffixes) { if (cacheEntryName.EndsWith(suffix)) goto Match; } return; } Match: Logger.LogAction(String.Format("Deleting '{0}'.", cacheEntryName)); if (!DeleteUrlCacheEntry(entry.lpszSourceUrlName)) ThrowExceptionForLastWin32Error(); }