You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1980 lines
59 KiB
1980 lines
59 KiB
/*++
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name: conmgr.cxx
|
|
|
|
Abstract:
|
|
|
|
Manages list of containers (CConList)
|
|
|
|
Author:
|
|
Adriaan Canter (adriaanc) 04-02-97
|
|
|
|
--*/
|
|
#include <wininetp.h>
|
|
#include <cache.hxx>
|
|
|
|
#define FAILSAFE_TIMEOUT (60000)
|
|
|
|
/*--------------------- Private Functions -----------------------------------*/
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::Init
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::Init()
|
|
{
|
|
DWORD dwError = ConfigureCache();
|
|
|
|
if (dwError==ERROR_SUCCESS)
|
|
{
|
|
// Get the extensible cache config info.
|
|
// These containers are delay-initialized.
|
|
dwError = GetExtensibleCacheConfigInfo(TRUE);
|
|
}
|
|
else
|
|
{
|
|
INET_ASSERT(FALSE);
|
|
}
|
|
return dwError;
|
|
|
|
}
|
|
|
|
#ifdef CHECKLOCK_PARANOID
|
|
void CConMgr::CheckNoLocks(DWORD dwThreadId)
|
|
{
|
|
URL_CONTAINER *co;
|
|
DWORD idx;
|
|
|
|
LOCK_CACHE();
|
|
for (idx = 0; idx < ConList.Size(); idx++)
|
|
{
|
|
URL_CONTAINER *co;
|
|
|
|
co = ConList.Get(idx);
|
|
if (co)
|
|
{
|
|
co->CheckNoLocks(dwThreadId);
|
|
co->Release(FALSE);
|
|
}
|
|
}
|
|
UNLOCK_CACHE();
|
|
}
|
|
#endif
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
BOOL CConMgr::WasModified
|
|
----------------------------------------------------------------------------*/
|
|
BOOL CConMgr::WasModified(BOOL fUpdateMemory)
|
|
{
|
|
DWORD dwOldCount = _dwModifiedCount;
|
|
return dwOldCount != ReadModifiedCount(fUpdateMemory);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::ReadModifiedCount
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::ReadModifiedCount(BOOL fUpdateMemory)
|
|
{
|
|
DWORD dwChangeCount;
|
|
DWORD *pdwChangeCount = fUpdateMemory ? &_dwModifiedCount : &dwChangeCount;
|
|
|
|
_coContent->GetHeaderData(CACHE_HEADER_DATA_CONLIST_CHANGE_COUNT,
|
|
pdwChangeCount);
|
|
return *pdwChangeCount;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::IncrementModifiedCount
|
|
----------------------------------------------------------------------------*/
|
|
void CConMgr::IncrementModifiedCount()
|
|
{
|
|
DWORD dwLocModified;
|
|
|
|
_coContent->IncrementHeaderData(CACHE_HEADER_DATA_CONLIST_CHANGE_COUNT,
|
|
&dwLocModified);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::InitFixedContainers
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::InitFixedContainers()
|
|
{
|
|
DWORD idx;
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
BOOL fInitSucceeded = TRUE;
|
|
|
|
// Create and init
|
|
_hMutexExtensible = OpenMutex(SYNCHRONIZE, FALSE, TEXT("_!MSFTHISTORY!_"));
|
|
if (_hMutexExtensible == NULL && (GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_INVALID_NAME))
|
|
{
|
|
SECURITY_ATTRIBUTES* psa = SHGetAllAccessSA();
|
|
if (psa)
|
|
{
|
|
_hMutexExtensible = CreateMutex(psa, FALSE, TEXT("_!MSFTHISTORY!_"));
|
|
}
|
|
}
|
|
if (_hMutexExtensible == NULL)
|
|
{
|
|
dwError = GetLastError();
|
|
fInitSucceeded = FALSE;
|
|
goto exit;
|
|
}
|
|
_dwLastUnmap = GetTickCountWrap();
|
|
|
|
LOCK_CACHE();
|
|
// Containers are configured. Attempt to initialize.
|
|
for (idx = CONTENT; idx < ConList.Size(); idx++)
|
|
{
|
|
URL_CONTAINER *co;
|
|
|
|
co = ConList.Get(idx);
|
|
if (co)
|
|
{
|
|
dwError = co->Init();
|
|
|
|
// NOTE - URL_CONTAINER::Init() returns ERROR_ALREADY_EXISTS
|
|
// only if the the existing memory mapped file has been opened
|
|
// successfully. If the memory mapped file was created, upgraded
|
|
// or corrupted (in both cases the mem mapped file will be reinited)
|
|
// the return value will be ERROR_SUCCESS.
|
|
|
|
if(dwError != ERROR_SUCCESS && dwError != ERROR_ALREADY_EXISTS)
|
|
{
|
|
fInitSucceeded = FALSE;
|
|
goto unlock_exit;
|
|
}
|
|
|
|
// Has the container been created, upgrade or corrupted?
|
|
if (dwError == ERROR_SUCCESS)
|
|
{
|
|
if(idx==CONTENT)
|
|
{
|
|
// Preload the content container.
|
|
LoadContent();
|
|
}
|
|
else if (idx==COOKIE)
|
|
{
|
|
CCookieLoader cl;
|
|
cl.LoadCookies(co);
|
|
}
|
|
}
|
|
co->Release(FALSE);
|
|
}
|
|
|
|
}
|
|
|
|
// Enable cachevu for CONTENT and HISTORY.
|
|
EnableCacheVu(_coContent->GetCachePath(), CONTENT);
|
|
EnableCacheVu(_coHistory->GetCachePath(), HISTORY);
|
|
|
|
unlock_exit:
|
|
|
|
UNLOCK_CACHE();
|
|
|
|
exit:
|
|
dwError = (fInitSucceeded ? ERROR_SUCCESS : ERROR_INTERNAL_ERROR);
|
|
if (!fInitSucceeded && _hMutexExtensible)
|
|
{
|
|
CloseHandle(_hMutexExtensible);
|
|
_hMutexExtensible = NULL;
|
|
}
|
|
INET_ASSERT(dwError == ERROR_SUCCESS);
|
|
return dwError;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::LoadContent()
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::LoadContent()
|
|
{
|
|
DWORD cbFile, dwError = ERROR_FILE_NOT_FOUND;
|
|
CHAR szPreloadKey[MAX_PATH],
|
|
szUrl[MAX_PATH],
|
|
szFile[MAX_PATH];
|
|
|
|
// Preload registry key string.
|
|
memcpy(szPreloadKey, OLD_CACHE_KEY, sizeof(OLD_CACHE_KEY) - 1);
|
|
szPreloadKey[sizeof(OLD_CACHE_KEY)-1] = '\\';
|
|
memcpy(szPreloadKey + sizeof(OLD_CACHE_KEY), "Preload", sizeof("PreLoad"));
|
|
|
|
// Construct preload registry object.
|
|
REGISTRY_OBJ roPreload(HKEY_CURRENT_USER, szPreloadKey);
|
|
REGISTRY_OBJ roIE5Preload;
|
|
if (roPreload.GetStatus() != ERROR_SUCCESS)
|
|
goto exit;
|
|
|
|
// Get the storage directory (cdf preload) to compare against to determine if we
|
|
// need to set EDITED_CACHE_ENTRY or not. We assume any preload entry not in the
|
|
// store dir IS and ECE.
|
|
DWORD cb;
|
|
CHAR szStorePath[MAX_PATH];
|
|
|
|
// Store dir is hardwired to "%windir%\Web\"
|
|
if ((cb = GetWindowsDirectory(szStorePath, MAX_PATH)))
|
|
{
|
|
AppendSlashIfNecessary(szStorePath, &cb);
|
|
memcpy(szStorePath + cb, WEBDIR_STRING, sizeof(WEBDIR_STRING));
|
|
cb += sizeof(WEBDIR_STRING) - 1; //cb now equals size of szStorePath.
|
|
}
|
|
|
|
|
|
// Enum the registry url/file values and commit them
|
|
// to the cache.
|
|
while (roPreload.FindNextValue(szUrl, MAX_PATH,
|
|
(LPBYTE) szFile, &(cbFile = MAX_PATH)) == ERROR_SUCCESS)
|
|
{
|
|
// Strip off any file:// off the file path/name.
|
|
CHAR* ptr = szFile;
|
|
|
|
if (!strnicmp(ptr, "file://", sizeof("file://") - 1))
|
|
ptr += sizeof("file://") - 1;
|
|
|
|
AddUrlArg Args;
|
|
memset(&Args, 0, sizeof(Args));
|
|
Args.pszUrl = szUrl;
|
|
Args.pszFilePath = ptr;
|
|
|
|
// If this is a Store entry, set the type to 0 else ECE
|
|
if (!strnicmp(ptr, szStorePath, cb))
|
|
Args.dwEntryType = 0;
|
|
else
|
|
Args.dwEntryType = EDITED_CACHE_ENTRY;
|
|
|
|
_coContent->AddUrl(&Args);
|
|
}
|
|
|
|
|
|
if (roIE5Preload.WorkWith(&roPreload, "IE5Preload")!=ERROR_SUCCESS)
|
|
goto exit;
|
|
|
|
DWORD cbMaxUrl, cbMaxEntry, cbEntry;
|
|
LPSTR pszUrl;
|
|
URL_FILEMAP_ENTRY *pEntry;
|
|
KEY_QUERY_INFO QueryInfo;
|
|
|
|
if (ERROR_SUCCESS != roIE5Preload.GetKeyInfo(&QueryInfo))
|
|
goto exit;
|
|
|
|
cbMaxUrl = QueryInfo.MaxValueNameLen + 1;
|
|
cbMaxEntry = QueryInfo.MaxValueLen + 1;
|
|
|
|
pszUrl = new CHAR[cbMaxUrl];
|
|
pEntry = (URL_FILEMAP_ENTRY*) new CHAR[cbMaxEntry];
|
|
|
|
if (!(pszUrl && pEntry))
|
|
goto exit;
|
|
|
|
|
|
__try
|
|
{
|
|
|
|
while ((dwError = roIE5Preload.FindNextValue(pszUrl, cbMaxUrl,
|
|
(LPBYTE) pEntry, &(cbEntry = cbMaxEntry))) == ERROR_SUCCESS)
|
|
{
|
|
FILETIME ft;
|
|
AddUrlArg Args;
|
|
memset(&Args, 0, sizeof(Args));
|
|
|
|
// Url
|
|
Args.pszUrl = pEntry->UrlNameOffset ?
|
|
(LPSTR) OFFSET_TO_POINTER(pEntry, pEntry->UrlNameOffset) : NULL;
|
|
|
|
// File path
|
|
Args.pszFilePath = pEntry->InternalFileNameOffset ?
|
|
(LPSTR) OFFSET_TO_POINTER(pEntry, pEntry->InternalFileNameOffset) : NULL;
|
|
|
|
// Header info
|
|
Args.pbHeaders = pEntry->HeaderInfoOffset ?
|
|
(LPSTR) OFFSET_TO_POINTER(pEntry, pEntry->HeaderInfoOffset) : NULL;
|
|
Args.cbHeaders = pEntry->HeaderInfoSize;
|
|
|
|
// Last modified.
|
|
Args.qwLastMod = pEntry->LastModifiedTime;
|
|
|
|
// Expires time.
|
|
DosTime2FileTime(pEntry->dostExpireTime, &ft);
|
|
Args.qwExpires = FT2LL(ft);
|
|
|
|
// Post check time.
|
|
DosTime2FileTime(pEntry->dostPostCheckTime, &ft);
|
|
Args.qwPostCheck = FT2LL(ft);
|
|
|
|
// File creation time.
|
|
DosTime2FileTime(pEntry->dostFileCreationTime, &ft);
|
|
Args.ftCreate = ft;
|
|
|
|
// File extension.
|
|
Args.pszFileExt = pEntry->FileExtensionOffset ?
|
|
(LPSTR) OFFSET_TO_POINTER(pEntry, pEntry->FileExtensionOffset) : NULL;
|
|
|
|
// Entry type.
|
|
Args.dwEntryType = pEntry->CacheEntryType;
|
|
|
|
// File size
|
|
Args.dwFileSize = pEntry->dwFileSize;
|
|
|
|
// Add the url.
|
|
_coContent->AddUrl(&Args);
|
|
}
|
|
|
|
} // __try
|
|
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
INET_ASSERT(FALSE);
|
|
dwError = GetLastError();
|
|
}
|
|
ENDEXCEPT
|
|
|
|
dwError = ERROR_SUCCESS;
|
|
|
|
if (pszUrl)
|
|
delete pszUrl;
|
|
if (pEntry)
|
|
delete pEntry;
|
|
|
|
exit:
|
|
return dwError;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
HANDLE CConMgr::FindFirstContainer
|
|
----------------------------------------------------------------------------*/
|
|
HANDLE CConMgr::FindFirstContainer(DWORD *pdwModified, LPINTERNET_CACHE_CONTAINER_INFOA lpContainerInfo, LPDWORD lpdwContainerInfoBufferSize, DWORD dwOptions)
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
CONTAINER_FIND_FIRST_HANDLE *pFind;
|
|
DWORD dwContainers = 0;
|
|
DWORD dwNames = 0;
|
|
DWORD dwPrefixes = 0;
|
|
DWORD dwLabels = 0;
|
|
DWORD dwTitles = 0;
|
|
DWORD dwTotal;
|
|
HANDLE hFind = NULL;
|
|
DWORD dwModified;
|
|
|
|
GetExtensibleCacheConfigInfo(FALSE);
|
|
|
|
LOCK_CACHE();
|
|
dwModified = *pdwModified;
|
|
*pdwModified = _dwModifiedCount;
|
|
|
|
|
|
if ((CACHE_FIND_CONTAINER_RETURN_NOCHANGE & dwOptions) == 0 ||
|
|
dwModified != *pdwModified)
|
|
{
|
|
for (DWORD i = NCONTAINERS; i < ConList.Size(); i++)
|
|
{
|
|
URL_CONTAINER *co = ConList.Get(i);
|
|
if (co)
|
|
{
|
|
if (co->IsVisible())
|
|
{
|
|
dwContainers++;
|
|
dwNames += strlen(co->GetCacheName()) + 1;
|
|
dwPrefixes += strlen(co->GetCachePrefix()) + 1;
|
|
dwLabels += strlen(co->GetVolumeLabel()) + 1;
|
|
dwTitles += strlen(co->GetVolumeTitle()) + 1;
|
|
}
|
|
co->Release(TRUE);
|
|
}
|
|
}
|
|
|
|
dwTotal = sizeof(CONTAINER_FIND_FIRST_HANDLE)+
|
|
dwContainers*(4 * sizeof(LPSTR)) +
|
|
(dwNames+dwPrefixes+dwLabels+dwTitles) * sizeof(char);
|
|
|
|
hFind = HandleMgr.Alloc (dwTotal);
|
|
if (hFind)
|
|
{
|
|
LPSTR ps;
|
|
|
|
pFind = (CONTAINER_FIND_FIRST_HANDLE*) HandleMgr.Map (hFind);
|
|
pFind->dwSignature = SIGNATURE_CONTAINER_FIND;
|
|
pFind->dwContainer = 0;
|
|
pFind->dwNumContainers = dwContainers;
|
|
if (dwContainers)
|
|
{
|
|
pFind->ppNames = (LPTSTR *) (((LPBYTE) pFind) + sizeof(CONTAINER_FIND_FIRST_HANDLE));
|
|
pFind->ppPrefixes = pFind->ppNames + dwContainers;
|
|
pFind->ppLabels = pFind->ppPrefixes + dwContainers;
|
|
pFind->ppTitles = pFind->ppLabels + dwContainers;
|
|
ps = (LPSTR) (((LPBYTE) pFind) +
|
|
sizeof(CONTAINER_FIND_FIRST_HANDLE)+
|
|
dwContainers*(4 * sizeof(LPSTR)));
|
|
dwContainers = 0;
|
|
|
|
for (DWORD i = NCONTAINERS; i < ConList.Size(); i++)
|
|
{
|
|
URL_CONTAINER *co = ConList.Get(i);
|
|
if (co)
|
|
{
|
|
if (co->IsVisible())
|
|
{
|
|
pFind->ppNames[dwContainers] = ps;
|
|
strcpy(ps, co->GetCacheName());
|
|
ps += strlen(co->GetCacheName()) + 1;
|
|
pFind->ppPrefixes[dwContainers] = ps;
|
|
strcpy(ps, co->GetCachePrefix());
|
|
ps += strlen(co->GetCachePrefix()) + 1;
|
|
pFind->ppLabels[dwContainers] = ps;
|
|
strcpy(ps, co->GetVolumeLabel());
|
|
ps += strlen(co->GetVolumeLabel()) + 1;
|
|
pFind->ppTitles[dwContainers] = ps;
|
|
strcpy(ps, co->GetVolumeTitle());
|
|
ps += strlen(co->GetVolumeTitle()) + 1;
|
|
|
|
dwContainers++;
|
|
}
|
|
co->Release(TRUE);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwError = ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwError = ERROR_WINHTTP_NO_NEW_CONTAINERS;
|
|
}
|
|
UNLOCK_CACHE();
|
|
|
|
if (hFind)
|
|
{
|
|
if (FindNextContainer(hFind, lpContainerInfo, lpdwContainerInfoBufferSize))
|
|
dwError = ERROR_SUCCESS;
|
|
else
|
|
dwError = GetLastError();
|
|
}
|
|
if( dwError != ERROR_SUCCESS )
|
|
{
|
|
FreeFindHandle(hFind);
|
|
SetLastError(dwError);
|
|
return NULL;
|
|
}
|
|
return hFind;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
BOOL CConMgr::FindNextContainer
|
|
----------------------------------------------------------------------------*/
|
|
BOOL CConMgr::FindNextContainer(HANDLE hFind, LPINTERNET_CACHE_CONTAINER_INFOA lpContainerInfo, LPDWORD lpdwContainerInfoBufferSize)
|
|
{
|
|
// BUGBUG - this logic is borrowed from the original cachapia.cxx.
|
|
|
|
DWORD dwError;
|
|
CONTAINER_FIND_FIRST_HANDLE* pFind;
|
|
|
|
// Map and validate the handle.
|
|
LOCK_CACHE();
|
|
pFind = (CONTAINER_FIND_FIRST_HANDLE*) HandleMgr.Map (hFind);
|
|
UNLOCK_CACHE();
|
|
if (!pFind || pFind->dwSignature != SIGNATURE_CONTAINER_FIND ||
|
|
!lpContainerInfo ||
|
|
*lpdwContainerInfoBufferSize < sizeof(INTERNET_CACHE_CONTAINER_INFOA))
|
|
{
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
goto exit;
|
|
}
|
|
|
|
// Continue the enumeration.
|
|
if (pFind->dwContainer < pFind->dwNumContainers)
|
|
{
|
|
DWORD cbName = strlen(pFind->ppNames[pFind->dwContainer])+1;
|
|
DWORD cbPrefix = strlen(pFind->ppPrefixes[pFind->dwContainer])+1;
|
|
DWORD cbLabel = strlen(pFind->ppLabels[pFind->dwContainer])+1;
|
|
DWORD cbTitle = strlen(pFind->ppTitles[pFind->dwContainer])+1;
|
|
|
|
DWORD cbTotal = cbName+cbPrefix+cbLabel+cbTitle+sizeof(INTERNET_CACHE_CONTAINER_INFOA);
|
|
if (cbTotal > *lpdwContainerInfoBufferSize)
|
|
{
|
|
dwError = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
else
|
|
{
|
|
lpContainerInfo->lpszName = (LPSTR) (((LPBYTE) lpContainerInfo) +
|
|
sizeof(INTERNET_CACHE_CONTAINER_INFOA));
|
|
lpContainerInfo->lpszCachePrefix = lpContainerInfo->lpszName + cbName;
|
|
lpContainerInfo->lpszVolumeLabel = lpContainerInfo->lpszCachePrefix + cbPrefix;
|
|
lpContainerInfo->lpszVolumeTitle = lpContainerInfo->lpszVolumeLabel + cbLabel;
|
|
|
|
strcpy(lpContainerInfo->lpszName, pFind->ppNames[pFind->dwContainer]);
|
|
strcpy(lpContainerInfo->lpszCachePrefix, pFind->ppPrefixes[pFind->dwContainer]);
|
|
strcpy(lpContainerInfo->lpszVolumeLabel, pFind->ppLabels[pFind->dwContainer]);
|
|
strcpy(lpContainerInfo->lpszVolumeTitle, pFind->ppTitles[pFind->dwContainer]);
|
|
lpContainerInfo->dwCacheVersion = URL_CACHE_VERSION_NUM;
|
|
pFind->dwContainer++;
|
|
dwError = ERROR_SUCCESS;
|
|
}
|
|
*lpdwContainerInfoBufferSize = cbTotal;
|
|
}
|
|
else
|
|
{
|
|
dwError = ERROR_NO_MORE_ITEMS;
|
|
}
|
|
|
|
exit:
|
|
if (dwError != ERROR_SUCCESS)
|
|
{
|
|
SetLastError(dwError);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::GetContainerInfo
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::GetContainerInfo(LPSTR szUrl,
|
|
LPINTERNET_CACHE_CONTAINER_INFOA pCI,
|
|
LPDWORD pcbCI)
|
|
{
|
|
URL_CONTAINER *co;
|
|
DWORD dwError;
|
|
|
|
// Find the associated container.
|
|
DWORD idx;
|
|
|
|
LOCK_CACHE();
|
|
|
|
idx = FindIndexFromPrefix(szUrl);
|
|
co = ConList.Get(idx);
|
|
|
|
if (co)
|
|
{
|
|
DWORD cbName = strlen(co->GetCacheName()) + 1;
|
|
DWORD cbPrefix = strlen(co->GetCachePrefix()) + 1;
|
|
DWORD cbLabel = strlen(co->GetVolumeLabel()) + 1;
|
|
DWORD cbTitle = strlen(co->GetVolumeTitle()) + 1;
|
|
DWORD cbReq = cbName + cbPrefix + cbLabel + cbTitle;
|
|
if (cbReq > *pcbCI)
|
|
{
|
|
*pcbCI = cbReq;
|
|
dwError = ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
else
|
|
{
|
|
pCI->lpszName = (LPSTR) (((LPBYTE) pCI) +
|
|
sizeof(INTERNET_CACHE_CONTAINER_INFOA));
|
|
|
|
pCI->lpszCachePrefix = pCI->lpszName + cbName;
|
|
pCI->lpszVolumeLabel = pCI->lpszName + cbName + cbPrefix;
|
|
pCI->lpszVolumeTitle = pCI->lpszName + cbName + cbPrefix + cbLabel;
|
|
|
|
memcpy(pCI->lpszName, co->GetCacheName(), cbName);
|
|
memcpy(pCI->lpszCachePrefix, co->GetCachePrefix(), cbPrefix);
|
|
memcpy(pCI->lpszVolumeLabel, co->GetVolumeLabel(), cbLabel);
|
|
memcpy(pCI->lpszVolumeTitle, co->GetVolumeTitle(), cbTitle);
|
|
pCI->dwCacheVersion = URL_CACHE_VERSION_NUM;
|
|
|
|
*pcbCI = cbReq;
|
|
dwError = ERROR_SUCCESS;
|
|
}
|
|
|
|
co->Release(TRUE);
|
|
}
|
|
else
|
|
{
|
|
dwError = ERROR_WINHTTP_INTERNAL_ERROR;
|
|
}
|
|
|
|
UNLOCK_CACHE();
|
|
|
|
return dwError;
|
|
}
|
|
|
|
VOID CompressPath(PTSTR pszPath, PTSTR pszScratch);
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::CreateContainer
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::CreateContainer(LPCSTR Name, LPCSTR CachePrefix, LPCSTR CachePath, DWORD KBCacheLimit, DWORD dwOptions)
|
|
{
|
|
BOOL fInsertOk = TRUE;
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
CHAR szVendorKey[MAX_PATH];
|
|
CHAR szDefaultPath[MAX_PATH];
|
|
CHAR szCachePath[MAX_PATH];
|
|
LONGLONG CacheStartUpLimit;
|
|
HKEY hKey;
|
|
DWORD cbKeyLen;
|
|
|
|
hKey = (_fProfilesCapable ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE);
|
|
REGISTRY_OBJ* pro = NULL;
|
|
MUTEX_HOLDER mh;
|
|
|
|
if (!Name || !*Name)
|
|
{
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
goto exit;
|
|
}
|
|
if (!CachePath || !*CachePath)
|
|
{
|
|
LPSTR p = _coHistory->GetCachePath();
|
|
int len = _coHistory->GetCachePathLen();
|
|
int clen = lstrlen(Name);
|
|
|
|
if (len + clen + sizeof(DIR_SEPARATOR_STRING) > sizeof(szDefaultPath))
|
|
{
|
|
dwError = ERROR_WINHTTP_INTERNAL_ERROR;
|
|
goto exit;
|
|
}
|
|
memcpy(szDefaultPath, p, len);
|
|
|
|
memcpy(&szDefaultPath[len], Name, clen);
|
|
memcpy(&szDefaultPath[len + clen], DIR_SEPARATOR_STRING, sizeof(DIR_SEPARATOR_STRING));
|
|
}
|
|
else
|
|
{
|
|
INET_ASSERT((CachePrefix && *CachePrefix));
|
|
|
|
// For non-history containers, we need to stuff into the appropriate subcontainer
|
|
// Assumption: Content cache never falls here.
|
|
if (!GenerateStringWithOrdinal(CachePath,
|
|
GlobalIdentity,
|
|
szDefaultPath,
|
|
ARRAY_ELEMENTS(szDefaultPath)))
|
|
{
|
|
INET_ASSERT(FALSE);
|
|
dwError = ERROR_WINHTTP_INTERNAL_ERROR;
|
|
goto exit;
|
|
}
|
|
}
|
|
CachePath = szDefaultPath;
|
|
|
|
if (KBCacheLimit == 0)
|
|
{
|
|
CacheStartUpLimit = _coHistory->GetCacheStartUpLimit();
|
|
KBCacheLimit = (DWORD) (CacheStartUpLimit / 1024);
|
|
}
|
|
|
|
|
|
if (!CachePrefix || !*CachePrefix || !CachePath || !*CachePath)
|
|
{
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
goto exit;
|
|
}
|
|
|
|
pro = CreateExtensiRegObj(hKey);
|
|
if (!pro)
|
|
{
|
|
dwError = ERROR_ACCESS_DENIED;
|
|
goto exit;
|
|
}
|
|
{
|
|
REGISTRY_OBJ& roExtensibleCache = *pro;
|
|
mh.Grab(_hMutexExtensible, FAILSAFE_TIMEOUT);
|
|
|
|
// Get the container paths, prefixes (if any) and default limit values.
|
|
while (roExtensibleCache.FindNextKey(szVendorKey, MAX_PATH) == ERROR_SUCCESS)
|
|
{
|
|
REGISTRY_OBJ roVendor(&roExtensibleCache, szVendorKey);
|
|
if (roVendor.GetStatus()==ERROR_SUCCESS)
|
|
{
|
|
// Path.
|
|
TCHAR szScratch[MAX_PATH];
|
|
cbKeyLen = MAX_PATH;
|
|
if (roVendor.GetValue(CACHE_PATH_VALUE,(LPBYTE) szScratch,&cbKeyLen) != ERROR_SUCCESS)
|
|
continue;
|
|
|
|
ExpandEnvironmentStrings(szScratch, szCachePath, sizeof(szCachePath)-1); // don't count the NULL
|
|
if (!stricmp(szVendorKey, Name) || !stricmp(CachePath, szCachePath))
|
|
{
|
|
fInsertOk = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fInsertOk)
|
|
{
|
|
REGISTRY_OBJ roNewVendor(&roExtensibleCache, (LPSTR)Name, CREATE_KEY_IF_NOT_EXISTS);
|
|
if (roNewVendor.GetStatus() == ERROR_SUCCESS)
|
|
{
|
|
CHAR szScratch[MAX_PATH];
|
|
CompressPath((LPTSTR)CachePath, szScratch);
|
|
// Path.
|
|
if ((dwError = roNewVendor.SetValue(CACHE_PATH_VALUE, (LPSTR)szScratch, REG_EXPAND_SZ)) != ERROR_SUCCESS)
|
|
goto exit;
|
|
|
|
// Prefix.
|
|
if ((dwError = roNewVendor.SetValue(CACHE_PREFIX_VALUE, (LPSTR)CachePrefix, REG_SZ)) != ERROR_SUCCESS)
|
|
goto exit;
|
|
|
|
// Limit.
|
|
if ((dwError = roNewVendor.SetValue(CACHE_LIMIT_VALUE, &KBCacheLimit)) != ERROR_SUCCESS)
|
|
goto exit;
|
|
|
|
// Options.
|
|
if ((dwError = roNewVendor.SetValue(CACHE_OPTIONS_VALUE, &dwOptions)) != ERROR_SUCCESS)
|
|
goto exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwError = ERROR_ALREADY_EXISTS;
|
|
}
|
|
}
|
|
|
|
if (fInsertOk)
|
|
{
|
|
IncrementModifiedCount();
|
|
}
|
|
|
|
exit:
|
|
if (pro)
|
|
{
|
|
delete pro;
|
|
}
|
|
mh.Release();
|
|
if (fInsertOk)
|
|
{
|
|
GetExtensibleCacheConfigInfo(TRUE);
|
|
}
|
|
return dwError;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::FindExtensibleContainer
|
|
----------------------------------------------------------------------------*/
|
|
// THIS FUNCTION MUST BE CALLED WITH THE CACHE CRIT SECTION
|
|
DWORD CConMgr::FindExtensibleContainer(LPCSTR Name)
|
|
{
|
|
DWORD n = NOT_AN_INDEX;
|
|
DWORD i;
|
|
URL_CONTAINER *co;
|
|
|
|
for (i = NCONTAINERS; i < ConList.Size(); i++)
|
|
{
|
|
co = ConList.Get(i);
|
|
if (co)
|
|
{
|
|
if (!stricmp(Name, co->GetCacheName()) && co->IsVisible())
|
|
{
|
|
// Found a match
|
|
n = i;
|
|
co->Release(FALSE);
|
|
break;
|
|
}
|
|
co->Release(FALSE);
|
|
}
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::DeleteContainer
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::DeleteContainer(LPCSTR Name, DWORD dwOptions)
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
URL_CONTAINER *co = NULL;
|
|
DWORD n = NOT_AN_INDEX;
|
|
HKEY hKey;
|
|
|
|
if (!Name || !*Name)
|
|
{
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
goto exit;
|
|
}
|
|
|
|
LOCK_CACHE();
|
|
n = FindExtensibleContainer(Name);
|
|
if (n != NOT_AN_INDEX)
|
|
{
|
|
co = ConList.Get(n);
|
|
|
|
if (co)
|
|
{
|
|
co->SetDeletePending(TRUE);
|
|
// Don't release here, hold it pending until we've updated registry
|
|
}
|
|
}
|
|
UNLOCK_CACHE();
|
|
|
|
if (n!= NOT_AN_INDEX)
|
|
{
|
|
hKey = (_fProfilesCapable ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE);
|
|
|
|
REGISTRY_OBJ* pro = CreateExtensiRegObj(hKey);
|
|
if (!pro)
|
|
{
|
|
dwError = ERROR_ACCESS_DENIED;
|
|
goto exit;
|
|
}
|
|
|
|
{
|
|
REGISTRY_OBJ& roExtensibleCache = *pro;
|
|
MUTEX_HOLDER mh;
|
|
mh.Grab(_hMutexExtensible, FAILSAFE_TIMEOUT);
|
|
dwError = roExtensibleCache.DeleteKey((LPSTR)Name);
|
|
mh.Release();
|
|
IncrementModifiedCount();
|
|
}
|
|
delete pro;
|
|
}
|
|
|
|
exit:
|
|
LOCK_CACHE();
|
|
SAFERELEASE(co, TRUE);
|
|
UNLOCK_CACHE();
|
|
return dwError;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::DeleteFileIfNotRegistered
|
|
----------------------------------------------------------------------------*/
|
|
BOOL CConMgr::DeleteFileIfNotRegistered(URL_CONTAINER *coDelete)
|
|
{
|
|
BOOL fDelete = TRUE;
|
|
BOOL fFound = FALSE;
|
|
CHAR szCachePath[MAX_PATH];
|
|
CHAR szCachePrefix[MAX_PATH];
|
|
DWORD dwOptions;
|
|
LONGLONG cbCacheLimit;
|
|
|
|
HKEY hKey = (HKEY) INVALID_HANDLE_VALUE;
|
|
DWORD cbKeyLen, cbKBLimit, dwError;
|
|
CHAR szVendorKey[MAX_PATH];
|
|
|
|
hKey = (_fProfilesCapable ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE);
|
|
REGISTRY_OBJ* pro = CreateExtensiRegObj(hKey);
|
|
MUTEX_HOLDER mh;
|
|
|
|
if (!pro)
|
|
{
|
|
dwError = ERROR_ACCESS_DENIED;
|
|
goto exit;
|
|
}
|
|
|
|
if (!WasModified(FALSE))
|
|
{
|
|
// If our internal cache is up to date, it can't
|
|
// have been deleted unless DeletePending or Deleted
|
|
fFound = !(coDelete->GetDeletePending()||coDelete->GetDeleted());
|
|
if (fFound)
|
|
{
|
|
goto exit;
|
|
}
|
|
// If not found, need to look at registry to make sure we're not
|
|
// deleting a path that has been reused
|
|
}
|
|
|
|
mh.Grab(_hMutexExtensible, FAILSAFE_TIMEOUT);
|
|
|
|
{
|
|
REGISTRY_OBJ& roExtensibleCache = *pro;
|
|
|
|
// Get the container paths, prefixes.
|
|
while (roExtensibleCache.FindNextKey(szVendorKey, MAX_PATH) == ERROR_SUCCESS)
|
|
{
|
|
BOOL fPathMatch;
|
|
REGISTRY_OBJ roVendor(&roExtensibleCache, szVendorKey);
|
|
if (roVendor.GetStatus()==ERROR_SUCCESS)
|
|
{
|
|
// Path.
|
|
TCHAR szScratch[MAX_PATH];
|
|
cbKeyLen = MAX_PATH;
|
|
if (roVendor.GetValue(CACHE_PATH_VALUE,(LPBYTE) szScratch, &cbKeyLen) != ERROR_SUCCESS)
|
|
continue;
|
|
|
|
ExpandEnvironmentStrings(szScratch, szCachePath, sizeof(szCachePath)-1); // don't count the NULL
|
|
|
|
// Prefix.
|
|
cbKeyLen = MAX_PATH;
|
|
if (roVendor.GetValue(CACHE_PREFIX_VALUE,(LPBYTE) szCachePrefix, &cbKeyLen) != ERROR_SUCCESS)
|
|
continue;
|
|
|
|
// Options.
|
|
if (roVendor.GetValue(CACHE_OPTIONS_VALUE,&dwOptions) != ERROR_SUCCESS)
|
|
continue;
|
|
|
|
fPathMatch = !stricmp(coDelete->GetCachePath(), szCachePath);
|
|
if (!stricmp(coDelete->GetCacheName(), szVendorKey) && fPathMatch &&
|
|
!stricmp(coDelete->GetCachePrefix(), szCachePrefix) &&
|
|
coDelete->GetOptions() != dwOptions)
|
|
{
|
|
fFound = TRUE;
|
|
}
|
|
if (fPathMatch)
|
|
fDelete = FALSE;
|
|
}
|
|
}
|
|
}
|
|
if (fDelete)
|
|
{
|
|
// This will fail if another process still has the container mapped,
|
|
// that's ok. They will check on exit if container needs to be
|
|
// deleted
|
|
if (coDelete->GetOptions() & INTERNET_CACHE_CONTAINER_AUTODELETE)
|
|
{
|
|
CFileMgr::DeleteCache(coDelete->GetCachePath());
|
|
}
|
|
}
|
|
exit:
|
|
if (pro)
|
|
{
|
|
delete pro;
|
|
}
|
|
mh.Release();
|
|
|
|
return !fFound;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::FindIndexFromPrefix
|
|
----------------------------------------------------------------------------*/
|
|
// THIS FUNCTION MUST BE CALLED WITH THE CACHE CRIT SEC
|
|
DWORD CConMgr::FindIndexFromPrefix(LPCSTR szUrl)
|
|
{
|
|
// Unless we find a matching prefix, CONTENT is the default.
|
|
DWORD n = szUrl[0]==EXTENSIBLE_FIRST ? NOT_AN_INDEX : CONTENT;
|
|
URL_CONTAINER *co = NULL;
|
|
|
|
// NOTE: if deleting a container is supported, ConList.Get(i) can
|
|
// return NULL, if list shrinks after getting size.
|
|
// NOTE: if deleting containers is supported, it is not safe to
|
|
// assume CONTENT if prefix is not found. client may be trying to
|
|
// insert into a container that has been deleted, but once existed.
|
|
// proper response is to return an error. the simplest way to do this
|
|
// is to insist that all Extensible cache prefixes start with an illegal
|
|
// URL character, EXTENSIBLE_FIRST
|
|
|
|
GetExtensibleCacheConfigInfo(FALSE);
|
|
for (DWORD i = COOKIE; i < ConList.Size(); i++)
|
|
{
|
|
co = ConList.Get(i);
|
|
if (co)
|
|
{
|
|
if (co->PrefixMatch(szUrl))
|
|
{
|
|
// For content container, strnicmp (szUrl, "", 0) returns nonzero
|
|
if (co->IsVisible())
|
|
{
|
|
// Found a match
|
|
n = i;
|
|
if (!co->IsInitialized())
|
|
{
|
|
// Init the container. If this fails,
|
|
// Mark it as DELETED and return CONTENT.
|
|
switch (co->Init())
|
|
{
|
|
case ERROR_SUCCESS:
|
|
case ERROR_ALREADY_EXISTS:
|
|
if (!(co->GetOptions() & INTERNET_CACHE_CONTAINER_NODESKTOPINIT))
|
|
EnableCacheVu(co->GetCachePath(), n);
|
|
break;
|
|
default:
|
|
INET_ASSERT(FALSE);
|
|
co->SetDeleted(TRUE);
|
|
n = szUrl[0]==EXTENSIBLE_FIRST ? NOT_AN_INDEX : CONTENT;
|
|
break;
|
|
}
|
|
}
|
|
co->Release(FALSE);
|
|
break;
|
|
}
|
|
}
|
|
co->Release(FALSE);
|
|
}
|
|
}
|
|
return n;
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
BOOL CConMgr::PathPrefixMatch
|
|
----------------------------------------------------------------------------*/
|
|
BOOL CConMgr::PathPrefixMatch(LPCSTR szPath, LPCSTR szPathRef)
|
|
{
|
|
// BUGBUG - logic borrowed from original cacheapi.cxx
|
|
|
|
INT len;
|
|
|
|
// TRUE if the passed in path is NULL
|
|
if (!szPath)
|
|
return TRUE;
|
|
|
|
len = lstrlen(szPath);
|
|
|
|
// TRUE if it is 0 length.
|
|
if (!len)
|
|
return TRUE;
|
|
|
|
// stripout the trailing slash
|
|
if (szPath[len-1] == DIR_SEPARATOR_CHAR)
|
|
--len;
|
|
|
|
// Compare paths.
|
|
if (!strnicmp(szPath, szPathRef, len))
|
|
if (szPathRef[len] == DIR_SEPARATOR_CHAR || szPathRef[len] == 0)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/*--------------------- Public Functions -----------------------------------*/
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
CConMgr::CConMgr
|
|
|
|
Default Constructor
|
|
----------------------------------------------------------------------------*/
|
|
CConMgr::CConMgr()
|
|
: ConList()
|
|
{
|
|
_coContent = NULL;
|
|
_coCookies = NULL;
|
|
_coHistory = NULL;
|
|
_hMutexExtensible = 0;
|
|
|
|
// Assume this is a profiles-capable machine. Later on, we'll make sure this is
|
|
// the case.
|
|
_fProfilesCapable = TRUE;
|
|
|
|
// Assume that we'll be using the regular containers, instead of the backup
|
|
_fUsingBackupContainers = FALSE;
|
|
_dwStatus = Init();
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
CConMgr::~CConMgr
|
|
|
|
Default Destructor
|
|
----------------------------------------------------------------------------*/
|
|
CConMgr::~CConMgr()
|
|
{
|
|
ConList.Free();
|
|
if (_hMutexExtensible)
|
|
{
|
|
CloseHandle(_hMutexExtensible);
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::GetStatus()
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::GetStatus()
|
|
{
|
|
return _dwStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::UnlockUrl
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::UnlockUrl(LPCSTR szUrl)
|
|
{
|
|
URL_CONTAINER *co;
|
|
DWORD dwError = ERROR_FILE_NOT_FOUND;
|
|
// Find the associated container.
|
|
DWORD idx;
|
|
|
|
LOCK_CACHE();
|
|
|
|
idx = FindIndexFromPrefix(szUrl);
|
|
co = ConList.Get(idx);
|
|
|
|
if (co)
|
|
{
|
|
UNLOCK_CACHE();
|
|
// Call UnlockUrl on the appropriate container.
|
|
dwError = co->UnlockUrl(szUrl); // may be expensive
|
|
LOCK_CACHE();
|
|
co->Release(TRUE);
|
|
}
|
|
UNLOCK_CACHE();
|
|
return dwError;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::DeleteUrl
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::DeleteUrl(LPCSTR szUrl)
|
|
{
|
|
URL_CONTAINER *co;
|
|
DWORD dwError = ERROR_FILE_NOT_FOUND;
|
|
// Find the associated container.
|
|
DWORD idx;
|
|
|
|
UNIX_RETURN_ERR_IF_READONLY_CACHE(dwError);
|
|
|
|
LOCK_CACHE();
|
|
|
|
idx = FindIndexFromPrefix(szUrl);
|
|
co = ConList.Get(idx);
|
|
|
|
if (co)
|
|
{
|
|
UNLOCK_CACHE();
|
|
// Call DeleteUrl on the appropriate container.
|
|
dwError = co->DeleteUrl(szUrl); // may be expensive.
|
|
LOCK_CACHE();
|
|
|
|
co->Release(TRUE);
|
|
|
|
// Update the change count for the cookies container.
|
|
if (idx == COOKIE)
|
|
{
|
|
DWORD dwChange = 0;
|
|
_coContent->IncrementHeaderData(CACHE_HEADER_DATA_COOKIE_CHANGE_COUNT, &dwChange);
|
|
}
|
|
}
|
|
|
|
UNLOCK_CACHE();
|
|
return dwError;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
BOOL CConMgr::GetHeaderData
|
|
----------------------------------------------------------------------------*/
|
|
BOOL CConMgr::GetHeaderData(DWORD nIdx, LPDWORD pdwData)
|
|
{
|
|
return _coContent->GetHeaderData(nIdx, pdwData);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
BOOL CConMgr::SetHeaderData
|
|
----------------------------------------------------------------------------*/
|
|
BOOL CConMgr::SetHeaderData(DWORD nIdx, DWORD dwData)
|
|
{
|
|
UNIX_RETURN_ERR_IF_READONLY_CACHE(FALSE);
|
|
return _coContent->SetHeaderData(nIdx, dwData);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
BOOL CConMgr::IncrementHeaderData
|
|
----------------------------------------------------------------------------*/
|
|
BOOL CConMgr::IncrementHeaderData(DWORD nIdx, LPDWORD pdwData)
|
|
{
|
|
UNIX_RETURN_ERR_IF_READONLY_CACHE(FALSE);
|
|
return _coContent->IncrementHeaderData(nIdx, pdwData);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::SetUrlGroup
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::SetUrlGroup(
|
|
IN LPCSTR szUrl,
|
|
IN DWORD dwFlags,
|
|
IN GROUPID GroupId
|
|
)
|
|
{
|
|
URL_CONTAINER *co;
|
|
DWORD dwError = ERROR_FILE_NOT_FOUND;
|
|
// Find the associated container.
|
|
|
|
UNIX_RETURN_ERR_IF_READONLY_CACHE(dwError);
|
|
|
|
LOCK_CACHE();
|
|
DWORD idx = FindIndexFromPrefix(szUrl);
|
|
|
|
co = ConList.Get(idx);
|
|
|
|
if (co)
|
|
{
|
|
UNLOCK_CACHE();
|
|
// Call SetUrlInGroup on the appropriate container.
|
|
dwError = co->SetUrlGroup
|
|
(szUrl, dwFlags, GroupId);
|
|
LOCK_CACHE();
|
|
co->Release(TRUE);
|
|
}
|
|
|
|
UNLOCK_CACHE();
|
|
return dwError;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::CreateUniqueFile
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::CreateUniqueFile(LPCSTR szUrl, DWORD dwExpectedSize,
|
|
LPCSTR szFileExtension, LPTSTR szFileName,
|
|
HANDLE *phfHandle,
|
|
BOOL fCreatePerUser)
|
|
{
|
|
URL_CONTAINER *co;
|
|
DWORD dwError = ERROR_FILE_NOT_FOUND;
|
|
// Find the associated container.
|
|
|
|
UNIX_RETURN_ERR_IF_READONLY_CACHE(dwError);
|
|
|
|
LOCK_CACHE();
|
|
DWORD idx = FindIndexFromPrefix(szUrl);
|
|
|
|
|
|
co = ConList.Get(idx);
|
|
|
|
|
|
if (co)
|
|
{
|
|
UNLOCK_CACHE();
|
|
// Call CreateUniqueFile on the appropriate container.
|
|
dwError = co->CreateUniqueFile(szUrl, dwExpectedSize,
|
|
szFileExtension, szFileName, phfHandle, fCreatePerUser); // expensive call
|
|
LOCK_CACHE();
|
|
|
|
co->Release(TRUE);
|
|
}
|
|
|
|
UNLOCK_CACHE();
|
|
return dwError;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::AddUrl
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::AddUrl(AddUrlArg* pArgs)
|
|
{
|
|
URL_CONTAINER *co;
|
|
DWORD dwError = ERROR_FILE_NOT_FOUND;
|
|
// Find the associated container.
|
|
|
|
UNIX_RETURN_ERR_IF_READONLY_CACHE(dwError);
|
|
|
|
LOCK_CACHE();
|
|
|
|
DWORD idx = FindIndexFromPrefix(pArgs->pszUrl);
|
|
co = ConList.Get(idx);
|
|
|
|
if (co)
|
|
{
|
|
UNLOCK_CACHE();
|
|
// Call AddUrl on the appropriate container.
|
|
dwError = co->AddUrl(pArgs); // may be expensive
|
|
LOCK_CACHE();
|
|
|
|
co->Release(TRUE);
|
|
|
|
// Update the change count for the cookies container.
|
|
if (idx == COOKIE)
|
|
{
|
|
DWORD dwChange = 0;
|
|
_coContent->IncrementHeaderData(CACHE_HEADER_DATA_COOKIE_CHANGE_COUNT, &dwChange);
|
|
}
|
|
}
|
|
|
|
UNLOCK_CACHE();
|
|
return dwError;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::RetrieveUrl
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::RetrieveUrl( LPCSTR szUrl,
|
|
LPCACHE_ENTRY_INFOA* ppCacheEntryInfo,
|
|
LPDWORD pcbCacheEntryInfoBufferSize,
|
|
DWORD dwLookupFlags,
|
|
DWORD dwRetrievalFlags)
|
|
{
|
|
URL_CONTAINER *co;
|
|
DWORD dwError = ERROR_FILE_NOT_FOUND;
|
|
// Find the associated container.
|
|
|
|
LOCK_CACHE();
|
|
DWORD idx = FindIndexFromPrefix(szUrl);
|
|
|
|
|
|
co = ConList.Get(idx);
|
|
|
|
if (co)
|
|
{
|
|
UNLOCK_CACHE();
|
|
// Call RetrieveUrl on the appropriate container.
|
|
dwError = co->RetrieveUrl(szUrl,
|
|
ppCacheEntryInfo,
|
|
pcbCacheEntryInfoBufferSize,
|
|
dwLookupFlags, dwRetrievalFlags); // expensive?
|
|
LOCK_CACHE();
|
|
co->Release(TRUE);
|
|
}
|
|
|
|
UNLOCK_CACHE();
|
|
return dwError;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::GetUrlInfo
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::GetUrlInfo( LPCSTR szUrl,
|
|
LPCACHE_ENTRY_INFOA* ppCacheEntryInfo,
|
|
LPDWORD pcbCacheEntryInfoBufferSize,
|
|
DWORD dwLookupFlags,
|
|
DWORD dwEntryFlags,
|
|
DWORD dwRetrievalFlags)
|
|
{
|
|
URL_CONTAINER *co;
|
|
DWORD dwError = ERROR_FILE_NOT_FOUND;
|
|
// Find the associated container.
|
|
|
|
LOCK_CACHE();
|
|
DWORD idx = FindIndexFromPrefix(szUrl);
|
|
|
|
co = ConList.Get(idx);
|
|
|
|
if (co)
|
|
{
|
|
// Call GetUrlInfo on the appropriate container.
|
|
dwError = co->GetUrlInfo(szUrl,
|
|
ppCacheEntryInfo,
|
|
pcbCacheEntryInfoBufferSize,
|
|
dwLookupFlags,
|
|
dwEntryFlags,
|
|
dwRetrievalFlags);
|
|
|
|
co->Release(TRUE);
|
|
}
|
|
UNLOCK_CACHE();
|
|
return dwError;
|
|
}
|
|
|
|
DWORD CConMgr::GetUrlInfo(LPCSTR szUrl,
|
|
LPCACHE_ENTRY_INFOA pCacheEntryInfo,
|
|
LPDWORD pcbCacheEntryInfoBufferSize,
|
|
DWORD dwLookupFlags,
|
|
DWORD dwEntryFlags)
|
|
{
|
|
return GetUrlInfo(szUrl,
|
|
(pCacheEntryInfo) ? &pCacheEntryInfo : NULL,
|
|
pcbCacheEntryInfoBufferSize,
|
|
dwLookupFlags,
|
|
dwEntryFlags,
|
|
0);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::SetUrlInfo
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::SetUrlInfo(LPCSTR szUrl,
|
|
LPCACHE_ENTRY_INFOA pCacheEntryInfo,
|
|
DWORD dwFieldControl)
|
|
{
|
|
URL_CONTAINER *co;
|
|
DWORD dwError = ERROR_FILE_NOT_FOUND;
|
|
// Find the associated container.
|
|
|
|
UNIX_RETURN_ERR_IF_READONLY_CACHE(dwError);
|
|
|
|
LOCK_CACHE();
|
|
DWORD idx = FindIndexFromPrefix(szUrl);
|
|
|
|
co = ConList.Get(idx);
|
|
|
|
if (co)
|
|
{
|
|
// Call SetUrlInfo on the appropriate container.
|
|
dwError = co->SetUrlInfo(szUrl,
|
|
pCacheEntryInfo,
|
|
dwFieldControl);
|
|
co->Release(TRUE);
|
|
}
|
|
|
|
UNLOCK_CACHE();
|
|
return dwError;
|
|
}
|
|
|
|
DWORD CConMgr::FreeFindHandle(HANDLE hFind)
|
|
{
|
|
DWORD dwError = ERROR_INVALID_HANDLE;
|
|
|
|
if (hFind)
|
|
{
|
|
LOCK_CACHE();
|
|
|
|
LPCACHE_FIND_FIRST_HANDLE pFind;
|
|
pFind = (CACHE_FIND_FIRST_HANDLE*) HandleMgr.Map (hFind);
|
|
if (pFind)
|
|
{
|
|
// NOTHING SPECIAL TO DO FOR SIGNATURE_CONTAINER_FIND
|
|
if (pFind->dwSig == SIG_CACHE_FIND && !pFind->fFixed)
|
|
{
|
|
URL_CONTAINER *co = ConList.Get(pFind->nIdx);
|
|
if (co)
|
|
{
|
|
// It now has 2 AddRefs to balance
|
|
co->Release(FALSE);
|
|
co->Release(TRUE);
|
|
}
|
|
}
|
|
|
|
HandleMgr.Free (hFind);
|
|
dwError = ERROR_SUCCESS;
|
|
}
|
|
|
|
UNLOCK_CACHE();
|
|
}
|
|
|
|
return dwError;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::FindNextEntry
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::FindNextEntry(
|
|
HANDLE *phFind,
|
|
LPCSTR szPrefix,
|
|
LPCACHE_ENTRY_INFOA* ppInfo,
|
|
LPDWORD pcbInfo,
|
|
DWORD dwFilter,
|
|
GROUPID GroupId,
|
|
DWORD dwFlags,
|
|
DWORD dwRetrievalFlags)
|
|
{
|
|
DWORD idx, dwError;
|
|
URL_CONTAINER *co = NULL;
|
|
LPCACHE_FIND_FIRST_HANDLE pFind = NULL;
|
|
|
|
LOCK_CACHE();
|
|
|
|
// Null handle initiates enumeration.
|
|
if (!*phFind)
|
|
{
|
|
// Allocate a handle.
|
|
//LOCK_CACHE();
|
|
*phFind = HandleMgr.Alloc (sizeof(CACHE_FIND_FIRST_HANDLE));
|
|
if (*phFind)
|
|
pFind = (CACHE_FIND_FIRST_HANDLE*) HandleMgr.Map (*phFind);
|
|
//UNLOCK_CACHE();
|
|
if (!*phFind)
|
|
{
|
|
dwError = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
if (!pFind)
|
|
{
|
|
dwError = ERROR_INVALID_HANDLE;
|
|
goto exit;
|
|
}
|
|
|
|
// Set signature and initial hash table find
|
|
// handle in the newly allocated find handle.
|
|
pFind->dwSig = SIG_CACHE_FIND;
|
|
pFind->dwHandle = 0;
|
|
pFind->dwFlags = dwFlags;
|
|
|
|
// Find the associated container. NULL prefix
|
|
// results in enumeration over fixed containers.
|
|
if (!szPrefix)
|
|
{
|
|
pFind->fFixed = TRUE;
|
|
pFind->nIdx = CONTENT;
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
idx = FindIndexFromPrefix(szPrefix);
|
|
if (idx == NOT_AN_INDEX)
|
|
{
|
|
dwError = ERROR_NO_MORE_ITEMS;
|
|
goto exit;
|
|
}
|
|
|
|
// Under old semantics prefix resolving to CONTENT
|
|
// container implies that an enumeration over all
|
|
// the fixed containers is desired. Enumeration then
|
|
// begins with the CONTENT container. We do not keep
|
|
// a refcount on any fixed containers in this case.
|
|
if (idx == CONTENT && (dwFlags & FIND_FLAGS_OLD_SEMANTICS))
|
|
{
|
|
pFind->fFixed = TRUE;
|
|
pFind->nIdx = CONTENT;
|
|
}
|
|
else
|
|
{
|
|
// Otherwise only enumeration over the found container
|
|
// is implied. Retrieve this container. Set fFixed to FALSE.
|
|
// NO RELEASE: hold RefCnt until handle is closed
|
|
co = ConList.Get(idx);
|
|
|
|
if (co)
|
|
{
|
|
pFind->fFixed = FALSE;
|
|
pFind->nIdx = idx;
|
|
pFind->dwHandle = co->GetInitialFindHandle();
|
|
}
|
|
else
|
|
{
|
|
dwError = ERROR_NO_MORE_ITEMS;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
}
|
|
// Set filter and group id in handle.
|
|
pFind->dwFilter = dwFilter;
|
|
pFind->GroupId = GroupId;
|
|
}
|
|
else
|
|
{
|
|
// Valid handle passed in - map it.
|
|
//LOCK_CACHE();
|
|
pFind = (CACHE_FIND_FIRST_HANDLE*) HandleMgr.Map (*phFind);
|
|
//UNLOCK_CACHE();
|
|
if (!pFind)
|
|
{
|
|
dwError = ERROR_INVALID_HANDLE;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// The handle is initialized or was created via a previous FindNextEntry.
|
|
//--------------------------------------------------------------------------
|
|
|
|
dwError = ERROR_NO_MORE_ITEMS;
|
|
|
|
// Are we only enumerating over one container?
|
|
if (!pFind->fFixed)
|
|
{
|
|
// Get the associated container.
|
|
co = ConList.Get(pFind->nIdx);
|
|
|
|
if (co)
|
|
{
|
|
// Enum on the container and release.
|
|
dwError = co->FindNextEntry(&pFind->dwHandle, ppInfo, pcbInfo, pFind->dwFilter, pFind->GroupId, pFind->dwFlags, dwRetrievalFlags);
|
|
co->Release(TRUE);
|
|
}
|
|
else
|
|
{
|
|
// Getting container failed.
|
|
dwError = ERROR_NO_MORE_ITEMS;
|
|
goto exit;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// fFixed is TRUE - enumerate over the fixed containers.
|
|
while (pFind->nIdx < NCONTAINERS)
|
|
{
|
|
// Get the associated container.
|
|
co = ConList.Get(pFind->nIdx);
|
|
|
|
if (co)
|
|
{
|
|
// Get the initial hash find handle if not already done so.
|
|
if (!pFind->dwHandle)
|
|
pFind->dwHandle = co->GetInitialFindHandle();
|
|
|
|
// Enum on the container and release.
|
|
dwError = co->FindNextEntry(&pFind->dwHandle, ppInfo, pcbInfo, pFind->dwFilter, pFind->GroupId, pFind->dwFlags, dwRetrievalFlags);
|
|
co->Release(TRUE);
|
|
|
|
// Goto exit only if ERROR_NO_MORE_ITEMS.
|
|
// This handles ERROR_SUCCESS correctly.
|
|
if (dwError != ERROR_NO_MORE_ITEMS)
|
|
goto exit;
|
|
|
|
// ERROR_NO_MORE_ITEMS: Go to next container
|
|
// and begin enum anew.
|
|
pFind->nIdx++;
|
|
pFind->dwHandle = 0;
|
|
}
|
|
else
|
|
{
|
|
// Getting container failed.
|
|
dwError = ERROR_NO_MORE_ITEMS;
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
exit:
|
|
|
|
UNLOCK_CACHE();
|
|
|
|
INET_ASSERT(*phFind != 0);
|
|
INET_ASSERT(pFind != NULL);
|
|
|
|
return dwError;
|
|
}
|
|
|
|
DWORD CConMgr::FindNextEntry(
|
|
HANDLE *phFind,
|
|
LPCSTR szPrefix,
|
|
LPCACHE_ENTRY_INFOA pInfo,
|
|
LPDWORD pcbInfo,
|
|
DWORD dwFilter,
|
|
GROUPID GroupId,
|
|
DWORD dwFlags)
|
|
{
|
|
return FindNextEntry(
|
|
phFind,
|
|
szPrefix,
|
|
(pInfo ? &pInfo : NULL),
|
|
pcbInfo,
|
|
dwFilter,
|
|
GroupId,
|
|
dwFlags,
|
|
0);
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::CleanupUrls
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::CleanupUrls
|
|
(LPCTSTR szCachePath, DWORD dwFactor, DWORD dwFilter)
|
|
{
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
UNIX_RETURN_ERR_IF_READONLY_CACHE(dwError);
|
|
|
|
// Bad cleanup parameter.
|
|
if (dwFactor <= 0 || dwFactor > 100)
|
|
{
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
goto exit;
|
|
}
|
|
|
|
// For null or empty path, clean up content container.
|
|
if (!szCachePath || !*szCachePath)
|
|
{
|
|
_coContent->CleanupUrls(dwFactor, dwFilter);
|
|
}
|
|
else
|
|
{
|
|
LOCK_CACHE();
|
|
|
|
// Find the container with the matching cache path and clean it up.
|
|
for (DWORD idx = CONTENT; idx < NCONTAINERS; idx++)
|
|
{
|
|
URL_CONTAINER *co = ConList.Get(idx);
|
|
|
|
if (co)
|
|
{
|
|
if (PathPrefixMatch(szCachePath, co->GetCachePath()))
|
|
{
|
|
UNLOCK_CACHE();
|
|
co->CleanupUrls(dwFactor, dwFilter); // expensive?
|
|
LOCK_CACHE();
|
|
co->Release(TRUE);
|
|
break;
|
|
}
|
|
co->Release(TRUE);
|
|
}
|
|
}
|
|
|
|
UNLOCK_CACHE();
|
|
}
|
|
|
|
exit:
|
|
return dwError;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::GetUrlInGroup
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::GetUrlInGroup(LPCSTR szUrl, GROUPID* pGroupId, LPDWORD pdwExemptDelta)
|
|
{
|
|
URL_CONTAINER *co;
|
|
DWORD dwError = ERROR_FILE_NOT_FOUND;
|
|
// Find the associated container.
|
|
LOCK_CACHE();
|
|
DWORD idx = FindIndexFromPrefix(szUrl);
|
|
|
|
co = ConList.Get(idx);
|
|
|
|
if (co)
|
|
{
|
|
UNLOCK_CACHE();
|
|
// Call GetUrlInGroup on the appropriate container.
|
|
dwError = co->GetUrlInGroup(szUrl, pGroupId, pdwExemptDelta);
|
|
LOCK_CACHE();
|
|
co->Release(TRUE);
|
|
}
|
|
UNLOCK_CACHE();
|
|
return dwError;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::CreateGroup()
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::CreateGroup(DWORD dwFlags, GROUPID* pGID)
|
|
{
|
|
INET_ASSERT(_coContent);
|
|
|
|
LOCK_CACHE();
|
|
|
|
GroupMgr gm;
|
|
DWORD dwError = ERROR_WINHTTP_INTERNAL_ERROR;
|
|
|
|
if( gm.Init(_coContent) )
|
|
{
|
|
dwError = gm.CreateGroup(dwFlags, pGID);
|
|
}
|
|
|
|
|
|
UNLOCK_CACHE();
|
|
return dwError;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::CreateDefaultGroups()
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::CreateDefaultGroups()
|
|
{
|
|
INET_ASSERT(_coContent);
|
|
|
|
LOCK_CACHE();
|
|
|
|
GroupMgr gm;
|
|
DWORD dwError = ERROR_WINHTTP_INTERNAL_ERROR;
|
|
|
|
if( gm.Init(_coContent) )
|
|
{
|
|
dwError = gm.CreateDefaultGroups();
|
|
}
|
|
|
|
|
|
UNLOCK_CACHE();
|
|
return dwError;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::DeleteGroup()
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::DeleteGroup(GROUPID gid, DWORD dwFlags)
|
|
{
|
|
INET_ASSERT(_coContent);
|
|
|
|
LOCK_CACHE();
|
|
GroupMgr gm;
|
|
DWORD dwError = ERROR_WINHTTP_INTERNAL_ERROR;
|
|
|
|
if( gm.Init(_coContent) )
|
|
{
|
|
dwError = gm.DeleteGroup(gid, dwFlags);
|
|
}
|
|
|
|
UNLOCK_CACHE();
|
|
|
|
return dwError;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::FindNextGroup()
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::FindNextGroup(
|
|
HANDLE* phFind,
|
|
DWORD dwFlags,
|
|
GROUPID* pGroupId
|
|
)
|
|
{
|
|
DWORD dwError;
|
|
GROUP_FIND_FIRST_HANDLE* pFind = NULL;
|
|
GroupMgr gm;
|
|
|
|
INET_ASSERT(_coContent);
|
|
LOCK_CACHE();
|
|
|
|
|
|
// Null handle initiates enumeration.
|
|
if (!*phFind)
|
|
{
|
|
// BUGBUG currently only supports SEARCH_ALL option
|
|
if( dwFlags )
|
|
{
|
|
dwError = ERROR_INVALID_PARAMETER;
|
|
goto exit;
|
|
}
|
|
|
|
|
|
// Allocate a handle.
|
|
*phFind = HandleMgr.Alloc (sizeof(GROUP_FIND_FIRST_HANDLE));
|
|
if (*phFind)
|
|
pFind = (GROUP_FIND_FIRST_HANDLE*) HandleMgr.Map (*phFind);
|
|
|
|
if (!*phFind)
|
|
{
|
|
dwError = ERROR_NOT_ENOUGH_MEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
if (!pFind)
|
|
{
|
|
dwError = ERROR_INVALID_HANDLE;
|
|
goto exit;
|
|
}
|
|
|
|
// Set signature and initial hash table find
|
|
// handle in the newly allocated find handle.
|
|
pFind->dwSig = SIG_GROUP_FIND;
|
|
pFind->fFixed = TRUE;
|
|
pFind->nIdx = CONTENT;
|
|
pFind->dwLastItemOffset = 0;
|
|
}
|
|
else
|
|
{
|
|
// Valid handle passed in - map it.
|
|
pFind = (GROUP_FIND_FIRST_HANDLE*) HandleMgr.Map (*phFind);
|
|
if (!pFind)
|
|
{
|
|
dwError = ERROR_INVALID_HANDLE;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// The handle is initialized or was created via a previous FindNextEntry.
|
|
//
|
|
|
|
dwError = ERROR_FILE_NOT_FOUND;
|
|
|
|
// Enum on the container and release.
|
|
if( gm.Init(_coContent) )
|
|
{
|
|
DWORD dwLastItemOffset = pFind->dwLastItemOffset;
|
|
|
|
dwError = gm.GetNextGroup(&dwLastItemOffset, pGroupId);
|
|
|
|
// update offset field of the find handle
|
|
pFind->dwLastItemOffset = dwLastItemOffset;
|
|
|
|
}
|
|
|
|
exit:
|
|
|
|
UNLOCK_CACHE();
|
|
INET_ASSERT(*phFind != 0);
|
|
INET_ASSERT(pFind != NULL);
|
|
|
|
return dwError;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::GetGroupAttributes()
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::GetGroupAttributes(
|
|
GROUPID gid,
|
|
DWORD dwAttrib,
|
|
LPINTERNET_CACHE_GROUP_INFOA lpGroupInfo,
|
|
LPDWORD lpdwGroupInfo
|
|
)
|
|
{
|
|
INET_ASSERT(_coContent);
|
|
DWORD dwError = ERROR_WINHTTP_INTERNAL_ERROR;
|
|
|
|
LOCK_CACHE();
|
|
GroupMgr gm;
|
|
if( gm.Init(_coContent) )
|
|
{
|
|
dwError = gm.GetGroup(gid, dwAttrib, lpGroupInfo, lpdwGroupInfo);
|
|
}
|
|
|
|
UNLOCK_CACHE();
|
|
return dwError;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
DWORD CConMgr::SetGroupAttributes()
|
|
----------------------------------------------------------------------------*/
|
|
DWORD CConMgr::SetGroupAttributes(
|
|
GROUPID gid,
|
|
DWORD dwAttrib,
|
|
LPINTERNET_CACHE_GROUP_INFOA lpGroupInfo
|
|
)
|
|
{
|
|
INET_ASSERT(_coContent);
|
|
DWORD dwError = ERROR_WINHTTP_INTERNAL_ERROR;
|
|
|
|
LOCK_CACHE();
|
|
GroupMgr gm;
|
|
if( gm.Init(_coContent))
|
|
{
|
|
dwError = gm.SetGroup(gid, dwAttrib, lpGroupInfo);
|
|
}
|
|
|
|
UNLOCK_CACHE();
|
|
return dwError;
|
|
}
|
|
|
|
|
|
DWORD CConMgr::RegisterCacheNotify(
|
|
HWND hWnd,
|
|
UINT uMsg,
|
|
GROUPID gid,
|
|
DWORD dwFilter
|
|
)
|
|
{
|
|
DWORD dwError;
|
|
INET_ASSERT(_coContent);
|
|
dwError = _coContent->RegisterCacheNotify(hWnd, uMsg, gid, dwFilter);
|
|
return dwError;
|
|
}
|
|
|
|
DWORD CConMgr::SendCacheNotification( DWORD dwOp)
|
|
{
|
|
DWORD dwError;
|
|
|
|
INET_ASSERT(_coContent);
|
|
_coContent->SendCacheNotification(dwOp);
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
VOID CConMgr::GetCacheInfo
|
|
----------------------------------------------------------------------------*/
|
|
VOID CConMgr::GetCacheInfo(LPCSTR szPrefix, LPSTR szCachePath, LONGLONG *cbLimit)
|
|
{
|
|
URL_CONTAINER *co;
|
|
// Find the associated container.
|
|
|
|
LOCK_CACHE();
|
|
DWORD idx = FindIndexFromPrefix(szPrefix);
|
|
|
|
co = ConList.Get(idx);
|
|
|
|
if (co)
|
|
{
|
|
// Call GetCacheInfo on the appropriate container.
|
|
co->GetCacheInfo(szCachePath, cbLimit);
|
|
co->Release(TRUE);
|
|
}
|
|
|
|
UNLOCK_CACHE();
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
VOID CConMgr::SetCacheLimit
|
|
----------------------------------------------------------------------------*/
|
|
VOID CConMgr::SetCacheLimit(LONGLONG cbLimit, DWORD idx)
|
|
{
|
|
URL_CONTAINER *co;
|
|
// Find the associated container.
|
|
|
|
UNIX_RETURN_IF_READONLY_CACHE;
|
|
|
|
LOCK_CACHE();
|
|
co = ConList.Get(idx);
|
|
|
|
if (co)
|
|
{
|
|
// Call SetCacheLimit on the container.
|
|
co->SetCacheLimit(cbLimit);
|
|
co->Release(TRUE);
|
|
}
|
|
|
|
UNLOCK_CACHE();
|
|
}
|
|
|