Piotr Caban : wininet: Added support for leaked urlcache entries handling.
Alexandre Julliard
julliard at winehq.org
Wed Sep 19 13:39:46 CDT 2012
Module: wine
Branch: master
Commit: b7010348cfc53674913733b72033ee16a6868f99
URL: http://source.winehq.org/git/wine.git/?a=commit;h=b7010348cfc53674913733b72033ee16a6868f99
Author: Piotr Caban <piotr at codeweavers.com>
Date: Wed Sep 19 15:30:03 2012 +0200
wininet: Added support for leaked urlcache entries handling.
---
dlls/wininet/urlcache.c | 170 ++++++++++++++++++++++++++++++-----------------
1 files changed, 109 insertions(+), 61 deletions(-)
diff --git a/dlls/wininet/urlcache.c b/dlls/wininet/urlcache.c
index 04ecd80..3a028b5 100644
--- a/dlls/wininet/urlcache.c
+++ b/dlls/wininet/urlcache.c
@@ -82,6 +82,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(wininet);
#define PENDING_DELETE_CACHE_ENTRY 0x00400000
+#define CACHE_HEADER_DATA_ROOT_LEAK_OFFSET 0x16
+
#define DWORD_SIG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24))
#define URL_SIGNATURE DWORD_SIG('U','R','L',' ')
#define REDR_SIGNATURE DWORD_SIG('R','E','D','R')
@@ -752,44 +754,6 @@ static BOOL URLCacheContainer_UnlockIndex(URLCACHECONTAINER * pContainer, LPURLC
return UnmapViewOfFile(pHeader);
}
-/***********************************************************************
- * URLCacheContainer_CleanIndex (Internal)
- *
- * This function is meant to make place in index file by removing old
- * entries and resizing the file.
- *
- * CAUTION: file view may get mapped to new memory
- * TODO: implement entries cleaning
- *
- * RETURNS
- * ERROR_SUCCESS when new memory is available
- * error code otherwise
- */
-static DWORD URLCacheContainer_CleanIndex(URLCACHECONTAINER *container, URLCACHE_HEADER **file_view)
-{
- URLCACHE_HEADER *header = *file_view;
- DWORD ret;
-
- FIXME("(%s %s) semi-stub\n", debugstr_w(container->cache_prefix), debugstr_w(container->path));
-
- if(header->dwFileSize >= ALLOCATION_TABLE_SIZE*8*BLOCKSIZE + ENTRY_START_OFFSET) {
- WARN("index file has maximal size\n");
- return ERROR_NOT_ENOUGH_MEMORY;
- }
-
- URLCacheContainer_CloseIndex(container);
- ret = URLCacheContainer_OpenIndex(container, header->dwIndexCapacityInBlocks*2);
- if(ret != ERROR_SUCCESS)
- return ret;
- header = MapViewOfFile(container->hMapping, FILE_MAP_WRITE, 0, 0, 0);
- if(!header)
- return GetLastError();
-
- UnmapViewOfFile(*file_view);
- *file_view = header;
- return ERROR_SUCCESS;
-}
-
#ifndef CHAR_BIT
#define CHAR_BIT (8 * sizeof(CHAR))
#endif
@@ -996,6 +960,107 @@ static BOOL URLCache_LocalFileNameToPathA(
return FALSE;
}
+/***********************************************************************
+ * URLCache_DeleteFile (Internal)
+ */
+static DWORD URLCache_DeleteFile(const URLCACHECONTAINER *container,
+ URLCACHE_HEADER *header, URL_CACHEFILE_ENTRY *url_entry)
+{
+ WCHAR path[MAX_PATH];
+ LONG path_size = sizeof(path);
+ DWORD err;
+
+ if(!url_entry->dwOffsetLocalName)
+ goto succ;
+
+ if(!URLCache_LocalFileNameToPathW(container, header,
+ (LPCSTR)url_entry+url_entry->dwOffsetLocalName,
+ url_entry->CacheDir, path, &path_size))
+ goto succ;
+
+ err = (DeleteFileW(path) ? ERROR_SUCCESS : GetLastError());
+ if(err == ERROR_ACCESS_DENIED || err == ERROR_SHARING_VIOLATION)
+ return err;
+
+succ:
+ if (url_entry->CacheDir < header->DirectoryCount)
+ {
+ if (header->directory_data[url_entry->CacheDir].dwNumFiles)
+ header->directory_data[url_entry->CacheDir].dwNumFiles--;
+ }
+ if (url_entry->CacheEntryType & STICKY_CACHE_ENTRY)
+ {
+ if (url_entry->size.QuadPart < header->ExemptUsage.QuadPart)
+ header->ExemptUsage.QuadPart -= url_entry->size.QuadPart;
+ else
+ header->ExemptUsage.QuadPart = 0;
+ }
+ else
+ {
+ if (url_entry->size.QuadPart < header->CacheUsage.QuadPart)
+ header->CacheUsage.QuadPart -= url_entry->size.QuadPart;
+ else
+ header->CacheUsage.QuadPart = 0;
+ }
+
+ return ERROR_SUCCESS;
+}
+
+/***********************************************************************
+ * URLCacheContainer_CleanIndex (Internal)
+ *
+ * This function is meant to make place in index file by removing leaked
+ * files entries and resizing the file.
+ *
+ * CAUTION: file view may get mapped to new memory
+ *
+ * RETURNS
+ * ERROR_SUCCESS when new memory is available
+ * error code otherwise
+ */
+static DWORD URLCacheContainer_CleanIndex(URLCACHECONTAINER *container, URLCACHE_HEADER **file_view)
+{
+ URLCACHE_HEADER *header = *file_view;
+ DWORD ret;
+ DWORD *leak_off;
+ BOOL freed = FALSE;
+
+ TRACE("(%s %s)\n", debugstr_w(container->cache_prefix), debugstr_w(container->path));
+
+ leak_off = &(*file_view)->options[CACHE_HEADER_DATA_ROOT_LEAK_OFFSET];
+ while(*leak_off) {
+ URL_CACHEFILE_ENTRY *url_entry = (URL_CACHEFILE_ENTRY*)((LPBYTE)(*file_view) + *leak_off);
+
+ if(SUCCEEDED(URLCache_DeleteFile(container, *file_view, url_entry))) {
+ *leak_off = url_entry->dwExemptDelta;
+ URLCache_DeleteEntry(*file_view, &url_entry->CacheFileEntry);
+ freed = TRUE;
+ }else {
+ leak_off = &url_entry->dwExemptDelta;
+ }
+ }
+
+ if(freed)
+ return ERROR_SUCCESS;
+
+ if(header->dwFileSize >= ALLOCATION_TABLE_SIZE*8*BLOCKSIZE + ENTRY_START_OFFSET) {
+ WARN("index file has maximal size\n");
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
+ URLCacheContainer_CloseIndex(container);
+ ret = URLCacheContainer_OpenIndex(container, header->dwIndexCapacityInBlocks*2);
+ if(ret != ERROR_SUCCESS)
+ return ret;
+ header = MapViewOfFile(container->hMapping, FILE_MAP_WRITE, 0, 0, 0);
+ if(!header)
+ return GetLastError();
+
+ UnmapViewOfFile(*file_view);
+ *file_view = header;
+ return ERROR_SUCCESS;
+}
+
/* Just like DosDateTimeToFileTime, except that it also maps the special
* case of a DOS date/time of (0,0) to a filetime of (0,0).
*/
@@ -2218,8 +2283,6 @@ static BOOL DeleteUrlCacheEntryInternal(const URLCACHECONTAINER * pContainer,
{
CACHEFILE_ENTRY * pEntry;
URL_CACHEFILE_ENTRY * pUrlEntry;
- WCHAR path[MAX_PATH];
- LONG path_size = sizeof(path);
pEntry = (CACHEFILE_ENTRY *)((LPBYTE)pHeader + pHashEntry->dwOffsetEntry);
if (pEntry->dwSignature != URL_SIGNATURE)
@@ -2239,33 +2302,18 @@ static BOOL DeleteUrlCacheEntryInternal(const URLCACHECONTAINER * pContainer,
return FALSE;
}
- if (pUrlEntry->CacheDir < pHeader->DirectoryCount)
+ if(!URLCache_DeleteFile(pContainer, pHeader, pUrlEntry))
{
- if (pHeader->directory_data[pUrlEntry->CacheDir].dwNumFiles)
- pHeader->directory_data[pUrlEntry->CacheDir].dwNumFiles--;
- }
- if (pUrlEntry->CacheEntryType & STICKY_CACHE_ENTRY)
- {
- if (pUrlEntry->size.QuadPart < pHeader->ExemptUsage.QuadPart)
- pHeader->ExemptUsage.QuadPart -= pUrlEntry->size.QuadPart;
- else
- pHeader->ExemptUsage.QuadPart = 0;
+ URLCache_DeleteEntry(pHeader, pEntry);
}
else
{
- if (pUrlEntry->size.QuadPart < pHeader->CacheUsage.QuadPart)
- pHeader->CacheUsage.QuadPart -= pUrlEntry->size.QuadPart;
- else
- pHeader->CacheUsage.QuadPart = 0;
- }
-
- if (pUrlEntry->dwOffsetLocalName && URLCache_LocalFileNameToPathW(pContainer, pHeader,
- (LPCSTR)pUrlEntry+pUrlEntry->dwOffsetLocalName, pUrlEntry->CacheDir, path, &path_size))
- {
- DeleteFileW(path);
+ /* Add entry to leaked files list */
+ pUrlEntry->CacheFileEntry.dwSignature = LEAK_SIGNATURE;
+ pUrlEntry->dwExemptDelta = pHeader->options[CACHE_HEADER_DATA_ROOT_LEAK_OFFSET];
+ pHeader->options[CACHE_HEADER_DATA_ROOT_LEAK_OFFSET] = pHashEntry->dwOffsetEntry;
}
- URLCache_DeleteEntry(pHeader, pEntry);
URLCache_DeleteEntryFromHash(pHashEntry);
return TRUE;
}
More information about the wine-cvs
mailing list