📄 urlcache.c
字号:
}
else if (j >= 255)
{
/* Give up. The most likely cause of this
* is a full disk, but whatever the cause
* is, it should be more than apparent that
* we won't succeed.
*/
dwError = GetLastError();
break;
}
}
}
UnmapViewOfFile(pHeader);
}
else
{
dwError = GetLastError();
}
CloseHandle(hMapping);
}
else
{
dwError = GetLastError();
}
}
if (dwError)
{
CloseHandle(hFile);
DeleteFileW(wszFilePath);
ReleaseMutex(pContainer->hMutex);
SetLastError(dwError);
return FALSE;
}
}
ReleaseMutex(pContainer->hMutex);
wsprintfW(wszFilePath, wszMappingFormat, pContainer->path, wszIndex, dwFileSize);
URLCache_PathToObjectName(wszFilePath, '_');
pContainer->hMapping = OpenFileMappingW(FILE_MAP_WRITE, FALSE, wszFilePath);
if (!pContainer->hMapping)
pContainer->hMapping = CreateFileMappingW(hFile, NULL, PAGE_READWRITE, 0, 0, wszFilePath);
CloseHandle(hFile);
if (!pContainer->hMapping)
{
ERR("Couldn't create file mapping (error is %ld)\n", GetLastError());
return FALSE;
}
return TRUE;
}
/***********************************************************************
* URLCacheContainer_CloseIndex (Internal)
*
* Closes the index
*
* RETURNS
* nothing
*
*/
static void URLCacheContainer_CloseIndex(URLCACHECONTAINER * pContainer)
{
CloseHandle(pContainer->hMapping);
pContainer->hMapping = NULL;
}
static BOOL URLCacheContainers_AddContainer(LPCWSTR cache_prefix, LPCWSTR path, LPWSTR mutex_name)
{
URLCACHECONTAINER * pContainer = HeapAlloc(GetProcessHeap(), 0, sizeof(URLCACHECONTAINER));
int path_len = strlenW(path);
int cache_prefix_len = strlenW(cache_prefix);
if (!pContainer)
{
return FALSE;
}
pContainer->hMapping = NULL;
pContainer->file_size = 0;
pContainer->path = HeapAlloc(GetProcessHeap(), 0, (path_len + 1) * sizeof(WCHAR));
if (!pContainer->path)
{
HeapFree(GetProcessHeap(), 0, pContainer);
return FALSE;
}
memcpy(pContainer->path, path, (path_len + 1) * sizeof(WCHAR));
pContainer->cache_prefix = HeapAlloc(GetProcessHeap(), 0, (cache_prefix_len + 1) * sizeof(WCHAR));
if (!pContainer->cache_prefix)
{
HeapFree(GetProcessHeap(), 0, pContainer->path);
HeapFree(GetProcessHeap(), 0, pContainer);
return FALSE;
}
memcpy(pContainer->cache_prefix, cache_prefix, (cache_prefix_len + 1) * sizeof(WCHAR));
CharLowerW(mutex_name);
URLCache_PathToObjectName(mutex_name, '!');
if ((pContainer->hMutex = CreateMutexW(NULL, FALSE, mutex_name)) == NULL)
{
ERR("couldn't create mutex (error is %ld)\n", GetLastError());
HeapFree(GetProcessHeap(), 0, pContainer->path);
HeapFree(GetProcessHeap(), 0, pContainer);
return FALSE;
}
list_add_head(&UrlContainers, &pContainer->entry);
return TRUE;
}
static void URLCacheContainer_DeleteContainer(URLCACHECONTAINER * pContainer)
{
list_remove(&pContainer->entry);
URLCacheContainer_CloseIndex(pContainer);
CloseHandle(pContainer->hMutex);
HeapFree(GetProcessHeap(), 0, pContainer->path);
HeapFree(GetProcessHeap(), 0, pContainer->cache_prefix);
HeapFree(GetProcessHeap(), 0, pContainer);
}
void URLCacheContainers_CreateDefaults(void)
{
static const WCHAR UrlSuffix[] = {'C','o','n','t','e','n','t','.','I','E','5',0};
static const WCHAR UrlPrefix[] = {0};
static const WCHAR HistorySuffix[] = {'H','i','s','t','o','r','y','.','I','E','5',0};
static const WCHAR HistoryPrefix[] = {'V','i','s','i','t','e','d',':',0};
static const WCHAR CookieSuffix[] = {0};
static const WCHAR CookiePrefix[] = {'C','o','o','k','i','e',':',0};
static const struct
{
int nFolder; /* CSIDL_* constant */
const WCHAR * shpath_suffix; /* suffix on path returned by SHGetSpecialFolderPath */
const WCHAR * cache_prefix; /* prefix used to reference the container */
} DefaultContainerData[] =
{
{ CSIDL_INTERNET_CACHE, UrlSuffix, UrlPrefix },
{ CSIDL_HISTORY, HistorySuffix, HistoryPrefix },
{ CSIDL_COOKIES, CookieSuffix, CookiePrefix },
};
DWORD i;
for (i = 0; i < sizeof(DefaultContainerData) / sizeof(DefaultContainerData[0]); i++)
{
WCHAR wszCachePath[MAX_PATH];
WCHAR wszMutexName[MAX_PATH];
int path_len, suffix_len;
if (FAILED(SHGetSpecialFolderPathW(NULL, wszCachePath, DefaultContainerData[i].nFolder, TRUE)))
{
ERR("Couldn't get path for default container %lu\n", i);
continue;
}
path_len = strlenW(wszCachePath);
suffix_len = strlenW(DefaultContainerData[i].shpath_suffix);
if (path_len + suffix_len + 2 > MAX_PATH)
{
ERR("Path too long\n");
continue;
}
wszCachePath[path_len] = '\\';
strcpyW(wszMutexName, wszCachePath);
if (suffix_len)
{
memcpy(wszCachePath + path_len + 1, DefaultContainerData[i].shpath_suffix, (suffix_len + 1) * sizeof(WCHAR));
wszCachePath[path_len + suffix_len + 1] = '\\';
wszCachePath[path_len + suffix_len + 2] = '\0';
}
URLCacheContainers_AddContainer(DefaultContainerData[i].cache_prefix, wszCachePath, wszMutexName);
}
}
void URLCacheContainers_DeleteAll(void)
{
while(!list_empty(&UrlContainers))
URLCacheContainer_DeleteContainer(
LIST_ENTRY(list_head(&UrlContainers), URLCACHECONTAINER, entry)
);
}
static BOOL URLCacheContainers_FindContainerW(LPCWSTR lpwszUrl, URLCACHECONTAINER ** ppContainer)
{
struct list * cursor;
TRACE("searching for prefix for URL: %s\n", debugstr_w(lpwszUrl));
LIST_FOR_EACH(cursor, &UrlContainers)
{
URLCACHECONTAINER * pContainer = LIST_ENTRY(cursor, URLCACHECONTAINER, entry);
int prefix_len = strlenW(pContainer->cache_prefix);
if (!strncmpW(pContainer->cache_prefix, lpwszUrl, prefix_len))
{
TRACE("found container with prefx %s for URL %s\n", debugstr_w(pContainer->cache_prefix), debugstr_w(lpwszUrl));
*ppContainer = pContainer;
return TRUE;
}
}
ERR("no container found\n");
SetLastError(ERROR_FILE_NOT_FOUND);
return FALSE;
}
static BOOL URLCacheContainers_FindContainerA(LPCSTR lpszUrl, URLCACHECONTAINER ** ppContainer)
{
BOOL ret;
LPWSTR lpwszUrl;
int url_len = MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, NULL, 0);
if (url_len && (lpwszUrl = HeapAlloc(GetProcessHeap(), 0, url_len * sizeof(WCHAR))))
{
MultiByteToWideChar(CP_ACP, 0, lpszUrl, -1, lpwszUrl, url_len);
ret = URLCacheContainers_FindContainerW(lpwszUrl, ppContainer);
HeapFree(GetProcessHeap(), 0, lpwszUrl);
return ret;
}
return FALSE;
}
/***********************************************************************
* URLCacheContainer_LockIndex (Internal)
*
*/
static LPURLCACHE_HEADER URLCacheContainer_LockIndex(URLCACHECONTAINER * pContainer)
{
BYTE index;
LPVOID pIndexData;
URLCACHE_HEADER * pHeader;
/* acquire mutex */
WaitForSingleObject(pContainer->hMutex, INFINITE);
pIndexData = MapViewOfFile(pContainer->hMapping, FILE_MAP_WRITE, 0, 0, 0);
if (!pIndexData)
{
ReleaseMutex(pContainer->hMutex);
ERR("Couldn't MapViewOfFile. Error: %ld\n", GetLastError());
return FALSE;
}
pHeader = (URLCACHE_HEADER *)pIndexData;
/* file has grown - we need to remap to prevent us getting
* access violations when we try and access beyond the end
* of the memory mapped file */
if (pHeader->dwFileSize != pContainer->file_size)
{
URLCacheContainer_CloseIndex(pContainer);
if (!URLCacheContainer_OpenIndex(pContainer))
{
ReleaseMutex(pContainer->hMutex);
return FALSE;
}
pIndexData = MapViewOfFile(pContainer->hMapping, FILE_MAP_WRITE, 0, 0, 0);
if (!pIndexData)
{
ReleaseMutex(pContainer->hMutex);
ERR("Couldn't MapViewOfFile. Error: %ld\n", GetLastError());
return FALSE;
}
pHeader = (URLCACHE_HEADER *)pIndexData;
}
TRACE("Signature: %s, file size: %ld bytes\n", pHeader->szSignature, pHeader->dwFileSize);
for (index = 0; index < pHeader->DirectoryCount; index++)
{
TRACE("Directory[%d] = \"%.8s\"\n", index, pHeader->directory_data[index].filename);
}
return pHeader;
}
/***********************************************************************
* URLCacheContainer_UnlockIndex (Internal)
*
*/
static BOOL URLCacheContainer_UnlockIndex(URLCACHECONTAINER * pContainer, LPURLCACHE_HEADER pHeader)
{
/* release mutex */
ReleaseMutex(pContainer->hMutex);
return UnmapViewOfFile(pHeader);
}
#ifndef CHAR_BIT
#define CHAR_BIT (8 * sizeof(CHAR))
#endif
/***********************************************************************
* URLCache_Allocation_BlockIsFree (Internal)
*
* Is the specified block number free?
*
* RETURNS
* zero if free
* non-zero otherwise
*
*/
static inline BYTE URLCache_Allocation_BlockIsFree(BYTE * AllocationTable, DWORD dwBlockNumber)
{
BYTE mask = 1 << (dwBlockNumber % CHAR_BIT);
return (AllocationTable[dwBlockNumber / CHAR_BIT] & mask) == 0;
}
/***********************************************************************
* URLCache_Allocation_BlockFree (Internal)
*
* Marks the specified block as free
*
* RETURNS
* nothing
*
*/
static inline void URLCache_Allocation_BlockFree(BYTE * AllocationTable, DWORD dwBlockNumber)
{
BYTE mask = ~(1 << (dwBlockNumber % CHAR_BIT));
AllocationTable[dwBlockNumber / CHAR_BIT] &= mask;
}
/***********************************************************************
* URLCache_Allocation_BlockAllocate (Internal)
*
* Marks the specified block as allocated
*
* RETURNS
* nothing
*
*/
static inline void URLCache_Allocation_BlockAllocate(BYTE * AllocationTable, DWORD dwBlockNumber)
{
BYTE mask = 1 << (dwBlockNumber % CHAR_BIT);
AllocationTable[dwBlockNumber / CHAR_BIT] |= mask;
}
/***********************************************************************
* URLCache_FindFirstFreeEntry (Internal)
*
* Finds and allocates the first block of free space big enough and
* sets ppEntry to point to it.
*
* RETURNS
* TRUE if it had enough space
* FALSE if it couldn't find enough space
*
*/
static BOOL URLCache_FindFirstFreeEntry(URLCACHE_HEADER * pHeader, DWORD dwBlocksNeeded, CACHEFILE_ENTRY ** ppEntry)
{
LPBYTE AllocationTable = (LPBYTE)pHeader + ALLOCATION_TABLE_OFFSET;
DWORD dwBlockNumber;
DWORD dwFreeCounter;
for (dwBlockNumber = 0; dwBlockNumber < pHeader->dwIndexCapacityInBlocks; dwBlockNumber++)
{
for (dwFreeCounter = 0;
dwFreeCounter < dwBlocksNeeded &&
dwFreeCounter + dwBlockNumber < pHeader->dwIndexCapacityInBlocks &&
URLCache_Allocation_BlockIsFree(AllocationTable, dwBlockNumber + dwFreeCounter);
dwFreeCounter++)
TRACE("Found free block at no. %ld (0x%lx)\n", dwBlockNumber, ENTRY_START_OFFSET + dwBlockNumber * BLOCKSIZE);
if (dwFreeCounter == dwBlocksNeeded)
{
DWORD index;
TRACE("Found free blocks starting at no. %ld (0x%lx)\n", dwBlockNumber, ENTRY_START_OFFSET + dwBlockNumber * BLOCKSIZE);
for (index = 0; index < dwBlocksNeeded; index++)
URLCache_Allocation_BlockAllocate(AllocationTable, dwBlockNumber + index);
*ppEntry = (CACHEFILE_ENTRY *)((LPBYTE)pHeader + ENTRY_START_OFFSET + dwBlockNumber * BLOCKSIZE);
(*ppEntry)->dwBlocksUsed = dwBlocksNeeded;
return TRUE;
}
}
FIXME("Grow file\n");
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -