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.
 
 
 
 
 
 

869 lines
25 KiB

//
// Pei-Hwa Lin (peiwhal), Feb 3, 1997
//
// Notes:
// Compile switch : NO_FILE_WHEN_CREATE can turn on when wininet cache
// would create url cache entry if attached file is empty.
// LOG_CACHE_PATH will create log cache at the same level as
// content cache.
#include "private.h"
#undef TF_THISMODULE
#define TF_THISMODULE TF_TRACKCACHE
#define MY_CACHE_FILE_ENTRY_SIZE 2048
const TCHAR c_szExt[] = TEXT("log");
//used for creating tracking container (registry)
const TCHAR c_szLogContainer[] = TEXT("Log"); // if you modify this, modify iedev\inc\inetreg.h REGSTR_PATH_TRACKING too.
const TCHAR c_szLogPrefix[] = TEXT("Log:");
const char c_szLogContainerA[] = "Log";
// helper function
inline BOOL IsNumber(WCHAR x) { return (x >= L'0' && x <= L'9'); }
/*=============================================================================
FILEFROMPATH returns the filename of given filename which may include path.
=============================================================================*/
LPTSTR FileFromPath( LPCTSTR lpsz )
{
LPTSTR lpch;
/* Strip path/drive specification from name if there is one */
lpch = CharPrev( lpsz, lpsz + lstrlen(lpsz) );
// special case for "http://server/domain/channel.cdf/"
if (*lpch == '/') lpch = CharPrev( lpsz, lpch);
while (lpch > lpsz)
{
if (*lpch == '/') {
lpch = CharNext(lpch);
break;
}
lpch = CharPrev( lpsz, lpch);
}
return(lpch);
} /* end FileFromPath */
// CDF updates, create new group and deal with previous posting information
void
CUrlTrackingCache :: Init(LPCWSTR pwszURL)
{
DWORD dwRetry;
BSTR bstrEncoding = NULL;
_groupId = 0;
_pwszPostUrl = NULL;
_pszChannelUrlSite = NULL;
_pszPostUrlSite = NULL;
_pwszEncodingMethod = NULL;
_groupId = CreateUrlCacheGroup(CACHEGROUP_FLAG_GIDONLY, NULL);
WriteLONGLONG(_pCDFStartItem, c_szTrackingCookie, _groupId);
// #54653: remove previous tracking information, if any
if (SUCCEEDED(ReadBSTR(_pCDFStartItem, c_szPostHeader, &bstrEncoding)))
{
WriteEMPTY(_pCDFStartItem, c_szPostHeader);
SAFEFREEBSTR(bstrEncoding);
}
if (SUCCEEDED(ReadDWORD(_pCDFStartItem, c_szPostingRetry, &dwRetry)))
WriteEMPTY(_pCDFStartItem, c_szPostingRetry);
DoBaseURL(pwszURL);
return;
}
void
CUrlTrackingCache :: DoBaseURL(LPCWSTR pwszURL)
{
DWORD cbLen;
DWORD useSecurity = 1;
ASSERT(!_pszChannelUrlSite)
cbLen = (lstrlenW(pwszURL)+1) * sizeof(WCHAR);
_pszChannelUrlSite = (LPTSTR)MemAlloc( LPTR, cbLen);
#ifdef DEBUG
HKEY hkey;
// provide security switch for debugging
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
MY_WEBCHECK_POST_REG,
0,
KEY_READ,
&hkey))
{
DWORD cbsize = sizeof(useSecurity);
if (ERROR_SUCCESS == RegQueryValueEx(hkey,
TEXT("PostSecurity"),
NULL,
NULL,
(LPBYTE)&useSecurity,
&cbsize))
{
if ((useSecurity == 0) && (NULL != _pszChannelUrlSite))
StrCpyN(_pszChannelUrlSite, TEXT("http://"), cbLen / sizeof(WCHAR));
}
}
#endif
if ((useSecurity == 1) && (NULL != _pszChannelUrlSite))
{
MyOleStrToStrN(_pszChannelUrlSite, cbLen, pwszURL);
*(FileFromPath( _pszChannelUrlSite )) = 0;
}
return;
}
// only track URLs come from the same server of Channel CDF or LogTarget URL
//
BOOL
CUrlTrackingCache :: IsValidURL(LPCTSTR lpszURL)
{
BOOL bret;
if (!_pszChannelUrlSite || !_pszPostUrlSite)
return FALSE;
if (!StrCmpNI(lpszURL, _pszChannelUrlSite, lstrlen(_pszChannelUrlSite)))
bret = TRUE;
else if (!StrCmpNI(lpszURL, _pszPostUrlSite, lstrlen(_pszPostUrlSite)))
bret = TRUE;
else
bret = FALSE;
return bret;
}
#define LOG_CACHE_PATH
#ifdef LOG_CACHE_PATH
LPSTR PathPreviousBackslashA(LPSTR psz)
{
LPSTR lpch = CharPrevA(psz, psz + lstrlenA(psz));
for (; *lpch && *lpch != '\\'; lpch=CharPrevA(psz,lpch));
return lpch;
}
//------------------------------------------------------------------------------
// GetCacheLocation
//
// Purpose: Return the location of the logging cache
// ***** GetUrlCacheConfigInfoW is yet implemented in wininet
//------------------------------------------------------------------------------
//
HRESULT GetCacheLocation
(
LPTSTR pszCacheLocation,
DWORD dwSize // no. of chars in pszCacheLocation
)
{
HRESULT hr = S_OK;
DWORD dwLastErr;
LPINTERNET_CACHE_CONFIG_INFOA lpCCI = NULL;
DWORD dwCCISize = sizeof(INTERNET_CACHE_CONFIG_INFOA);
BOOL fOnceErrored = FALSE;
while (TRUE)
{
if ((lpCCI = (LPINTERNET_CACHE_CONFIG_INFOA)MemAlloc(LPTR,
dwCCISize)) == NULL)
{
hr = E_OUTOFMEMORY;
goto cleanup;
}
if (!GetUrlCacheConfigInfoA(lpCCI, &dwCCISize,
CACHE_CONFIG_CONTENT_PATHS_FC))
{
if ((dwLastErr = GetLastError()) != ERROR_INSUFFICIENT_BUFFER ||
fOnceErrored)
{
hr = HRESULT_FROM_WIN32(dwLastErr);
goto cleanup;
}
//
// We have insufficient buffer size; reallocate a buffer with the
// new dwCCISize set by GetUrlCacheConfigInfo
// Set fOnceErrored to TRUE so that we don't loop indefinitely
//
fOnceErrored = TRUE;
}
else
{
//
LPSTR pszPath = lpCCI->CachePaths[0].CachePath;
INT iLen;
PathRemoveBackslashA(pszPath);
*(PathPreviousBackslashA(pszPath)) = 0;
iLen = lstrlenA(pszPath) + sizeof(CHAR); // + 1 is for the null char
if ((((DWORD) iLen + ARRAYSIZE(c_szLogContainer) + 1) * sizeof(TCHAR)) < dwSize)
{
TCHAR szPathT[MAX_PATH];
SHAnsiToTChar(pszPath, szPathT, ARRAYSIZE(szPathT));
wnsprintf(pszCacheLocation, dwSize, TEXT("%s\\%s"), szPathT, c_szLogContainer);
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
break;
}
SAFELOCALFREE(lpCCI);
lpCCI = NULL;
}
cleanup:
if (lpCCI != NULL)
{
LocalFree(lpCCI);
}
return hr;
}
#endif
//-----------------------------------------------------------------------------
//
// ReadTrackingPrefix
//
// will create tracking container if current profile doesn't have one
// **** FindFirstUrlCacheContainerW is yet implemented in wininet
// **** FindNextUrlCacheContainerW is yet implemented either
//-----------------------------------------------------------------------------
LPTSTR
ReadTrackingPrefix(void)
{
LPTSTR lpPfx = NULL;
DWORD cbPfx = 0;
struct {
INTERNET_CACHE_CONTAINER_INFOA cInfo;
CHAR szBuffer[MAX_PATH+INTERNET_MAX_URL_LENGTH+1];
} ContainerInfo;
DWORD dwModified, dwContainer;
HANDLE hEnum;
dwContainer = sizeof(ContainerInfo);
hEnum = FindFirstUrlCacheContainerA(&dwModified,
&ContainerInfo.cInfo,
&dwContainer,
0);
if (hEnum)
{
for (;;)
{
if (!StrCmpIA(ContainerInfo.cInfo.lpszName, c_szLogContainerA))
{
ASSERT(ContainerInfo.cInfo.lpszCachePrefix[0]);
CHAR szPfx[MAX_PATH];
DWORD cch = ARRAYSIZE(ContainerInfo.cInfo.lpszCachePrefix)+sizeof(CHAR);
StrCpyNA(szPfx, ContainerInfo.cInfo.lpszCachePrefix, cch);
cch *= sizeof(TCHAR);
lpPfx = (LPTSTR)MemAlloc(LPTR, cch);
if (!lpPfx)
SetLastError(ERROR_OUTOFMEMORY);
SHAnsiToTChar(szPfx, lpPfx, cch);
break;
}
dwContainer = sizeof(ContainerInfo);
if (!FindNextUrlCacheContainerA(hEnum, &ContainerInfo.cInfo, &dwContainer))
{
// This code used to check GetLastError() for ERROR_NO_MORE_ITEMS before
// it would break. Well, that could put us in an infinite loop if the
// reason for failure were something else (like insufficient buffer) because
// wininet would not move forward in it's enumeration and we would not
// have done anything to address the error.
break;
}
}
FindCloseUrlCache(hEnum);
}
if (!lpPfx)
{
LPTSTR pszCachePath = NULL;
#ifdef LOG_CACHE_PATH
TCHAR szCachePath[MAX_PATH];
pszCachePath = (SUCCEEDED(GetCacheLocation(szCachePath, MAX_PATH))) ?
szCachePath : NULL;
#endif
if (CreateUrlCacheContainer(c_szLogContainer,
c_szLogPrefix,
pszCachePath, // wininet bug:if NULL, will create under ..\History\Log //
8192, // dwCacheLimit,
INTERNET_CACHE_CONTAINER_NOSUBDIRS, // dwContainerType,
0, // dwOptions,
NULL, // pvBuffer,
0 // cbBuffer
))
{
return ReadTrackingPrefix();
}
// unable to create Log container, stop.
}
return lpPfx;
}
//-----------------------------------------------------------------------------
//
// ConvertToPrefixedUrl
//
// caller must release lplpPrefixedUrl
//-----------------------------------------------------------------------------
BOOL
CUrlTrackingCache :: ConvertToPrefixedUrl
(
IN LPCTSTR lpUrl,
IN LPTSTR* lplpPrefixedUrl
)
{
BOOL bret = FALSE;
ASSERT(lpUrl);
if (!_lpPfx)
_lpPfx = ReadTrackingPrefix();
if (_lpPfx)
{
int len = lstrlen(lpUrl) + lstrlen(_lpPfx) + 1;
*lplpPrefixedUrl = NULL;
*lplpPrefixedUrl = (LPTSTR)MemAlloc(LPTR, len * sizeof(TCHAR));
if (*lplpPrefixedUrl)
{
wnsprintf(*lplpPrefixedUrl, len, TEXT("%s%s"), _lpPfx, lpUrl);
bret = TRUE;
}
else
bret = FALSE;
}
return bret;
}
//-----------------------------------------------------------------------------
//
// RetrieveUrlCacheEntry
//
// caller must release lpCE
//-----------------------------------------------------------------------------
LPINTERNET_CACHE_ENTRY_INFO
CUrlTrackingCache :: RetrieveUrlCacheEntry
(
IN LPCTSTR lpUrl
)
{
LPINTERNET_CACHE_ENTRY_INFO lpCE = NULL;
DWORD cbSize;
BOOL bret = FALSE;
lpCE = (LPINTERNET_CACHE_ENTRY_INFO)MemAlloc(LPTR, MY_MAX_CACHE_ENTRY_INFO);
if (lpCE)
{
cbSize = MY_MAX_CACHE_ENTRY_INFO;
while ((bret = GetUrlCacheEntryInfo(lpUrl, lpCE, &cbSize)) != TRUE)
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
SAFELOCALFREE(lpCE);
lpCE = (LPINTERNET_CACHE_ENTRY_INFO)MemAlloc(LPTR, cbSize);
if (!lpCE)
break;
}
else
break;
}
}
if (!bret && lpCE)
{
SAFELOCALFREE(lpCE);
SetLastError(ERROR_FILE_NOT_FOUND);
}
return lpCE;
}
#define FILETIME_SEC 100000000
#define SECS_PER_DAY (60 * 60 * 24)
DWORD WCTOI(LPCWSTR pwstr)
{
DWORD dw;
int len = lstrlenW(pwstr);
dw = 0;
for (int i = 0; i<len; i++)
{
if (!IsNumber(pwstr[i]))
break;
dw = dw * 10 + (pwstr[i] - L'0');
}
if (dw == 0) dw = 24;
return dw;
}
//-----------------------------------------------------------------------------
//
// CreatePrefixedCacheEntry
//
// Create cache entry in Tracking cache bucket
//-----------------------------------------------------------------------------
HRESULT CreateLogCacheEntry
(
LPCTSTR lpPfxUrl,
FILETIME ftExpire,
FILETIME ftModified,
DWORD CacheEntryType
)
{
TCHAR lpFile[MAX_PATH];
HRESULT hr = E_FAIL;
DWORD cbSize;
if (CreateUrlCacheEntry(lpPfxUrl, MY_CACHE_FILE_ENTRY_SIZE, c_szExt, lpFile, 0))
{
HANDLE hFile = CreateFile(lpFile,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
return hr;
// note: wininet will not create the entry if file size equals to zero
// WriteFile(hFile, c_szLogFields, g_ccLogFields, &cbSize, NULL);
WriteFile(hFile, c_szEmptyLog, c_ccEmptyLog, &cbSize, NULL);
CloseHandle(hFile);
return (CommitUrlCacheEntry(lpPfxUrl,
lpFile,
ftExpire,
ftModified,
CacheEntryType,
NULL,
0,
NULL,
0)) ? S_OK : E_FAIL;
}
return hr;
}
HRESULT
CUrlTrackingCache :: CreatePrefixedCacheEntry
(
IN LPCTSTR lpPfxUrl
)
{
HRESULT hr = E_FAIL;
LPINTERNET_CACHE_ENTRY_INFO lpCE = NULL;
FILETIME ftModified;
// IE50: due to change to wininet cache group enumeration, now we save our filter
// information _groupId along with each cache entry itself. the wininet url cache
// no longer maintain this for us
ftModified.dwHighDateTime = (DWORD)(_groupId >> 32);
ftModified.dwLowDateTime = (DWORD)(0x00000000ffffffff & _groupId);
lpCE = RetrieveUrlCacheEntry(lpPfxUrl);
if (lpCE )
{
// exist in Tracking bucket, set tracking flag
// IE50: save _groupId info in LastModifiedTime
lpCE->CacheEntryType |= _ConnectionScope;
lpCE->LastModifiedTime.dwHighDateTime = ftModified.dwHighDateTime;
lpCE->LastModifiedTime.dwLowDateTime = ftModified.dwLowDateTime;
ASSERT(SetUrlCacheEntryInfo(lpCE->lpszSourceUrlName, lpCE,
CACHE_ENTRY_ATTRIBUTE_FC | CACHE_ENTRY_MODTIME_FC) == TRUE);
hr = S_OK;
}
else
//FILE_NOT_FOUND, create it.
{
LONGLONG llExpireHorizon;
SYSTEMTIME st;
FILETIME ftMod, ftExpire;
llExpireHorizon = (LONGLONG)(SECS_PER_DAY * _dwPurgeTime / 24);
GetLocalTime(&st);
SystemTimeToFileTime(&st, &ftMod);
llExpireHorizon *= FILETIME_SEC;
ftExpire.dwLowDateTime = ftMod.dwLowDateTime + (DWORD)(llExpireHorizon % 0xFFFFFFFF);
ftExpire.dwHighDateTime = ftMod.dwHighDateTime + (DWORD)(llExpireHorizon / 0xFFFFFFFF);
hr = CreateLogCacheEntry(lpPfxUrl, ftExpire, ftModified, _ConnectionScope);
}
SAFELOCALFREE(lpCE);
return hr;
}
HRESULT
CUrlTrackingCache :: AddToTrackingCacheEntry
(
IN LPCWSTR pwszUrl
)
{
HRESULT hr = E_OUTOFMEMORY;
TCHAR szCanonicalUrl[MAX_URL];
DWORD dwSize = MAX_URL;
LPTSTR lpUrl = NULL;
LPTSTR lpPfxUrl = NULL;
DWORD cbSize;
PROPVARIANT vProp = {0};
if (pwszUrl == NULL)
return E_INVALIDARG;
cbSize = lstrlenW(pwszUrl) + 1;
lpUrl = (LPTSTR)MemAlloc(LPTR, cbSize * sizeof(TCHAR));
if (!lpUrl)
return hr;
SHUnicodeToTChar(pwszUrl, lpUrl, cbSize);
if (!IsValidURL(lpUrl))
{
MemFree(lpUrl);
return E_INVALIDARG;
}
// canonicalize URL
InternetCanonicalizeUrl(lpUrl, szCanonicalUrl, &dwSize, ICU_DECODE);
SAFELOCALFREE(lpUrl);
ConvertToPrefixedUrl(szCanonicalUrl, &lpPfxUrl);
if (!lpPfxUrl)
{
return hr;
}
hr = CreatePrefixedCacheEntry(lpPfxUrl);
if (SUCCEEDED(hr))
{
// exist in Tracking bucket, set tracking flag.
vProp.vt = VT_UI4;
vProp.ulVal = _ConnectionScope;
hr = IntSiteHelper(szCanonicalUrl, &c_rgPropRead[PROP_TRACKING], &vProp, 1, TRUE);
PropVariantClear( &vProp );
}
SAFELOCALFREE(lpPfxUrl);
return hr;
}
//-----------------------------------------------------------------------------
//
// Process log related tags
//
//-----------------------------------------------------------------------------
//
// <LOGTARGET href="http://foo.htm" SCOPE="ALL"/>
// <HTTP-EQUIV name="Encoding-type" value="gzip" />
// <PurgeTime HOUR="12" />
// </Logtarget>
//
HRESULT
CUrlTrackingCache :: ProcessTrackingInLog
(
IXMLElement *pTracking
)
{
HRESULT hr;
LPWSTR pwszScope = NULL;
if (_pwszPostUrl)
return S_OK; // there are more than 1 logtarget, take whatever first was read
hr = ReadAttribute(pTracking, L"HREF", &_pwszPostUrl); // must exist to enalbe logging
if (FAILED(hr))
return hr;
// fill it in item for post agent
WriteOLESTR(_pCDFStartItem, c_szTrackingPostURL, _pwszPostUrl);
// #41460: add 2nd domain allowing tracking to
DWORD cbLen = (lstrlenW(_pwszPostUrl)+1) * sizeof(WCHAR);
_pszPostUrlSite = (LPTSTR)MemAlloc( LPTR, cbLen);
MyOleStrToStrN(_pszPostUrlSite, cbLen, _pwszPostUrl);
*(FileFromPath( _pszPostUrlSite )) = 0;
_ConnectionScope = TRACK_ONLINE_CACHE_ENTRY | TRACK_OFFLINE_CACHE_ENTRY;
hr = ReadAttribute(pTracking, L"SCOPE", &pwszScope);
if (SUCCEEDED(hr))
{
if (!StrCmpIW(pwszScope, L"OFFLINE"))
_ConnectionScope = TRACK_OFFLINE_CACHE_ENTRY;
else if (!StrCmpIW(pwszScope, L"ONLINE"))
_ConnectionScope = TRACK_ONLINE_CACHE_ENTRY;
SAFELOCALFREE(pwszScope);
}
RunChildElement(pTracking);
// #42687: save purgetime to item and used later by post agent
if (_pwszPurgeTime) // if not specify, default is 24 hours
{
_dwPurgeTime = WCTOI(_pwszPurgeTime);
}
DATE dt = 0.0;
SYSTEMTIME st;
GetLocalTime(&st);
SystemTimeToVariantTime(&st, &dt);
dt += ((DATE)_dwPurgeTime/24);
#ifdef DEBUG
VariantTimeToSystemTime(dt, &st);
#endif
WriteDATE(_pCDFStartItem, c_szPostPurgeTime, &dt);
return S_OK;
}
//-----------------------------------------------------------------------------
//
// ProcessTrackingItems
// <Item href="http://foo">
// <Log value="document:view"/>
// </Item>
// or <Item>
// <A href="http://foo" />
// </Item>
// This routine will setup tracking cache entries for all URLs which are
// specified in CDF file to track. All URLs entries belong to same channel
// are created in same cache group
//-----------------------------------------------------------------------------
HRESULT
CUrlTrackingCache :: ProcessTrackingInItem
(
IXMLElement *pItem, //point to <Item> tag
LPCWSTR pwszUrl, //absolute URL for item
BOOL fForceLog //global log flag
)
{
HRESULT hr = S_OK;
_bTrackIt = fForceLog;
if (!_bTrackIt)
hr = RunChildElement(pItem);
if (SUCCEEDED(hr) && _bTrackIt)
hr = AddToTrackingCacheEntry(pwszUrl);
return (_bTrackIt) ? S_OK : E_FAIL; // #42604: global logging, report if this item needs logged
}
HRESULT
CUrlTrackingCache :: RunChildElement
(
IXMLElement* pElement
)
{
IXMLElementCollection *pCollection;
long lIndex = 0;
long lMax;
VARIANT vIndex, vEmpty;
IDispatch *pDisp;
IXMLElement *pItem;
BSTR bstrTagName;
HRESULT hr = E_FAIL;
if (SUCCEEDED(pElement->get_children(&pCollection)) && pCollection)
{
if (SUCCEEDED(pCollection->get_length(&lMax)))
{
vEmpty.vt = VT_EMPTY;
for (; lIndex < lMax; lIndex++)
{
vIndex.vt = VT_UI4;
vIndex.lVal = lIndex;
if (SUCCEEDED(pCollection->item(vIndex, vEmpty, &pDisp)))
{
if (SUCCEEDED(pDisp->QueryInterface(IID_IXMLElement, (void **)&pItem)))
{
if (SUCCEEDED(pItem->get_tagName(&bstrTagName)) && bstrTagName)
{
hr = ProcessItemInEnum(bstrTagName, pItem);
SysFreeString(bstrTagName);
}
pItem->Release();
}
pDisp->Release();
}
}
}
pCollection->Release();
}
return hr;
}
HRESULT
CUrlTrackingCache :: ProcessItemInEnum
(
LPCWSTR pwszTagName,
IXMLElement *pItem
)
{
HRESULT hr;
LPWSTR pwszName = NULL;
if (!StrCmpIW(pwszTagName, L"HTTP-EQUIV"))
{
DBG("CUrlTrackingCache processing HTTP-EQUIV");
hr = ReadAttribute(pItem, L"NAME", &pwszName);
if (SUCCEEDED(hr) && !StrCmpIW(pwszName, L"ENCODING-TYPE"))
{
hr = ReadAttribute(pItem, L"VALUE", &_pwszEncodingMethod);
if (SUCCEEDED(hr) && *_pwszEncodingMethod)
WriteOLESTR(_pCDFStartItem, c_szPostHeader, _pwszEncodingMethod);
}
SAFELOCALFREE(pwszName);
}
else if (!StrCmpIW(pwszTagName, L"PURGETIME"))
{
DBG("CUrlTrackingCache processing PurgeTime");
return ReadAttribute(pItem, L"HOUR", &_pwszPurgeTime);
}
else if (!StrCmpIW(pwszTagName, L"LOG"))
{
DBG("CUrlTrackingCache processing Log");
hr = ReadAttribute(pItem, L"VALUE", &pwszName);
if (SUCCEEDED(hr))
_bTrackIt = (!StrCmpIW(pwszName, L"document:view")) ? TRUE : FALSE;
SAFELOCALFREE(pwszName);
}
return S_OK;
}
HRESULT
CUrlTrackingCache :: ReadAttribute
(
IN IXMLElement* pItem,
IN LPCWSTR pwszAttributeName,
OUT LPWSTR* pwszAttributeValue
)
{
VARIANT vProp;
BSTR bstrName = NULL;
HRESULT hr = E_FAIL;
DWORD dwLen;
vProp.vt = VT_EMPTY;
bstrName = SysAllocString(pwszAttributeName);
if (bstrName && SUCCEEDED(pItem->getAttribute(bstrName, &vProp)))
{
if (vProp.vt == VT_BSTR)
{
dwLen = sizeof(WCHAR) * (lstrlenW(vProp.bstrVal) + 1);
*pwszAttributeValue = (LPWSTR)MemAlloc(LPTR, dwLen);
if (*pwszAttributeValue)
{
StrCpyNW(*pwszAttributeValue, vProp.bstrVal, dwLen / sizeof(WCHAR));
hr = S_OK;
}
VariantClear(&vProp);
}
}
SysFreeString(bstrName);
return hr;
}
//--------------------------------------------------------------------------
//
// CUrlTrackingCache
//
//--------------------------------------------------------------------------
CUrlTrackingCache::CUrlTrackingCache
(
ISubscriptionItem *pCDFItem,
LPCWSTR pwszURL
)
{
_lpPfx = NULL;
_dwPurgeTime = 24;
_pCDFStartItem = pCDFItem;
ASSERT(_pCDFStartItem);
_pCDFStartItem->AddRef();
Init(pwszURL);
}
CUrlTrackingCache::~CUrlTrackingCache()
{
SAFEFREEOLESTR(_pwszPostUrl);
SAFEFREEOLESTR(_pwszEncodingMethod);
SAFEFREEOLESTR(_pwszPurgeTime);
SAFELOCALFREE(_pszChannelUrlSite);
SAFELOCALFREE(_pszPostUrlSite);
SAFELOCALFREE(_lpPfx);
SAFERELEASE(_pCDFStartItem);
}