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.
469 lines
14 KiB
469 lines
14 KiB
/*++
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name: instcon.cxx
|
|
|
|
Abstract:
|
|
|
|
Installed container class derived from URL_CONTAINER
|
|
|
|
Author:
|
|
Adriaan Canter (adriaanc) 04-10-97
|
|
|
|
--*/
|
|
|
|
#include <cache.hxx>
|
|
|
|
#define HTTP_OK "HTTP/1.0 200 OK\r\n\r\n"
|
|
|
|
|
|
|
|
/*--------------------- CInstCon Public Functions-----------------------------*/
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
CInstCon::CInstCon
|
|
-----------------------------------------------------------------------------*/
|
|
CInstCon::CInstCon(LPSTR CacheName, LPSTR VolumeLabel, LPSTR VolumeTitle,
|
|
LPSTR CachePath, LPSTR CachePrefix, LPSTR PrefixMap,
|
|
LONGLONG CacheLimit, DWORD dwOptions)
|
|
|
|
: URL_CONTAINER(CacheName, CachePath, CachePrefix, CacheLimit, dwOptions)
|
|
{
|
|
if (_Status != ERROR_SUCCESS)
|
|
{
|
|
INET_ASSERT(FALSE);
|
|
return;
|
|
}
|
|
|
|
_szVolumeLabel = NewString(VolumeLabel);
|
|
_szVolumeTitle = NewString(VolumeTitle);
|
|
_szPrefixMap = NewString(PrefixMap);
|
|
|
|
if (!(_szVolumeLabel && _szVolumeTitle && _szPrefixMap))
|
|
{
|
|
INET_ASSERT(FALSE);
|
|
_Status = ERROR_NOT_ENOUGH_MEMORY;
|
|
return;
|
|
}
|
|
|
|
_cbPrefixMap = strlen(PrefixMap);
|
|
_cbMaxFileSize = MAX_FILE_SIZE_TO_MIGRATE;
|
|
_Status = ERROR_SUCCESS;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
CInstCon::~CInstCon
|
|
-----------------------------------------------------------------------------*/
|
|
CInstCon::~CInstCon()
|
|
{
|
|
delete _szPrefixMap;
|
|
delete _szVolumeLabel;
|
|
delete _szVolumeTitle;
|
|
}
|
|
|
|
|
|
/*------------------ URL_CONTAINER virtual overrides-------------------------*/
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
CInstCon::GetPrefixMap
|
|
-----------------------------------------------------------------------------*/
|
|
LPSTR CInstCon::GetPrefixMap()
|
|
{
|
|
return _szPrefixMap;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
CInstCon::GetVolumeLabel
|
|
-----------------------------------------------------------------------------*/
|
|
LPSTR CInstCon::GetVolumeLabel()
|
|
{
|
|
return _szVolumeLabel;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
CInstCon::GetVolumeTitle
|
|
-----------------------------------------------------------------------------*/
|
|
LPSTR CInstCon::GetVolumeTitle()
|
|
{
|
|
return _szVolumeTitle;
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
CInstCon::AddUrl
|
|
-----------------------------------------------------------------------------*/
|
|
DWORD CInstCon::AddUrl (AddUrlArg* pArgs)
|
|
{
|
|
pArgs->dwEntryType |= INSTALLED_CACHE_ENTRY;
|
|
return URL_CONTAINER::AddUrl(pArgs);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
CInstCon::RetrieveUrl
|
|
-----------------------------------------------------------------------------*/
|
|
DWORD CInstCon::RetrieveUrl(LPCSTR UrlName, LPCACHE_ENTRY_INFO EntryInfo,
|
|
LPDWORD EntryInfoSize, DWORD dwLookupFlags,
|
|
DWORD dwRetrievalFlags)
|
|
{
|
|
DWORD dwError;
|
|
BOOL fMustUnlock;
|
|
|
|
INET_ASSERT(EntryInfo && EntryInfoSize);
|
|
|
|
if (!LockContainer(&fMustUnlock))
|
|
{
|
|
dwError = GetLastError();
|
|
goto exit;
|
|
}
|
|
|
|
dwError = GetEntry(UrlName, EntryInfo, EntryInfoSize, dwLookupFlags);
|
|
|
|
exit:
|
|
if (fMustUnlock) UnlockContainer();
|
|
return dwError;
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
CInstCon::GetUrlInfo
|
|
-----------------------------------------------------------------------------*/
|
|
DWORD CInstCon::GetUrlInfo(LPCSTR szUrlName, LPCACHE_ENTRY_INFO pei,
|
|
LPDWORD pcbei, DWORD dwLookupFlags, DWORD dwEntryFlags)
|
|
{
|
|
DWORD dwError;
|
|
DWORD cbeiTemp = 0x256;
|
|
BYTE bTemp[0x256];
|
|
BOOL fMustUnlock;
|
|
|
|
if (!LockContainer(&fMustUnlock))
|
|
{
|
|
dwError = GetLastError();
|
|
goto exit;
|
|
}
|
|
|
|
// Zero buffer case.
|
|
if (pei && pcbei)
|
|
{
|
|
dwError = GetEntry(szUrlName, pei, pcbei, dwLookupFlags);
|
|
goto exit;
|
|
}
|
|
|
|
// Zero buffer case.
|
|
if (dwEntryFlags & INTERNET_CACHE_FLAG_ENTRY_OR_MAPPING)
|
|
{
|
|
// Return success to indicate that a mapping exists.
|
|
// We wouldn't have gotten here otherwise.
|
|
dwError = ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
// Otherwise, no flag passed in. Only return
|
|
// success if the entry has been successfully found.
|
|
dwError = GetEntry(szUrlName, (LPCACHE_ENTRY_INFO) bTemp,
|
|
&cbeiTemp, dwLookupFlags);
|
|
}
|
|
|
|
exit:
|
|
if (fMustUnlock) UnlockContainer();
|
|
return dwError;
|
|
}
|
|
|
|
|
|
/*--------------------- CInstCon Private Functions-----------------------------*/
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
CInstCon::GetEntry
|
|
-----------------------------------------------------------------------------*/
|
|
DWORD CInstCon::GetEntry(LPCSTR UrlName, LPCACHE_ENTRY_INFO EntryInfo,
|
|
LPDWORD EntryInfoSize, DWORD dwLookupFlags)
|
|
{
|
|
INT cbOld, cbNew, cbDiff;
|
|
DWORD cbOriginalInfoSize = *EntryInfoSize;
|
|
DWORD dwError = ERROR_SUCCESS, dwCDStatus;
|
|
|
|
DWORD cb;
|
|
LPSTR ptr;
|
|
|
|
|
|
// Try to get it from the CD.
|
|
dwCDStatus = GetEntryFromCD(UrlName, EntryInfo, EntryInfoSize);
|
|
|
|
switch(dwCDStatus)
|
|
{
|
|
// Couldn't find it on the CD.
|
|
case ERROR_FILE_NOT_FOUND:
|
|
case ERROR_PATH_NOT_FOUND:
|
|
|
|
// Not on CD. Look in memory mapped file.
|
|
dwError = URL_CONTAINER::RetrieveUrl(UrlName, (EntryInfo ? &EntryInfo : NULL),
|
|
EntryInfoSize, dwLookupFlags,
|
|
RETRIEVE_WITH_CHECKS);
|
|
break;
|
|
|
|
// CD not in drive.
|
|
case ERROR_INVALID_DRIVE:
|
|
case ERROR_NOT_READY:
|
|
case ERROR_WRONG_DISK:
|
|
|
|
dwError = ERROR_INTERNET_INSERT_CDROM;
|
|
break;
|
|
|
|
// Found it on the CD.
|
|
case ERROR_SUCCESS:
|
|
|
|
dwError = ERROR_SUCCESS;
|
|
break;
|
|
|
|
default:
|
|
|
|
// Some other error.
|
|
dwError = ERROR_INTERNET_INTERNAL_ERROR;
|
|
}
|
|
|
|
return dwError;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
CInstCon::MapUrlToAbsPath
|
|
-----------------------------------------------------------------------------*/
|
|
VOID CInstCon::MapUrlToAbsPath(LPSTR UrlName,
|
|
LPSTR szAbsPath, LPDWORD pcbAbsPath)
|
|
{
|
|
// Construct the absolute path to the file.
|
|
memcpy(szAbsPath, _szPrefixMap, _cbPrefixMap + 1);
|
|
|
|
LPSTR ptr = UrlName + _CachePrefixLen;
|
|
DWORD cbSuffix = strlen(ptr);
|
|
|
|
*pcbAbsPath = _cbPrefixMap + cbSuffix;
|
|
memcpy(szAbsPath + _cbPrefixMap, ptr, cbSuffix + 1);
|
|
|
|
// Convert all forward slashes to back slashes,
|
|
// including any that were inadvertently placed
|
|
// in the prefix map. This path might be returned
|
|
// to the caller.
|
|
ptr = szAbsPath;
|
|
while (*ptr++)
|
|
{
|
|
#ifndef unix
|
|
if (*ptr == '/')
|
|
*ptr = '\\';
|
|
#else
|
|
if (*ptr == '\\')
|
|
*ptr = '/';
|
|
#endif /* unix */
|
|
}
|
|
|
|
// Unescape - final length may be less than
|
|
// pcbAbsPath, but is always null terminated.
|
|
UrlUnescapeInPlace(szAbsPath, NULL);
|
|
}
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
CInstCon::GetEntryFromCD
|
|
-----------------------------------------------------------------------------*/
|
|
DWORD CInstCon::GetEntryFromCD(LPCSTR UrlName,
|
|
LPCACHE_ENTRY_INFO EntryInfo,
|
|
LPDWORD EntryInfoSize)
|
|
{
|
|
LPBYTE pb;
|
|
CHAR szAbsPath[MAX_PATH], *ptr;
|
|
|
|
DWORD cbUrl, cbSuffix, cbAbsPath, cbSizeRequired, cbExt, i,
|
|
dwError = ERROR_SUCCESS;
|
|
|
|
LONGLONG llZero = (LONGLONG) 0;
|
|
WIN32_FILE_ATTRIBUTE_DATA FileAttributes;
|
|
|
|
CHAR szVolumeLabel[MAX_PATH];
|
|
|
|
CHAR szVolRoot[4];
|
|
memcpy(szVolRoot, _szPrefixMap, 2);
|
|
memcpy(szVolRoot + 2, DIR_SEPARATOR_STRING, sizeof(DIR_SEPARATOR_STRING));
|
|
// First check that the correct CD is inserted.
|
|
if (GetVolumeInformation(szVolRoot, szVolumeLabel, MAX_PATH,
|
|
NULL, NULL, NULL, NULL, 0))
|
|
{
|
|
if (strcmp(_szVolumeLabel, szVolumeLabel))
|
|
{
|
|
dwError = ERROR_WRONG_DISK;
|
|
goto exit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwError = ERROR_INVALID_DRIVE;
|
|
goto exit;
|
|
}
|
|
|
|
// ---- Find the file and file info from the url -----
|
|
|
|
|
|
cbUrl = strlen(UrlName);
|
|
|
|
// Formulate path to file.
|
|
MapUrlToAbsPath((LPSTR) UrlName, szAbsPath, &cbAbsPath);
|
|
|
|
// Determine required CACHE_ENTRY_INFO buffer size.
|
|
cbSizeRequired = sizeof(CACHE_ENTRY_INFO)
|
|
+ cbUrl + 1 + cbAbsPath + 1 + MAX_EXTENSION_LEN + 1 + sizeof(HTTP_OK);
|
|
if (cbSizeRequired > *EntryInfoSize)
|
|
{
|
|
dwError = ERROR_INSUFFICIENT_BUFFER;
|
|
goto exit;
|
|
}
|
|
|
|
// Get the file information. Shouldn't be a directory.
|
|
dwError = GetFileSizeAndTimeByName(szAbsPath, &FileAttributes);
|
|
if (dwError != ERROR_SUCCESS)
|
|
{
|
|
if (FileAttributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
dwError = ERROR_FILE_NOT_FOUND;
|
|
}
|
|
goto exit;
|
|
}
|
|
|
|
|
|
// ---- Assemble the CACHE_ENTRY_INFO structure to return ----
|
|
|
|
|
|
// Urlname.
|
|
pb = (LPBYTE) EntryInfo + sizeof(CACHE_ENTRY_INFO);
|
|
memcpy(pb, UrlName, cbUrl + 1);
|
|
EntryInfo->lpszSourceUrlName = (LPSTR) pb;
|
|
|
|
// Filename.
|
|
pb += cbUrl + 1;
|
|
strcpy((LPSTR) pb, szAbsPath);
|
|
EntryInfo->lpszLocalFileName = (LPSTR) pb;
|
|
|
|
// Header.
|
|
pb += cbAbsPath + 1;
|
|
memcpy(pb, HTTP_OK, sizeof(HTTP_OK));
|
|
EntryInfo->lpHeaderInfo = (LPSTR)pb;
|
|
|
|
// File extension
|
|
cbExt = 0;
|
|
ptr = (LPSTR) UrlName + cbUrl;
|
|
for (i = 0; i < MAX_EXTENSION_LEN+1; i++)
|
|
{
|
|
if (*(--ptr) == '.')
|
|
{
|
|
cbExt = i+1;
|
|
break;
|
|
}
|
|
}
|
|
if (cbExt)
|
|
{
|
|
pb += sizeof(HTTP_OK);
|
|
memcpy(pb, ptr+1, cbExt + 1);
|
|
EntryInfo->lpszFileExtension = (LPSTR) pb;
|
|
}
|
|
else
|
|
EntryInfo->lpszFileExtension = NULL;
|
|
|
|
pb += cbExt +1;
|
|
|
|
INET_ASSERT((DWORD) ((LPCACHE_ENTRY_INFO) pb - EntryInfo) < cbSizeRequired);
|
|
|
|
// Version , type, count, hit rate, file size.
|
|
EntryInfo->dwStructSize = URL_CACHE_VERSION_NUM;
|
|
EntryInfo->CacheEntryType = INSTALLED_CACHE_ENTRY;
|
|
EntryInfo->dwUseCount = 0;
|
|
EntryInfo->dwHitRate = 0;
|
|
EntryInfo->dwSizeHigh = FileAttributes.nFileSizeHigh;
|
|
EntryInfo->dwSizeLow = FileAttributes.nFileSizeLow;
|
|
|
|
// Times: modified, expired, accessed, synced.
|
|
EntryInfo->LastModifiedTime = FileAttributes.ftCreationTime;
|
|
EntryInfo->ExpireTime = *(FILETIME*) &llZero;
|
|
|
|
// BUGBUG - getcurrent time for both.
|
|
EntryInfo->LastAccessTime = FileAttributes.ftLastAccessTime;
|
|
EntryInfo->LastSyncTime = *(FILETIME*) &llZero;
|
|
|
|
// Header size, file extension, exempt delta.
|
|
EntryInfo->dwHeaderInfoSize = sizeof(HTTP_OK);
|
|
EntryInfo->dwExemptDelta = 0;
|
|
|
|
// Buffer consumed.
|
|
*EntryInfoSize = cbSizeRequired - sizeof(CACHE_ENTRY_INFO);
|
|
|
|
|
|
exit:
|
|
return dwError;
|
|
}
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
CInstCon::AddEntryToIndex
|
|
-----------------------------------------------------------------------------*/
|
|
DWORD CInstCon::AddEntryToIndex(LPCACHE_ENTRY_INFO EntryInfo,
|
|
LPDWORD EntryInfoSize)
|
|
{
|
|
DWORD dwError;
|
|
AddUrlArg args;
|
|
CHAR szFileName[MAX_PATH];
|
|
|
|
// Create a local file name for the hard disk.
|
|
*szFileName = '\0';
|
|
dwError = URL_CONTAINER::CreateUniqueFile(EntryInfo->lpszSourceUrlName,
|
|
NULL, EntryInfo->lpszFileExtension, szFileName, NULL);
|
|
if (dwError != ERROR_SUCCESS)
|
|
goto exit;
|
|
|
|
// Copy the file from the CD.
|
|
// CreateUniqueFile has already created a file of 0 bytes.
|
|
if (!CopyFile(EntryInfo->lpszLocalFileName, szFileName, FALSE))
|
|
{
|
|
dwError = ERROR_INTERNET_INTERNAL_ERROR;
|
|
goto exit;
|
|
}
|
|
|
|
// Add the entry to the index.
|
|
|
|
// Url, filename, file size and extension.
|
|
memset(&args, 0, sizeof(args));
|
|
args.pszUrl = EntryInfo->lpszSourceUrlName;
|
|
args.pszFilePath = szFileName;
|
|
args.dwFileSize = EntryInfo->dwSizeLow;
|
|
args.pszFileExt = EntryInfo->lpszFileExtension;
|
|
args.dwEntryType = EntryInfo->CacheEntryType;
|
|
// Headers.
|
|
args.pbHeaders = EntryInfo->lpHeaderInfo;
|
|
args.cbHeaders = EntryInfo->dwHeaderInfoSize;
|
|
|
|
// Times: last modified and expired.
|
|
args.qwLastMod = FT2LL(EntryInfo->LastModifiedTime);
|
|
args.qwExpires = FT2LL(EntryInfo->ExpireTime);
|
|
|
|
// Redirect.
|
|
args.pszRedirect = NULL;
|
|
|
|
args.fImage = FALSE;
|
|
|
|
// Add the url to the index.
|
|
dwError = AddUrl(&args);
|
|
if (dwError != ERROR_SUCCESS)
|
|
goto exit;
|
|
|
|
// Retrieve the entry from the index. We do this because the EntryInfo
|
|
// structure returned from the CD references the CD filename.
|
|
// PERFPERF - we could optimize this by fixing up the EntryInfo
|
|
// structure to reference the CD filename.
|
|
dwError = URL_CONTAINER::RetrieveUrl(EntryInfo->lpszSourceUrlName,
|
|
(EntryInfo ? &EntryInfo : NULL), EntryInfoSize, NULL, RETRIEVE_WITH_CHECKS);
|
|
|
|
exit:
|
|
return dwError;
|
|
|
|
}
|