Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1886 lines
51 KiB

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
cachapiw.cxx
Abstract:
contains the UNICODE version of cache mangemant APIs.
Author:
Madan Appiah (madana) 12-Dec-1994
Environment:
User Mode - Win32
Revision History:
Ahsan Kabir (akabir) Dec-1997
--*/
#include <cache.hxx>
#include <w95wraps.h>
#define NUMBER_MEMBERS 4
const BYTE bOffsetTable[NUMBER_MEMBERS] =
{
(BYTE)&(((LPINTERNET_CACHE_ENTRY_INFOW)NULL)->lpszSourceUrlName),
(BYTE)&(((LPINTERNET_CACHE_ENTRY_INFOW)NULL)->lpszLocalFileName),
(BYTE)&(((LPINTERNET_CACHE_ENTRY_INFOW)NULL)->lpHeaderInfo),
(BYTE)&(((LPINTERNET_CACHE_ENTRY_INFOW)NULL)->lpszFileExtension)
};
DWORD
TransformA2W(
IN LPINTERNET_CACHE_ENTRY_INFOA pCEIA,
IN DWORD cbCEIA,
OUT LPINTERNET_CACHE_ENTRY_INFOW pCEIW,
OUT LPDWORD pcbCEIW
)
{
DWORD cbSize = sizeof(INTERNET_CACHE_ENTRY_INFOW);
DWORD cc;
if (!pCEIW || (*pcbCEIW<sizeof(INTERNET_CACHE_ENTRY_INFOW)))
{
*pcbCEIW = 0;
cc = 0;
}
else
{
//
// copy fixed portion.
//
memcpy((PBYTE)pCEIW, (PBYTE)pCEIA, sizeof(INTERNET_CACHE_ENTRY_INFOW) );
pCEIW->dwStructSize = sizeof(INTERNET_CACHE_ENTRY_INFOW);
cc = (*pcbCEIW - sizeof(INTERNET_CACHE_ENTRY_INFOW))/sizeof(WCHAR);
}
// Destination for strings
PWSTR pBuffer = (pCEIW ? (PWSTR)(pCEIW + 1) : NULL);
// Convert strings
for (int i=0; i < NUMBER_MEMBERS; i++)
{
PSTR *pBufferA = (PSTR*)((PBYTE)pCEIA + bOffsetTable[i]);
if (*pBufferA)
{
DWORD dwTmp = MultiByteToWideChar(CP_ACP, 0, *pBufferA, -1, NULL, 0);
if ((dwTmp<=cc) && pCEIW)
{
INET_ASSERT(pBuffer);
PWSTR *pBufferW = (PWSTR*)((PBYTE)pCEIW + bOffsetTable[i]);
*pBufferW = pBuffer;
MultiByteToWideChar(CP_ACP, 0, *pBufferA, -1, *pBufferW, dwTmp);
pBuffer += dwTmp;
cc -= dwTmp;
}
cbSize += dwTmp*sizeof(WCHAR);
}
}
DWORD dwErr = (*pcbCEIW>=cbSize) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
*pcbCEIW = cbSize; // Tell how much space used/needed.
return dwErr;
}
URLCACHEAPI_(BOOL) CreateUrlCacheEntryW(
IN LPCWSTR lpszUrlName,
IN DWORD dwExpectedFileSize,
IN LPCWSTR lpszFileExtension,
OUT LPWSTR lpszFileName,
IN DWORD dwReserved
)
{
ENTER_CACHE_API ((DBG_API, Bool, "CreateUrlCacheEntryW", "%wq, %wq, %d, %wq, %#x",
lpszUrlName, lpszFileExtension, dwExpectedFileSize, lpszFileName, dwReserved));
DWORD dwErr = ERROR_SUCCESS;
BOOL fResult = FALSE, fStrNotSafe = FALSE;
MEMORYPACKET mpUrlName, mpFileExtension, mpFileName;
if (lpszUrlName)
{
ALLOC_MB(lpszUrlName,0,mpUrlName);
if (!mpUrlName.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(lpszUrlName,mpUrlName, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
}
if (lpszFileExtension)
{
ALLOC_MB(lpszFileExtension,0,mpFileExtension);
if (!mpFileExtension.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(lpszFileExtension,mpFileExtension, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
}
ALLOC_MB(NULL, MAX_PATH, mpFileName);
if (!mpFileName.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
fResult = CreateUrlCacheEntryA(
mpUrlName.psStr,
dwExpectedFileSize,
mpFileExtension.psStr,
mpFileName.psStr,
dwReserved);
if (fResult)
{
MultiByteToWideChar(CP_ACP, 0, mpFileName.psStr, -1, lpszFileName, MAX_PATH);
}
cleanup:
if (dwErr!=ERROR_SUCCESS)
{
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
URLCACHEAPI_(BOOL) CommitUrlCacheEntryW(
IN LPCWSTR lpszUrlName,
IN LPCWSTR lpszLocalFileName,
IN FILETIME ExpireTime,
IN FILETIME LastModifiedTime,
IN DWORD CacheEntryType,
IN LPWSTR lpszHeaderInfo,
IN DWORD dwHeaders,
IN LPCWSTR lpszFileExtension,
IN LPCWSTR lpszOriginalUrl
)
{
ENTER_CACHE_API ((DBG_API, Bool, "CommitUrlCacheEntryW",
"%wq, %wq, <expires>, <last-mod>, %d, %wq, %d, %wq, %wq",
lpszUrlName,
lpszLocalFileName,
CacheEntryType,
lpszHeaderInfo,
dwHeaders,
lpszFileExtension,
lpszOriginalUrl
));
BOOL fResult = FALSE;
BOOL fStrNotSafe = FALSE;
DWORD dwErr = ERROR_SUCCESS;
MEMORYPACKET mpUrlName, mpLocalFileName, mpFileExtension, mpHeaders, mpOriginalUrl;
if( IsBadUrlW( lpszUrlName ) ||
( lpszLocalFileName ? IsBadStringPtrW( lpszLocalFileName, MAX_PATH ) : FALSE ) )
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
ALLOC_MB(lpszUrlName,0,mpUrlName);
if (!mpUrlName.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(lpszUrlName,mpUrlName, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
if (lpszLocalFileName)
{
ALLOC_MB(lpszLocalFileName,0,mpLocalFileName);
if (!mpLocalFileName.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(lpszLocalFileName,mpLocalFileName, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
}
if (lpszFileExtension)
{
ALLOC_MB(lpszFileExtension,0,mpFileExtension);
if (!mpFileExtension.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(lpszFileExtension,mpFileExtension, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
}
if (lpszHeaderInfo)
{
ALLOC_MB(lpszHeaderInfo,0,mpHeaders);
if (!mpHeaders.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(lpszHeaderInfo,mpHeaders, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
}
if (lpszOriginalUrl)
{
ALLOC_MB(lpszOriginalUrl,0,mpOriginalUrl);
if (!mpOriginalUrl.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(lpszOriginalUrl,mpOriginalUrl, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
}
fResult = CommitUrlCacheEntryA(
mpUrlName.psStr,
mpLocalFileName.psStr,
ExpireTime,
LastModifiedTime,
CacheEntryType,
(LPBYTE)mpHeaders.psStr,
mpHeaders.dwSize,
mpFileExtension.psStr,
mpOriginalUrl.psStr);
cleanup:
if (dwErr!=ERROR_SUCCESS)
{
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
BOOL
RetrieveUrlCacheEntryWCore(
IN LPCWSTR lpszUrlName,
OUT LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
IN OUT LPDWORD lpcbCacheEntryInfo,
IN DWORD dwReserved,
IN DWORD dwLookupFlags,
IN DWORD dwRetrievalFlags)
{
DWORD dwErr = ERROR_SUCCESS;
BOOL fStrNotSafe = FALSE;
MEMORYPACKET mpUrlName;
LPINTERNET_CACHE_ENTRY_INFOA pCEIA = NULL;
DWORD dwCEI = 0;
if (!InitGlobals())
{
dwErr = ERROR_INTERNET_INTERNAL_ERROR;
goto cleanup;
}
if (!(lpszUrlName && lpcbCacheEntryInfo))
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
ALLOC_MB(lpszUrlName, 0, mpUrlName);
if (!mpUrlName.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(lpszUrlName, mpUrlName, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
dwErr = GlobalUrlContainers->RetrieveUrl(
mpUrlName.psStr,
&pCEIA,
&dwCEI,
dwLookupFlags,
dwRetrievalFlags | RETRIEVE_WITH_ALLOCATION);
if (dwErr==ERROR_SUCCESS)
{
dwErr = TransformA2W(
pCEIA,
dwCEI,
lpCacheEntryInfo,
lpcbCacheEntryInfo);
if (dwErr!=ERROR_SUCCESS)
{
UnlockUrlCacheEntryFileW(lpszUrlName, 0);
}
}
cleanup:
if (pCEIA)
{
FREE_MEMORY(pCEIA);
}
if (dwErr!=ERROR_SUCCESS)
{
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
return (dwErr == ERROR_SUCCESS);
}
URLCACHEAPI_(BOOL) RetrieveUrlCacheEntryFileW(
IN LPCWSTR lpszUrlName,
OUT LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
IN OUT LPDWORD lpcbCacheEntryInfo,
IN DWORD dwReserved
)
{
ENTER_CACHE_API ((DBG_API, Bool, "RetrieveUrlCacheEntryFileW","%wq, %#x, %#x, %#x",
lpszUrlName, lpCacheEntryInfo, lpcbCacheEntryInfo, dwReserved));
BOOL fResult = RetrieveUrlCacheEntryWCore(
lpszUrlName,
lpCacheEntryInfo,
lpcbCacheEntryInfo,
dwReserved,
LOOKUP_URL_CREATE,
RETRIEVE_WITH_CHECKS);
DEBUG_LEAVE_API(fResult);
return fResult;
}
URLCACHEAPI_(HANDLE) RetrieveUrlCacheEntryStreamW(
IN LPCWSTR lpszUrlName,
OUT LPCACHE_ENTRY_INFOW lpCacheEntryInfo,
IN OUT LPDWORD lpcbCacheEntryInfo,
IN BOOL fRandomRead,
IN DWORD dwReserved
)
{
ENTER_CACHE_API ((DBG_API, Handle, "RetrieveUrlCacheEntryStreamW",
"%wq, %#x, %#x, %d, %#x",
lpszUrlName,
lpCacheEntryInfo,
lpcbCacheEntryInfo,
fRandomRead,
dwReserved
));
BOOL fLocked = FALSE;
HANDLE hInternet = NULL;
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD dwErr = ERROR_SUCCESS, dwFileSize;
CACHE_STREAM_CONTEXT_HANDLE* pStream;
if (!RetrieveUrlCacheEntryWCore(
lpszUrlName,
lpCacheEntryInfo,
lpcbCacheEntryInfo,
dwReserved,
LOOKUP_URL_NOCREATE,
RETRIEVE_WITHOUT_CHECKS))
{
goto cleanup;
}
fLocked = TRUE;
// Allocate a stream handle.
LOCK_CACHE();
hInternet = HandleMgr.Alloc (sizeof(CACHE_STREAM_CONTEXT_HANDLE));
if (hInternet)
{
pStream = (CACHE_STREAM_CONTEXT_HANDLE*) HandleMgr.Map (hInternet);
INET_ASSERT (pStream);
}
UNLOCK_CACHE();
if (!hInternet)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
// Open the file.
// Does CreateFileW exist on Win9x?
hFile = CreateFileW
(
lpCacheEntryInfo->lpszLocalFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL |
(fRandomRead ? FILE_FLAG_RANDOM_ACCESS : FILE_FLAG_SEQUENTIAL_SCAN),
// improves file read (cache) performance?
NULL
);
if( hFile == INVALID_HANDLE_VALUE )
{
dwErr = GetLastError();
goto cleanup;
}
dwFileSize = GetFileSize(hFile, NULL);
if (dwFileSize != lpCacheEntryInfo->dwSizeLow)
{
dwErr = (dwFileSize==0xFFFFFFFF) ? GetLastError() : ERROR_INVALID_DATA;
goto cleanup;
}
pStream->FileHandle = hFile;
// Copy URL name storage.
{
MEMORYPACKET mpUrl;
ALLOC_MB(lpszUrlName,0,mpUrl);
if (!mpUrl.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI(lpszUrlName,mpUrl);
pStream->SourceUrlName = NewString(mpUrl.psStr);
if( !pStream->SourceUrlName)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
}
cleanup:
if (dwErr!=ERROR_SUCCESS)
{
if (hInternet)
{
HandleMgr.Free(hInternet);
hInternet = NULL;
}
if (hFile)
CloseHandle (hFile);
if (fLocked)
{
UnlockUrlCacheEntryFileW(lpszUrlName, 0);
}
SetLastError (dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(hInternet);
return hInternet;
}
BOOL
GetUrlCacheEntryWCore(
IN LPCWSTR lpszUrl,
OUT LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
IN OUT LPDWORD lpcbCacheEntryInfo,
DWORD dwFlags,
DWORD dwLookupFlags,
BOOL fConvertHeaders)
{
BOOL fResult = FALSE;
DWORD dwErr = ERROR_SUCCESS;
BOOL fStrNotSafe = FALSE;
MEMORYPACKET mpUrlName;
LPINTERNET_CACHE_ENTRY_INFOA pCEIA = NULL;
DWORD cbCEIA;
if (!InitGlobals())
{
dwErr = ERROR_INTERNET_INTERNAL_ERROR;
goto cleanup;
}
if (IsBadUrlW(lpszUrl))
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
ALLOC_MB(lpszUrl,0,mpUrlName);
if (!mpUrlName.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(lpszUrl,mpUrlName, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
if (lpcbCacheEntryInfo)
{
dwErr = GlobalUrlContainers->GetUrlInfo(
mpUrlName.psStr,
&pCEIA,
&cbCEIA,
dwFlags,
dwLookupFlags,
RETRIEVE_WITH_ALLOCATION);
// convert from ansi to unicode.
if (dwErr==ERROR_SUCCESS)
{
dwErr = TransformA2W(pCEIA, cbCEIA, lpCacheEntryInfo, lpcbCacheEntryInfo);
if (dwErr==ERROR_SUCCESS)
{
fResult = TRUE;
}
}
}
else
{
fResult = GetUrlCacheEntryInfoExA(
mpUrlName.psStr,
NULL,
NULL,
NULL,
NULL,
NULL,
dwFlags);
}
cleanup:
if (pCEIA)
{
FREE_MEMORY(pCEIA);
}
if (dwErr!=ERROR_SUCCESS)
{
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
return fResult;
}
URLCACHEAPI_(BOOL) GetUrlCacheEntryInfoW(
IN LPCWSTR lpszUrlName,
OUT LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
IN OUT LPDWORD lpcbCacheEntryInfo
)
{
ENTER_CACHE_API ((DBG_API, Bool, "GetUrlCacheEntryInfoW", "%wq, %#x, %#x",
lpszUrlName, lpCacheEntryInfo, lpcbCacheEntryInfo));
BOOL fResult = GetUrlCacheEntryWCore(
lpszUrlName,
lpCacheEntryInfo,
lpcbCacheEntryInfo,
0,
LOOKUP_URL_NOCREATE,
TRUE);
DEBUG_LEAVE_API(fResult);
return fResult;
}
BOOLAPI GetUrlCacheEntryInfoExW(
IN LPCWSTR lpszUrl,
OUT LPINTERNET_CACHE_ENTRY_INFOW lpCacheEntryInfo,
IN OUT LPDWORD lpcbCacheEntryInfo,
OUT LPWSTR lpszRedirectUrl,
IN OUT LPDWORD lpcbRedirectUrl,
LPVOID lpReserved,
DWORD dwFlags
)
{
ENTER_CACHE_API ((DBG_API, Bool, "GetUrlCacheEntryInfoExW",
"%wq, %#x, %#x, %wq, %#x, %#x, %#x",
lpszUrl, lpCacheEntryInfo, lpcbCacheEntryInfo, lpszRedirectUrl, lpcbRedirectUrl, lpReserved, dwFlags));
DWORD dwErr = ERROR_SUCCESS;
BOOL fResult = FALSE;
if (lpszRedirectUrl
|| lpcbRedirectUrl
|| lpReserved
)
{
INET_ASSERT (FALSE);
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
fResult = GetUrlCacheEntryWCore(
lpszUrl,
lpCacheEntryInfo,
lpcbCacheEntryInfo,
dwFlags,
LOOKUP_URL_TRANSLATE | (dwFlags & INTERNET_CACHE_FLAG_ALLOW_COLLISIONS),
TRUE);
cleanup:
if (dwErr!=ERROR_SUCCESS)
{
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
URLCACHEAPI_(BOOL) SetUrlCacheEntryInfoW(
IN LPCWSTR lpszUrlName,
IN LPCACHE_ENTRY_INFOW lpCacheEntryInfo,
IN DWORD dwFieldControl
)
{
ENTER_CACHE_API ((DBG_API, Bool, "SetUrlCacheEntryInfoW", "%wq, %#x, %d",
lpszUrlName, lpCacheEntryInfo, dwFieldControl));
BOOL fResult = FALSE;
BOOL fStrNotSafe = FALSE;
DWORD dwErr = ERROR_SUCCESS;
MEMORYPACKET mpUrlName;
INTERNET_CACHE_ENTRY_INFOA CacheEntryInfoA;
if (!lpszUrlName)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
memcpy( &CacheEntryInfoA, lpCacheEntryInfo, sizeof(CacheEntryInfoA) );
ALLOC_MB(lpszUrlName,0,mpUrlName);
if (!mpUrlName.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(lpszUrlName,mpUrlName, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
fResult = SetUrlCacheEntryInfoA(
mpUrlName.psStr,
&CacheEntryInfoA,
dwFieldControl );
cleanup:
if (dwErr!=ERROR_SUCCESS)
{
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
BOOL FindUrlCacheEntryWCore(
IN OUT HANDLE *phFind,
IN LPCWSTR lpszUrlSearchPattern,
IN DWORD dwFlags,
IN DWORD dwFilter,
IN GROUPID GroupId,
OUT LPINTERNET_CACHE_ENTRY_INFOW pEntryInfo,
IN OUT LPDWORD pcbEntryInfo,
IN BOOL fConvertHeaders
)
{
DWORD dwErr = ERROR_SUCCESS;
BOOL fStrNotSafe = FALSE;
MEMORYPACKET mpSearchPattern;
LPINTERNET_CACHE_ENTRY_INFOA pCEIA = NULL;
DWORD cbCEIA;
BOOL fFindFirst = *phFind==NULL;
// DebugBreak();
if (!InitGlobals())
{
dwErr = ERROR_INTERNET_INTERNAL_ERROR;
goto cleanup;
}
if (!pcbEntryInfo)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
if (lpszUrlSearchPattern)
{
ALLOC_MB(lpszUrlSearchPattern, 0, mpSearchPattern);
if (!mpSearchPattern.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(lpszUrlSearchPattern, mpSearchPattern, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
}
dwErr = GlobalUrlContainers->FindNextEntry(phFind,
mpSearchPattern.psStr,
&pCEIA,
&cbCEIA,
dwFilter,
GroupId,
dwFlags,
RETRIEVE_WITH_ALLOCATION);
// TransformA2W will convert from ansi to unicode. ERROR_SUCCESS always means that
// the cache entry has been returned.
if (dwErr==ERROR_SUCCESS)
{
dwErr = TransformA2W(pCEIA,
cbCEIA,
pEntryInfo,
pcbEntryInfo);
}
cleanup:
if (pCEIA)
{
FREE_MEMORY(pCEIA);
}
if (dwErr!=ERROR_SUCCESS)
{
if (fFindFirst && *phFind)
{
GlobalUrlContainers->FreeFindHandle(*phFind);
*phFind = NULL;
}
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
return (dwErr==ERROR_SUCCESS) ;
}
URLCACHEAPI_(HANDLE) FindFirstUrlCacheEntryW(
IN LPCWSTR lpszUrlSearchPattern,
OUT LPCACHE_ENTRY_INFOW lpFirstCacheEntryInfo,
IN OUT LPDWORD lpcbCacheEntryInfo
)
{
ENTER_CACHE_API ((DBG_API, Bool, "FindFirstUrlCacheEntryW",
"%wq, %#x, %#x",
lpszUrlSearchPattern,
lpFirstCacheEntryInfo,
lpcbCacheEntryInfo
));
HANDLE hInternet = FindFirstUrlCacheEntryExW(
lpszUrlSearchPattern,
FIND_FLAGS_OLD_SEMANTICS,
URLCACHE_FIND_DEFAULT_FILTER,
NULL,
lpFirstCacheEntryInfo,
lpcbCacheEntryInfo,
NULL,
NULL,
NULL);
DEBUG_LEAVE_API(hInternet);
return hInternet;
}
URLCACHEAPI_(BOOL) FindNextUrlCacheEntryW(
IN HANDLE hEnumHandle,
OUT LPCACHE_ENTRY_INFOW pEntryInfo,
IN OUT LPDWORD pcbEntryInfo
)
{
ENTER_CACHE_API ((DBG_API, Bool, "FindNextUrlCacheEntryW",
"%#x, %#x, %#x",
hEnumHandle,
pEntryInfo,
pcbEntryInfo
));
BOOL fResult = FindNextUrlCacheEntryExW(
hEnumHandle,
pEntryInfo,
pcbEntryInfo,
NULL,
NULL,
NULL);
DEBUG_LEAVE_API(fResult);
return fResult;
}
INTERNETAPI_(HANDLE) FindFirstUrlCacheEntryExW(
IN LPCWSTR lpszUrlSearchPattern,
IN DWORD dwFlags,
IN DWORD dwFilter,
IN GROUPID GroupId,
OUT LPINTERNET_CACHE_ENTRY_INFOW pEntryInfo,
IN OUT LPDWORD pcbEntryInfo,
OUT LPVOID lpGroupAttributes, // must pass NULL
IN OUT LPDWORD pcbGroupAttributes, // must pass NULL
IN LPVOID lpReserved // must pass NULL
)
{
ENTER_CACHE_API ((DBG_API, Bool, "FindFirstUrlCacheEntryExW",
"%wq, %#x, %#x, %#x, %#x, %#x, %#x, %#x, %#x",
lpszUrlSearchPattern,
dwFlags,
dwFilter,
GroupId,
pEntryInfo,
pcbEntryInfo,
lpGroupAttributes,
pcbGroupAttributes,
lpReserved
));
HANDLE hInternet = NULL;
FindUrlCacheEntryWCore(
&hInternet,
lpszUrlSearchPattern,
dwFlags,
dwFilter,
GroupId,
pEntryInfo,
pcbEntryInfo,
TRUE);
DEBUG_LEAVE_API(hInternet);
return hInternet;
}
BOOLAPI FindNextUrlCacheEntryExW(
IN HANDLE hEnumHandle,
OUT LPINTERNET_CACHE_ENTRY_INFOW pEntryInfo,
IN OUT LPDWORD pcbEntryInfo,
OUT LPVOID lpGroupAttributes, // must pass NULL
IN OUT LPDWORD pcbGroupAttributes, // must pass NULL
IN LPVOID lpReserved // must pass NULL
)
{
ENTER_CACHE_API ((DBG_API, Bool, "FindNextUrlCacheEntryExW",
"%#x, %#x, %#x, %#x, %#x, %#x",
hEnumHandle,
pEntryInfo,
pcbEntryInfo,
lpGroupAttributes,
pcbGroupAttributes,
lpReserved
));
BOOL fResult = FALSE;
DWORD dwErr = ERROR_SUCCESS;
if (!hEnumHandle)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
fResult = FindUrlCacheEntryWCore(
&hEnumHandle,
NULL,
0,
0,
0,
pEntryInfo,
pcbEntryInfo,
TRUE);
cleanup:
if (dwErr!=ERROR_SUCCESS)
{
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
URLCACHEAPI_(BOOL) FreeUrlCacheSpaceW(
IN LPCWSTR lpszCachePath,
IN DWORD dwSize,
IN DWORD dwReserved
)
{
ENTER_CACHE_API ((DBG_API, Bool, "FreeUrlCacheSpaceW",
"<path>,%d, %#x", dwSize, dwReserved));
BOOL fResult = FALSE;
DWORD dwErr = ERROR_SUCCESS;
BOOL fStrNotSafe = FALSE;
MEMORYPACKET mpCachePath;
if (lpszCachePath)
{
ALLOC_MB(lpszCachePath,0,mpCachePath);
if (!mpCachePath.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(lpszCachePath,mpCachePath, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
}
fResult = FreeUrlCacheSpaceA(
mpCachePath.psStr,
dwSize,
dwReserved );
cleanup:
if (dwErr!=ERROR_SUCCESS)
{
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
URLCACHEAPI_(BOOL) UnlockUrlCacheEntryFileW(
LPCWSTR lpszUrlName,
IN DWORD dwReserved
)
/*++
Routine Description:
This API checks in the file that was check out as part of
RetrieveUrlFile API.
Arguments:
lpszUrlName : name of the URL that is being retrieved.
dwReserved : reserved for future use.
Return Value:
Windows Error code.
--*/
{
ENTER_CACHE_API ((DBG_API, Bool, "UnlockUrlCacheEntryFileW",
"%wq, %#x", lpszUrlName, dwReserved));
BOOL fResult = FALSE;
BOOL fStrNotSafe = FALSE;
DWORD dwErr = ERROR_SUCCESS;
MEMORYPACKET mpUrl;
if (!lpszUrlName)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
ALLOC_MB(lpszUrlName,0,mpUrl);
if (!mpUrl.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(lpszUrlName,mpUrl, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
fResult = UnlockUrlCacheEntryFileA(mpUrl.psStr, dwReserved);
cleanup:
if (dwErr!=ERROR_SUCCESS)
{
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
URLCACHEAPI_(BOOL) DeleteUrlCacheEntryW(
IN LPCWSTR lpszUrlName
)
{
ENTER_CACHE_API ((DBG_API, Bool, "DeleteUrlCacheEntryW",
"%wq", lpszUrlName));
BOOL fResult = FALSE;
BOOL fStrNotSafe = FALSE;
DWORD dwErr = ERROR_SUCCESS;
MEMORYPACKET mpUrl;
if (!lpszUrlName)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
ALLOC_MB(lpszUrlName,0,mpUrl);
if (!mpUrl.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(lpszUrlName,mpUrl, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
fResult = DeleteUrlCacheEntryA(mpUrl.psStr);
cleanup:
if (dwErr!=ERROR_SUCCESS)
{
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
BOOLAPI IsUrlCacheEntryExpiredW(
IN LPCWSTR lpszUrlName,
IN DWORD dwFlags,
IN OUT FILETIME* pftLastModifiedTime
)
{
ENTER_CACHE_API ((DBG_API, Bool, "UrlCacheEntryExpiredW",
"%wq, %#x", lpszUrlName, dwFlags));
BOOL fResult = FALSE;
BOOL fStrNotSafe = FALSE;
DWORD dwErr = ERROR_SUCCESS;
MEMORYPACKET mpUrl;
if (!lpszUrlName)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
ALLOC_MB(lpszUrlName,0,mpUrl);
if (!mpUrl.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(lpszUrlName,mpUrl, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
fResult = IsUrlCacheEntryExpiredA(
mpUrl.psStr,
dwFlags,
pftLastModifiedTime);
cleanup:
if (dwErr!=ERROR_SUCCESS)
{
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
BOOL CacheGroupInfoA2W(
IN LPINTERNET_CACHE_GROUP_INFOA lpAnsiGroupInfo,
IN DWORD dwAnsiGroupInfoSize,
OUT LPINTERNET_CACHE_GROUP_INFOW lpUnicodeGroupInfo,
IN OUT LPDWORD lpdwUnicodeGroupInfoSize
)
{
INET_ASSERT( lpUnicodeGroupInfo && lpAnsiGroupInfo);
lpUnicodeGroupInfo->dwGroupSize = sizeof(INTERNET_CACHE_GROUP_INFOW);
lpUnicodeGroupInfo->dwGroupFlags = lpAnsiGroupInfo->dwGroupFlags;
lpUnicodeGroupInfo->dwGroupType = lpAnsiGroupInfo->dwGroupType;
lpUnicodeGroupInfo->dwDiskUsage = lpAnsiGroupInfo->dwDiskUsage;
lpUnicodeGroupInfo->dwDiskQuota = lpAnsiGroupInfo->dwDiskQuota;
memcpy(lpUnicodeGroupInfo->dwOwnerStorage,
lpAnsiGroupInfo->dwOwnerStorage,
GROUP_OWNER_STORAGE_SIZE * sizeof(DWORD) );
BOOL fRet = MultiByteToWideChar(
CP_ACP,
MB_PRECOMPOSED,
lpAnsiGroupInfo->szGroupName,
-1, // null terminated ansi string.
lpUnicodeGroupInfo->szGroupName,
GROUPNAME_MAX_LENGTH
);
if( fRet )
{
*lpdwUnicodeGroupInfoSize = lpUnicodeGroupInfo->dwGroupSize;
}
else
{
*lpdwUnicodeGroupInfoSize = 0;
SetLastError(ERROR_INVALID_PARAMETER);
}
return fRet;
}
BOOL CacheGroupInfoW2A(
IN LPINTERNET_CACHE_GROUP_INFOW lpUnicodeGroupInfo,
IN DWORD dwUnicodeGroupInfoSize,
OUT LPINTERNET_CACHE_GROUP_INFOA lpAnsiGroupInfo,
IN OUT LPDWORD lpdwAnsiGroupInfoSize
)
{
INET_ASSERT( lpUnicodeGroupInfo && lpAnsiGroupInfo);
BOOL fStrNotSafe = FALSE;
lpAnsiGroupInfo->dwGroupSize = sizeof(INTERNET_CACHE_GROUP_INFOA);
lpAnsiGroupInfo->dwGroupFlags = lpUnicodeGroupInfo->dwGroupFlags;
lpAnsiGroupInfo->dwGroupType = lpUnicodeGroupInfo->dwGroupType;
lpAnsiGroupInfo->dwDiskUsage = lpUnicodeGroupInfo->dwDiskUsage;
lpAnsiGroupInfo->dwDiskQuota = lpUnicodeGroupInfo->dwDiskQuota;
memcpy( lpAnsiGroupInfo->dwOwnerStorage,
lpUnicodeGroupInfo->dwOwnerStorage,
GROUP_OWNER_STORAGE_SIZE * sizeof(DWORD) );
BOOL fRet = WideCharToMultiByte(
CP_ACP,
0, // no flags.
lpUnicodeGroupInfo->szGroupName,
-1, // null terminated unicode string.
lpAnsiGroupInfo->szGroupName,
GROUPNAME_MAX_LENGTH,
NULL, // lpDefaultChar
&fStrNotSafe // lpUseDefaultChar
);
if (fStrNotSafe)
{
fRet = FALSE;
}
if( fRet )
{
*lpdwAnsiGroupInfoSize = lpAnsiGroupInfo->dwGroupSize;
}
else
{
*lpdwAnsiGroupInfoSize = 0;
}
return fRet;
}
URLCACHEAPI_(BOOL) SetUrlCacheEntryGroupW(
IN LPCWSTR lpszUrlName,
IN DWORD dwFlags,
IN GROUPID GroupId,
IN LPBYTE pbGroupAttributes, // must pass NULL
IN DWORD cbGroupAttributes, // must pass 0
IN LPVOID lpReserved // must pass NULL
)
{
ENTER_CACHE_API ((DBG_API, Bool, "SetUrlCacheEntryGroupW",
"%wq, %#x, %#x, %#x, %#x, %#x", lpszUrlName, dwFlags, GroupId, pbGroupAttributes, cbGroupAttributes, lpReserved));
BOOL fResult = FALSE;
BOOL fStrNotSafe = FALSE;
DWORD dwErr = ERROR_SUCCESS;
MEMORYPACKET mpUrl;
if (!lpszUrlName)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
ALLOC_MB(lpszUrlName,0,mpUrl);
if (!mpUrl.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(lpszUrlName,mpUrl, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
fResult = SetUrlCacheEntryGroupA(
mpUrl.psStr,
dwFlags,
GroupId,
pbGroupAttributes,
cbGroupAttributes,
lpReserved);
cleanup:
if (dwErr!=ERROR_SUCCESS)
{
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
URLCACHEAPI_(BOOL) GetUrlCacheGroupAttributeW(
IN GROUPID gid,
IN DWORD dwFlags,
IN DWORD dwAttributes,
OUT LPINTERNET_CACHE_GROUP_INFOW lpGroupInfo,
IN OUT LPDWORD lpdwGroupInfo,
IN OUT LPVOID lpReserved
)
{
ENTER_CACHE_API ((DBG_API, Bool, "GetUrlCacheGroupAttributeW",
"%d, %d, %d, %#x, %#x, %#x",
gid, dwFlags, dwAttributes, lpGroupInfo, lpdwGroupInfo, lpReserved ));
BOOL fResult = FALSE;
DWORD Error = ERROR_SUCCESS;
INTERNET_CACHE_GROUP_INFOA AnsiGroupInfo;
DWORD dwAnsiGroupInfoSize = sizeof(INTERNET_CACHE_GROUP_INFOA);
if( !lpGroupInfo || !lpdwGroupInfo )
{
Error = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
if( *lpdwGroupInfo < sizeof(INTERNET_CACHE_GROUP_INFOW) )
{
Error = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
}
if( IsBadWriteUrlInfo(lpGroupInfo, *lpdwGroupInfo) )
{
Error = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
if( GetUrlCacheGroupAttributeA(
gid, dwFlags, dwAttributes,
&AnsiGroupInfo, &dwAnsiGroupInfoSize, lpReserved ) )
{
fResult = CacheGroupInfoA2W( &AnsiGroupInfo,
dwAnsiGroupInfoSize,
lpGroupInfo,
lpdwGroupInfo );
}
Cleanup:
if (Error!=ERROR_SUCCESS)
{
SetLastError(Error);
DEBUG_ERROR(API, Error);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
URLCACHEAPI_(BOOL) SetUrlCacheGroupAttributeW(
IN GROUPID gid,
IN DWORD dwFlags,
IN DWORD dwAttributes,
IN LPINTERNET_CACHE_GROUP_INFOW lpGroupInfo,
IN OUT LPVOID lpReserved
)
{
ENTER_CACHE_API ((DBG_API, Bool, "SetUrlCacheGroupAttributeA",
"%#x, %d, %d, %#x, %#x",
gid, dwFlags, dwAttributes, lpGroupInfo, lpReserved));
BOOL fResult = FALSE;
DWORD Error = ERROR_SUCCESS;
INTERNET_CACHE_GROUP_INFOA AnsiGroupInfo;
DWORD dwAnsiGroupInfoSize = sizeof(INTERNET_CACHE_GROUP_INFOA);
if( IsBadReadPtr(lpGroupInfo, sizeof(INTERNET_CACHE_GROUP_INFOW) ) )
{
Error = ERROR_INVALID_PARAMETER;
}
else if( CacheGroupInfoW2A(
lpGroupInfo, sizeof(INTERNET_CACHE_GROUP_INFOW),
&AnsiGroupInfo, &dwAnsiGroupInfoSize ) )
{
fResult = SetUrlCacheGroupAttributeA(
gid, dwFlags, dwAttributes, &AnsiGroupInfo, lpReserved );
}
if (Error!=ERROR_SUCCESS)
{
SetLastError(Error);
DEBUG_ERROR(API, Error);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
// Convert all the ansi strings in a structure to unicode
/* How does this work?
Take this structure for example:
struct foo
{
DWORD dwA;
LPTSTR pszB;
DWORD dwC;
LPTSTR pszD;
};
where LPTSTR are embedded pointers
The memory layout is thus:
[DWORD][LPTSTR][DWORD][LPTSTR][embedded string pszB][embedded string pszD]
^ ^
| |
|-struct beginning |-beginning of embedded strings
Assuming a 32-bit platform, we can construct pointers (relative to the struct beginning) to each element
in the structure. In this case,
{ 0, sizeof(DWORD), sizeof(DWORD)+sizeof(LPTSTR), sizeof(DWORD)+sizeof(LPTSTR)+sizeof(DWORD) }
Let's say we're interested in strings only, and we know that these strings are embedded. We can create a byte table thus:
BYTE bFoo[] = { sizeof(DWORD), sizeof(DWORD)+sizeof(LPTSTR)+sizeof(DWORD) }
Alternatively:
BYTE bFoo[] =
{
(BYTE)&(((foo*)NULL)->pszB),
(BYTE)&(((foo*)NULL)->pszD)
};
This layout is the same for both Ansi and Unicode versions of a struct, UNLESS the struct contains for example
a TCHAR szWhat[256] (in which case, we can't use the bulk converter).
Pass BulkConverter the following parameters, to convert strings in one swoop.
pbSrc = casted pointer to the beginning of the ansi structure
pbDest = casted pointer to the beginning of the unicode structure
cbAvail = number of bytes available for embedded strings
wSkip = offset from the beginning of the structure, at which point embedded strings may be written
cElements = number of elements to convert from ansi to unicode
If BulkConverter succeeds, it'll return the number of bytes used.
If it fails, it will return the number of bytes needed to store all the unicode strings.
BUT HOW DOES THIS THING WORK?
Oh.
1. Using the offset table, we figure out where the pointer to the string is in both the structures.
2. Then using magic, we decided where to place the unicode string.
3. Figure how much space we'll need to store the unicode string
4. If that much is available, convert.
5. Keep track, either way.
6. Go to 1, if we have any other strings left.
*/
LONG BulkConverter(PBYTE pbSrc, PBYTE pbDest, LONG cbAvail, WORD wSkip, CONST BYTE abTable[], WORD cElements)
{
PWSTR pBuffer = (PWSTR)(pbDest + wSkip);
PSTR *pBufferA;
PWSTR *pBufferW;
for (DWORD i=0; i < cElements; i++)
{
pBufferA = (PSTR*)((PBYTE)pbSrc + abTable[i]);
pBufferW = (PWSTR*)((PBYTE)pbDest + abTable[i]);
if (*pBufferA)
{
*pBufferW = pBuffer;
LONG dwTmp = MultiByteToWideChar(CP_ACP, 0, *pBufferA, -1,
*pBufferW, 0);
if (dwTmp<cbAvail)
{
MultiByteToWideChar(CP_ACP, 0, *pBufferA, -1,
*pBufferW, cbAvail);
pBuffer += dwTmp;
}
cbAvail -= dwTmp;
}
}
return cbAvail;
}
const BYTE bOffsetTableContainer[] =
{
(BYTE)&(((LPINTERNET_CACHE_CONTAINER_INFOW)NULL)->lpszName),
(BYTE)&(((LPINTERNET_CACHE_CONTAINER_INFOW)NULL)->lpszCachePrefix),
(BYTE)&(((LPINTERNET_CACHE_CONTAINER_INFOW)NULL)->lpszVolumeLabel),
(BYTE)&(((LPINTERNET_CACHE_CONTAINER_INFOW)NULL)->lpszVolumeTitle)
};
BOOL
TransformCacheContainerInfoToW(
IN BOOL fResult,
IN LPINTERNET_CACHE_CONTAINER_INFOA pCCIA,
IN DWORD cbCCIA,
OUT LPINTERNET_CACHE_CONTAINER_INFOW pCCIW,
OUT LPDWORD pcbCCIW
)
{
DWORD cbSize = *pcbCCIW;
if (fResult)
{
// If we have pointers, try to convert from
LONG cc = *pcbCCIW - sizeof(INTERNET_CACHE_CONTAINER_INFOW);
if (*pcbCCIW > sizeof(INTERNET_CACHE_CONTAINER_INFOW))
{
pCCIW->dwCacheVersion = pCCIA->dwCacheVersion;
}
cc /= sizeof(WCHAR);
// Convert strings
cc = BulkConverter((PBYTE)pCCIA,
(PBYTE)pCCIW,
cc,
sizeof(INTERNET_CACHE_CONTAINER_INFOW),
bOffsetTableContainer,
ARRAY_ELEMENTS(bOffsetTableContainer));
// Tell how much space was actually used.
*pcbCCIW -= cc*sizeof(WCHAR);
if (*pcbCCIW>cbSize)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
fResult = FALSE;
}
}
else if (GetLastError()==ERROR_INSUFFICIENT_BUFFER)
{
*pcbCCIW = (cbCCIA - sizeof(INTERNET_CACHE_CONTAINER_INFOA))*sizeof(WCHAR) + sizeof(INTERNET_CACHE_CONTAINER_INFOW);
}
return fResult;
}
#define USE_ORIGINAL_CODE
URLCACHEAPI_(BOOL) CreateUrlCacheContainerW(
IN LPCWSTR Name,
IN LPCWSTR CachePrefix,
IN LPCWSTR CachePath,
IN DWORD KBCacheLimit,
IN DWORD dwContainerType,
IN DWORD dwOptions,
IN OUT LPVOID pvBuffer,
IN OUT LPDWORD cbBuffer)
{
ENTER_CACHE_API ((DBG_API, Bool, "CreateUrlCacheContainerW", "%wq, %wq, %wq, %d, %d, %d, %#x, %#x",
Name, CachePrefix, CachePath, KBCacheLimit, dwContainerType, dwOptions, pvBuffer, cbBuffer));
DWORD dwErr = ERROR_SUCCESS;
BOOL fResult = FALSE;
MEMORYPACKET mpName, mpCachePrefix, mpCachePath;
BOOL fStrNotSafe = FALSE;
#ifdef USE_ORIGINAL_CODE
if (Name)
{
ALLOC_MB(Name, 0, mpName);
if (!mpName.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(Name, mpName, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
}
if (CachePrefix)
{
ALLOC_MB(CachePrefix, 0, mpCachePrefix);
if (!mpCachePrefix.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(CachePrefix, mpCachePrefix, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
}
if (CachePath)
{
ALLOC_MB(CachePath,0,mpCachePath);
if (!mpCachePath.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(CachePath,mpCachePath, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
}
#else
// Theoretically, the following fragment should be smaller than the above fragment.
// Although the retail obj shows a function that's about 100 bytes shorter, the
// actual dll doesn't show this gain. Until I figure this out, we won't use it.
DWORD c;
do
{
MEMORYPACKET* mp;
PCWSTR psz;
switch (c)
{
case 0:
psz = Name;
mp = &mpName;
break;
case 1:
psz = CachePrefix;
mp = &mpCachePrefix;
break;
case 2:
psz = CachePath;
mp = &mpCachePath;
break;
}
ALLOC_MB(psz, 0, (*mp));
if (!mp->psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(psz, (*mp), &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
c++;
}
while (c<3);
#endif
fResult = CreateUrlCacheContainerA(
mpName.psStr,
mpCachePrefix.psStr,
mpCachePath.psStr,
KBCacheLimit,
dwContainerType,
dwOptions,
pvBuffer,
cbBuffer);
cleanup:
if (dwErr!=ERROR_SUCCESS)
{
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
URLCACHEAPI_(BOOL) DeleteUrlCacheContainerW(
IN LPCWSTR Name,
IN DWORD dwOptions)
{
ENTER_CACHE_API ((DBG_API, Bool, "DeleteContainerW", "%wq, %#x", Name, dwOptions));
DWORD dwErr = ERROR_SUCCESS;
MEMORYPACKET mpName;
BOOL fResult = FALSE, fStrNotSafe = FALSE;
ALLOC_MB(Name, 0, mpName);
if (!mpName.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI_CHECKED(Name, mpName, &fStrNotSafe);
if (fStrNotSafe)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
fResult = DeleteUrlCacheContainerA(mpName.psStr, dwOptions);
cleanup:
if (dwErr!=ERROR_SUCCESS)
{
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
URLCACHEAPI_(HANDLE) FindFirstUrlCacheContainerW(
IN OUT DWORD *pdwModified,
OUT LPINTERNET_CACHE_CONTAINER_INFOW lpContainerInfo,
IN OUT LPDWORD lpcbContainerInfo,
IN DWORD dwOptions
)
{
ENTER_CACHE_API ((DBG_API, Bool, "FindFirstContainerW",
"%#x, %#x, %#x, %#x",
pdwModified,
lpContainerInfo,
lpcbContainerInfo,
dwOptions
));
DWORD dwErr = ERROR_SUCCESS;
MEMORYPACKET mpCacheInfo;
HANDLE hInternet = NULL;
if (!(lpcbContainerInfo && lpContainerInfo))
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
mpCacheInfo.psStr = (PSTR)ALLOC_BYTES(*lpcbContainerInfo);
if (!mpCacheInfo.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
mpCacheInfo.dwSize = mpCacheInfo.dwAlloc = *lpcbContainerInfo;
hInternet = FindFirstUrlCacheContainerA(pdwModified,
(LPINTERNET_CACHE_CONTAINER_INFOA)mpCacheInfo.psStr, &mpCacheInfo.dwSize, dwOptions);
// TransformCacheContainerInfoToW takes the return value and decides if any further actions need to be taken
// (eg. if successful, then try to convert from ansi to unicode; else if the ansi api failed, should we care?)
if (!TransformCacheContainerInfoToW(
hInternet ? TRUE : FALSE,
(LPINTERNET_CACHE_CONTAINER_INFOA)mpCacheInfo.psStr,
mpCacheInfo.dwSize,
lpContainerInfo,
lpcbContainerInfo))
{
if (hInternet)
{
FindCloseUrlCache(hInternet);
hInternet = NULL;
}
}
cleanup:
if (dwErr!=ERROR_SUCCESS)
{
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(hInternet);
return hInternet;
}
URLCACHEAPI_(BOOL) FindNextUrlCacheContainerW(
IN HANDLE hEnumHandle,
OUT LPINTERNET_CACHE_CONTAINER_INFOW lpContainerInfo,
IN OUT LPDWORD lpcbContainerInfo
)
{
ENTER_CACHE_API ((DBG_API, Bool, "FindNextContainerW",
"%#x, %#x, %#x",
hEnumHandle,
lpContainerInfo,
lpcbContainerInfo
));
DWORD dwErr = ERROR_SUCCESS;
MEMORYPACKET mpCacheInfo;
BOOL fResult = FALSE;
if (!(lpcbContainerInfo && lpContainerInfo))
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
mpCacheInfo.psStr = (PSTR)ALLOC_BYTES(*lpcbContainerInfo);
if (!mpCacheInfo.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
mpCacheInfo.dwSize = mpCacheInfo.dwAlloc = *lpcbContainerInfo;
fResult = FindNextUrlCacheContainerA(
hEnumHandle,
(LPINTERNET_CACHE_CONTAINER_INFOA)mpCacheInfo.psStr,
&mpCacheInfo.dwSize);
// TransformCacheContainerInfoToW takes the return value and decides if any further actions need to be taken
// (eg. if successful, then try to convert from ansi to unicode; else if the ansi api failed, should we care?)
fResult = TransformCacheContainerInfoToW(
fResult,
(LPINTERNET_CACHE_CONTAINER_INFOA)mpCacheInfo.psStr,
mpCacheInfo.dwSize,
lpContainerInfo,
lpcbContainerInfo);
cleanup:
if (dwErr!=ERROR_SUCCESS)
{
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
/* here's the struct referred to below
typedef struct _INTERNET_CACHE_CONFIG_INFOA {
DWORD dwStructSize;
DWORD dwContainer;
DWORD dwQuota;
DWORD dwReserved4;
BOOL fPerUser;
DWORD dwSyncMode;
DWORD dwNumCachePaths;
union
{
struct
{
CHAR CachePath[MAX_PATH];
DWORD dwCacheSize;
};
INTERNET_CACHE_CONFIG_PATH_ENTRYA CachePaths[ANYSIZE_ARRAY];
};
DWORD dwNormalUsage;
DWORD dwExemptUsage;
} INTERNET_CACHE_CONFIG_INFOA, * LPINTERNET_CACHE_CONFIG_INFOA;
*/
#define ICCIA_FIXED_PORTION_SIZE ((sizeof(DWORD)*6)+sizeof(BOOL))
URLCACHEAPI_(BOOL) GetUrlCacheConfigInfoW(
OUT LPINTERNET_CACHE_CONFIG_INFOW pCacheConfigInfo,
IN OUT LPDWORD pcbCacheConfigInfo,
IN DWORD dwFieldControl
)
{
ENTER_CACHE_API ((DBG_API, Bool, "GetUrlCacheConfigInfoW", "%#x, %#x, %#x",
pCacheConfigInfo, pcbCacheConfigInfo, dwFieldControl ));
INTERNET_CACHE_CONFIG_INFOA iccia;
iccia.dwContainer = pCacheConfigInfo->dwContainer;
iccia.dwStructSize = sizeof(INTERNET_CACHE_CONFIG_INFOA);
DWORD dwSize = sizeof(INTERNET_CACHE_CONFIG_INFOA);
BOOL fResult = GetUrlCacheConfigInfoA(&iccia, &dwSize, dwFieldControl);
if (fResult)
{
memcpy(pCacheConfigInfo, &iccia, ICCIA_FIXED_PORTION_SIZE);
// These are appended to the _end_ of the structure.
pCacheConfigInfo->dwNormalUsage = iccia.dwNormalUsage;
pCacheConfigInfo->dwExemptUsage = iccia.dwExemptUsage;
pCacheConfigInfo->dwStructSize = sizeof(INTERNET_CACHE_CONFIG_INFOW);
if (pCacheConfigInfo->dwContainer <= HISTORY)
{
MultiByteToWideChar(CP_ACP, 0, iccia.CachePath, -1, pCacheConfigInfo->CachePath, ARRAY_ELEMENTS(pCacheConfigInfo->CachePath));
}
}
DEBUG_LEAVE_API (fResult);
return fResult;
}
URLCACHEAPI_(BOOL) SetUrlCacheConfigInfoW(
LPCACHE_CONFIG_INFOW lpConfigConfigInfo,
DWORD dwFieldControl
)
{
SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
return( FALSE );
}