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.
1140 lines
30 KiB
1140 lines
30 KiB
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// cdfidl.cpp
|
|
//
|
|
// Cdf id list helper functions.
|
|
//
|
|
// History:
|
|
//
|
|
// 3/19/97 edwardp Created.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Includes
|
|
//
|
|
|
|
#include "stdinc.h"
|
|
#include "cdfidl.h"
|
|
#include "xmlutil.h"
|
|
#include "winineti.h" // for MAX_CACHE_ENTRY_INFO_SIZE
|
|
|
|
//
|
|
// Helper functions
|
|
//
|
|
|
|
|
|
LPTSTR CDFIDL_GetUserName()
|
|
{
|
|
static BOOL gunCalled = FALSE;
|
|
static TCHAR szUserName[INTERNET_MAX_USER_NAME_LENGTH] = TEXT("");
|
|
|
|
if (!gunCalled)
|
|
{
|
|
char szUserNameA[INTERNET_MAX_USER_NAME_LENGTH];
|
|
szUserNameA[0] = 0;
|
|
DWORD size = INTERNET_MAX_USER_NAME_LENGTH;
|
|
GetUserNameA(szUserNameA, &size);
|
|
SHAnsiToTChar(szUserNameA, szUserName, ARRAYSIZE(szUserName));
|
|
gunCalled = TRUE;
|
|
}
|
|
return szUserName;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CDFIDL_Create ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Creates a cdf id list.
|
|
//
|
|
// Parameters:
|
|
// [In] pCdfItem - A pointer to cdf item data.
|
|
//
|
|
// Return:
|
|
// A new cdf id list on success.
|
|
// NULL otherwise.
|
|
//
|
|
// Comments:
|
|
// This function builds a variable length cdf item id list. The item id
|
|
// consists of a fixed length initial section followed by two or more null
|
|
// terminated strings. It has the following form:
|
|
//
|
|
// USHORT cb - Size in bytes of this cdf item id.
|
|
// WORD wVersion; - Version number of this item id structure.
|
|
// DWORD dwId; - Used to identify cdf item ids. Set to
|
|
// 0x0ed1964ed
|
|
// CDFITEMTYPE cdfItemType - CDF_Folder, CDF_FolderLink or CDF_Link.
|
|
// LONG nIndex - The object model index for this item.
|
|
// TCHAR szName[1]; - Two or more null terminated strings
|
|
// beggining with the name of this item.
|
|
// USHORT next.cb - The size of the next item in the list.
|
|
// Set to zero to terminate the list.
|
|
//
|
|
// It is the callers responsability to free the item id list. This should
|
|
// be done using the IMalloc returned from SHGetMalloc();
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
PCDFITEMIDLIST
|
|
CDFIDL_Create(
|
|
PCDFITEM pCdfItem
|
|
)
|
|
{
|
|
#ifdef ALIGNMENT_MACHINE
|
|
TCHAR *pszTempName;
|
|
#endif
|
|
ASSERT(pCdfItem);
|
|
ASSERT(pCdfItem->bstrName);
|
|
ASSERT(pCdfItem->bstrURL);
|
|
|
|
PCDFITEMIDLIST pcdfidl = NULL;
|
|
|
|
//
|
|
// Get the number of chars of the name of the item including the terminating
|
|
// null character.
|
|
//
|
|
|
|
USHORT cchName = StrLenW(pCdfItem->bstrName) + 1;
|
|
|
|
//
|
|
// Get the number of chars of the URL of the item including the terminating
|
|
// null character.
|
|
//
|
|
|
|
USHORT cchURL = StrLenW(pCdfItem->bstrURL) + 1;
|
|
|
|
//
|
|
// Calculate the total size of the cdf item id in bytes. When calculating the size
|
|
// of a cdf item id one TCHAR should be subtracted to account for the TCHAR
|
|
// szName[1] included in the CDFITEMID struct definition.
|
|
//
|
|
|
|
USHORT cbItemId = sizeof(CDFITEMID) + (cchName + cchURL) * sizeof(TCHAR) - sizeof(TCHAR);
|
|
|
|
#ifdef ALIGNMENT_MACHINE
|
|
cbItemId = ALIGN4(cbItemId);
|
|
#endif
|
|
|
|
//
|
|
// Item ids must allocated by the shell's IMalloc interface.
|
|
//
|
|
|
|
IMalloc* pIMalloc;
|
|
|
|
HRESULT hr = SHGetMalloc(&pIMalloc);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ASSERT(pIMalloc);
|
|
|
|
//
|
|
// An item id *list* must be NULL terminated so an additional USHORT is
|
|
// allocated to hold the terminating NULL.
|
|
//
|
|
pcdfidl = (PCDFITEMIDLIST)pIMalloc->Alloc(cbItemId + sizeof(USHORT));
|
|
|
|
if (pcdfidl)
|
|
{
|
|
//
|
|
// NULL terminate the list.
|
|
//
|
|
|
|
*((UNALIGNED USHORT*) ( ((LPBYTE)pcdfidl) + cbItemId )) = 0;
|
|
|
|
#ifdef ALIGNMENT_MACHINE
|
|
USHORT cbActaulItemId = sizeof(CDFITEMID) + (cchName + cchURL) * sizeof(TCHAR) - sizeof(TCHAR);
|
|
if(cbActaulItemId < cbItemId)
|
|
ZeroMemory((LPBYTE)pcdfidl + cbActaulItemId, cbItemId - cbActaulItemId);
|
|
#endif
|
|
|
|
|
|
//
|
|
// Fill in the data shared by all cdf item ids.
|
|
//
|
|
|
|
pcdfidl->mkid.cb = cbItemId;
|
|
pcdfidl->mkid.wVersion = CDFITEMID_VERSION;
|
|
pcdfidl->mkid.dwId = CDFITEMID_ID;
|
|
|
|
//
|
|
// Set the data that is specific to this cdf item id.
|
|
//
|
|
|
|
pcdfidl->mkid.cdfItemType = pCdfItem->cdfItemType;
|
|
pcdfidl->mkid.nIndex = pCdfItem->nIndex;
|
|
|
|
//
|
|
// REVIEW: Need WSTR to TSTR conversion.
|
|
//
|
|
|
|
#ifndef ALIGNMENT_MACHINE
|
|
SHUnicodeToTChar(pCdfItem->bstrName, pcdfidl->mkid.szName, cchName);
|
|
SHUnicodeToTChar(pCdfItem->bstrURL, pcdfidl->mkid.szName + cchName,
|
|
cchURL);
|
|
#else
|
|
pszTempName = (LPTSTR)ALIGN4((ULONG_PTR)(pcdfidl->mkid.szName));
|
|
SHUnicodeToTChar(pCdfItem->bstrName, pszTempName, cchName);
|
|
pszTempName = (LPTSTR)((ULONG_PTR)(pcdfidl->mkid.szName+cchName));
|
|
SHUnicodeToTChar(pCdfItem->bstrURL, pszTempName,
|
|
cchURL);
|
|
#endif
|
|
|
|
}
|
|
else
|
|
{
|
|
pcdfidl = NULL;
|
|
}
|
|
|
|
pIMalloc->Release();
|
|
}
|
|
|
|
ASSERT(CDFIDL_IsValid(pcdfidl) || NULL == pcdfidl);
|
|
|
|
return pcdfidl;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CDFIDL_CreateFromXMLElement ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Creates a cdf item id list from a xml element.
|
|
//
|
|
// Parameters:
|
|
// [In] pIXMLElement - A pointer to the xml element.
|
|
// [In] nIndex - The index value used to set the cdfidl index field.
|
|
//
|
|
// Return:
|
|
// A poniter to a new cdf item id list if successful.
|
|
// NULL otherwise.
|
|
//
|
|
// Comments:
|
|
// The caller is responsible for freeing the returned id list.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
PCDFITEMIDLIST
|
|
CDFIDL_CreateFromXMLElement(
|
|
IXMLElement* pIXMLElement,
|
|
ULONG nIndex
|
|
)
|
|
{
|
|
ASSERT(pIXMLElement);
|
|
|
|
PCDFITEMIDLIST pcdfidl = NULL;
|
|
|
|
CDFITEM cdfItem;
|
|
|
|
if (cdfItem.bstrName = XML_GetAttribute(pIXMLElement, XML_TITLE))
|
|
{
|
|
if (cdfItem.bstrURL = XML_GetAttribute(pIXMLElement, XML_HREF))
|
|
{
|
|
cdfItem.nIndex = nIndex;
|
|
|
|
if (INDEX_CHANNEL_LINK == nIndex)
|
|
{
|
|
cdfItem.cdfItemType = CDF_FolderLink;
|
|
}
|
|
else
|
|
{
|
|
cdfItem.cdfItemType = XML_IsFolder(pIXMLElement) ? CDF_Folder :
|
|
CDF_Link;
|
|
}
|
|
|
|
pcdfidl = CDFIDL_Create(&cdfItem);
|
|
|
|
SysFreeString(cdfItem.bstrURL);
|
|
}
|
|
|
|
SysFreeString(cdfItem.bstrName);
|
|
}
|
|
|
|
ASSERT(CDFIDL_IsValid(pcdfidl) || NULL == pcdfidl);
|
|
|
|
return pcdfidl;
|
|
}
|
|
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CDFIDL_CreateFolderPidl ***
|
|
//
|
|
//
|
|
// Description: creates a special folder pidl
|
|
//
|
|
//
|
|
// Parameters:
|
|
// [In] pcdfidl - Pointer to the cdf id list to be created from
|
|
//
|
|
// Comments:
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
PCDFITEMIDLIST
|
|
CDFIDL_CreateFolderPidl(
|
|
PCDFITEMIDLIST pcdfidl
|
|
)
|
|
{
|
|
ASSERT(CDFIDL_IsValid(pcdfidl));
|
|
|
|
PCDFITEMIDLIST pcdfidlRet = (PCDFITEMIDLIST)ILClone((LPITEMIDLIST)pcdfidl);
|
|
|
|
if (pcdfidlRet)
|
|
{
|
|
((PCDFITEMID)pcdfidlRet)->nIndex = INDEX_CHANNEL_LINK;
|
|
((PCDFITEMID)pcdfidlRet)->cdfItemType = CDF_FolderLink; //CDF_Link instead?
|
|
}
|
|
ASSERT(CDFIDL_IsValid(pcdfidlRet));
|
|
|
|
return pcdfidlRet;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CDFIDL_Free ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Free the given cdf item id list.
|
|
//
|
|
// Parameters:
|
|
// [In] pcdfidl - Pointer to the cdf id list to be freed.
|
|
//
|
|
// Return:
|
|
// No return value.
|
|
//
|
|
// Comments:
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
void
|
|
CDFIDL_Free(
|
|
PCDFITEMIDLIST pcdfidl
|
|
)
|
|
{
|
|
ASSERT(CDFIDL_IsValid(pcdfidl));
|
|
|
|
IMalloc *pIMalloc;
|
|
|
|
if (SUCCEEDED(SHGetMalloc(&pIMalloc)))
|
|
{
|
|
ASSERT(pIMalloc);
|
|
ASSERT(pIMalloc->DidAlloc(pcdfidl));
|
|
|
|
pIMalloc->Free(pcdfidl);
|
|
|
|
pIMalloc->Release();
|
|
}
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CDFIDL_GetDisplayName ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Gets the name stored in the given cdf item id list.
|
|
//
|
|
// Parameters:
|
|
// [In] pcdfidl - A pointer to a cdf item id list.
|
|
// [Out] pName - A pointer to a STRRET structure. STRRET has the following
|
|
// structure:
|
|
// UINT uType - STRRET_CSTR, _OFFSET or _WSTR
|
|
// union {
|
|
// LPWSTR pOleStr;
|
|
// UINT uOffset;
|
|
// char cStr[MAX_PATH];
|
|
// }
|
|
//
|
|
// Return:
|
|
// S_OK on success. E_Fail otherwise.
|
|
//
|
|
// Comments:
|
|
// This function returns the name as an offset of the string from the start
|
|
// of the cdf item id list.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CDFIDL_GetDisplayName(
|
|
PCDFITEMIDLIST pcdfidl,
|
|
LPSTRRET pName
|
|
)
|
|
{
|
|
ASSERT(CDFIDL_IsValid(pcdfidl));
|
|
ASSERT(pName);
|
|
|
|
pName->uType = STRRET_CSTR;
|
|
LPTSTR pszName = CDFIDL_GetName(pcdfidl);
|
|
|
|
SHTCharToAnsi(pszName, pName->cStr, ARRAYSIZE(pName->cStr));
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CDFIDL_GetName ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Gets a pointer to the URL stored in the given cdf item id list.
|
|
//
|
|
// Parameters:
|
|
// [In] pcdfidl - A pointer to a cdf item id list.
|
|
//
|
|
// Return:
|
|
// A LPTSTR to the Name stored in the pidl.
|
|
//
|
|
// Comments:
|
|
// This function returns a pointer to the Name in the cdf item id list.
|
|
// The pointer is valid for the life of the item id list. The caller is
|
|
// resposible for maintaining the item id list and for not using the
|
|
// the returned pointer after the id list is freed.
|
|
//
|
|
// The name returned is the name of the last item in the list.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
LPTSTR
|
|
CDFIDL_GetName(
|
|
PCDFITEMIDLIST pcdfidl
|
|
)
|
|
{
|
|
ASSERT(CDFIDL_IsValid(pcdfidl));
|
|
|
|
pcdfidl = (PCDFITEMIDLIST)ILFindLastID((LPITEMIDLIST)pcdfidl);
|
|
|
|
return CDFIDL_GetNameId(&pcdfidl->mkid);
|
|
}
|
|
|
|
LPTSTR
|
|
CDFIDL_GetNameId(
|
|
PCDFITEMID pcdfid
|
|
)
|
|
{
|
|
ASSERT(pcdfid);
|
|
|
|
#if defined(ALIGNMENT_MACHINE)
|
|
return (LPTSTR)(ALIGN4((ULONG_PTR)pcdfid->szName));
|
|
#else
|
|
return pcdfid->szName;
|
|
#endif
|
|
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CDFIDL_GetURL ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Gets a pointer to the URL stored in the given cdf item id list.
|
|
//
|
|
// Parameters:
|
|
// [In] pcdfidl - A pointer to a cdf item id list.
|
|
//
|
|
// Return:
|
|
// A LPTSTR to the URL value for the given pcdfidl.
|
|
//
|
|
// Comments:
|
|
// This function returns a pointer to the URL in the cdf item id list. The
|
|
// pointer is valid for the life of the item id list. The caller is
|
|
// resposible for maintaining the item id list and for not using the
|
|
// the returned pointer after the id list is freed.
|
|
//
|
|
// The URL returned is the URL of the last item in the list.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
LPTSTR
|
|
CDFIDL_GetURL(
|
|
PCDFITEMIDLIST pcdfidl
|
|
)
|
|
{
|
|
ASSERT(CDFIDL_IsValid(pcdfidl));
|
|
|
|
//
|
|
// Get the first string after the name.
|
|
//
|
|
|
|
LPTSTR szURL = CDFIDL_GetName(pcdfidl);
|
|
|
|
while (*szURL++);
|
|
|
|
return szURL;
|
|
}
|
|
|
|
LPTSTR
|
|
CDFIDL_GetURLId(
|
|
PCDFITEMID pcdfid
|
|
)
|
|
{
|
|
ASSERT(pcdfid);
|
|
|
|
//
|
|
// Get the first string after the name.
|
|
//
|
|
|
|
LPTSTR szURL = CDFIDL_GetNameId(pcdfid);
|
|
|
|
while (*szURL++);
|
|
|
|
return szURL;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CDFIDL_GetIndex ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Returns the index item of the given cdf id list.
|
|
//
|
|
// Parameters:
|
|
// [In] pcdfidl - Pointer to the cdf item id list.
|
|
//
|
|
// Return:
|
|
// Returns the index item of the given id list.
|
|
//
|
|
// Comments:
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
ULONG
|
|
CDFIDL_GetIndex(
|
|
PCDFITEMIDLIST pcdfidl
|
|
)
|
|
{
|
|
pcdfidl = (PCDFITEMIDLIST)ILFindLastID((LPITEMIDLIST)pcdfidl);
|
|
|
|
return CDFIDL_GetIndexId(&pcdfidl->mkid);
|
|
}
|
|
|
|
ULONG
|
|
CDFIDL_GetIndexId(
|
|
PCDFITEMID pcdfid
|
|
)
|
|
{
|
|
return pcdfid->nIndex;
|
|
}
|
|
|
|
#define ASTR_HISTORY_PREFIX TEXT("Visited: ")
|
|
|
|
//
|
|
// Looks the URL up in the cache to see if the user has ever read this url
|
|
//
|
|
// REVIEW
|
|
// REVIEW - Should probably use IUrlStorage instead of constructing the
|
|
// REVIEW
|
|
// history cache URL on the fly
|
|
//
|
|
BOOL
|
|
CDFIDL_IsUnreadURL(
|
|
LPTSTR szUrl
|
|
)
|
|
{
|
|
DWORD dwLen;
|
|
|
|
//
|
|
// Canonicalize the input url.
|
|
//
|
|
TCHAR szCanonicalizedUrl[INTERNET_MAX_URL_LENGTH];
|
|
dwLen = INTERNET_MAX_URL_LENGTH;
|
|
if (!InternetCanonicalizeUrl(szUrl, szCanonicalizedUrl, &dwLen, 0))
|
|
StrCpyN(szCanonicalizedUrl, szUrl, ARRAYSIZE(szCanonicalizedUrl));
|
|
|
|
//
|
|
// Build a string that is the URL prefixed with VISITED: and the UserName
|
|
//
|
|
TCHAR szVisited[
|
|
INTERNET_MAX_USER_NAME_LENGTH+
|
|
1+
|
|
INTERNET_MAX_URL_LENGTH+
|
|
ARRAYSIZE(ASTR_HISTORY_PREFIX)];
|
|
|
|
StrCpyN(szVisited, ASTR_HISTORY_PREFIX, ARRAYSIZE(szVisited));
|
|
StrCatBuff(szVisited, CDFIDL_GetUserName(), ARRAYSIZE(szVisited));
|
|
int len = StrLen(szVisited);
|
|
StrCpyN(szVisited + len, TEXT("@"), ARRAYSIZE(szVisited) - len);
|
|
len++;
|
|
StrCpyN(szVisited + len, szCanonicalizedUrl, ARRAYSIZE(szVisited) - len);
|
|
len++;
|
|
|
|
// Check for trailing slash and eliminate, copied from shdocvw\urlhist.cpp
|
|
LPTSTR pszT = CharPrev(szVisited, szVisited + lstrlen(szVisited));
|
|
if (*pszT == TEXT('/'))
|
|
{
|
|
ASSERT(lstrlen(pszT) == 1);
|
|
*pszT = 0;
|
|
}
|
|
|
|
//
|
|
// If the VISITED: entry does not exist in the cache assume url is unread
|
|
//
|
|
#ifndef ALIGNMENT_MACHINE
|
|
BYTE visitedCEI[MAX_CACHE_ENTRY_INFO_SIZE];
|
|
LPINTERNET_CACHE_ENTRY_INFO pVisitedCEI = (LPINTERNET_CACHE_ENTRY_INFO)visitedCEI;
|
|
#else
|
|
union
|
|
{
|
|
double align8;
|
|
BYTE visitedCEI[MAX_CACHE_ENTRY_INFO_SIZE];
|
|
} alignedvisitedCEI;
|
|
LPINTERNET_CACHE_ENTRY_INFO pVisitedCEI = (LPINTERNET_CACHE_ENTRY_INFO)&alignedvisitedCEI;
|
|
#endif /* ALIGNMENT_MACHINE */
|
|
dwLen = MAX_CACHE_ENTRY_INFO_SIZE;
|
|
|
|
if (GetUrlCacheEntryInfo(szVisited, pVisitedCEI, &dwLen) == FALSE)
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// URL has been visited, but it still may be unread if the page has
|
|
// been placed in the cache by the infodelivery mechanism
|
|
//
|
|
#ifndef ALIGNMENT_MACHINE
|
|
BYTE urlCEI[MAX_CACHE_ENTRY_INFO_SIZE];
|
|
LPINTERNET_CACHE_ENTRY_INFO pUrlCEI = (LPINTERNET_CACHE_ENTRY_INFO)urlCEI;
|
|
#else
|
|
union
|
|
{
|
|
double align8;
|
|
BYTE urlCEI[MAX_CACHE_ENTRY_INFO_SIZE];
|
|
} alignedurlCEI;
|
|
LPINTERNET_CACHE_ENTRY_INFO pUrlCEI = (LPINTERNET_CACHE_ENTRY_INFO)&alignedurlCEI;
|
|
#endif /* ALIGNMENT_MACHINE */
|
|
|
|
dwLen = MAX_CACHE_ENTRY_INFO_SIZE;
|
|
|
|
if (GetUrlCacheEntryInfo(szCanonicalizedUrl, pUrlCEI, &dwLen) == FALSE)
|
|
{
|
|
return FALSE; // no url cache entry but url was visited so mark read
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If the url has been modified after the time of the visited
|
|
// record then url is unread
|
|
//
|
|
if (CompareFileTime(&pUrlCEI->LastModifiedTime,
|
|
&pVisitedCEI->LastModifiedTime) > 0)
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Looks the URL up in the cache. TRUE if it is and FALSE otherwise
|
|
//
|
|
BOOL
|
|
CDFIDL_IsCachedURL(
|
|
LPWSTR wszUrl
|
|
)
|
|
{
|
|
|
|
BOOL fCached;
|
|
TCHAR szUrlT[INTERNET_MAX_URL_LENGTH];
|
|
|
|
|
|
//
|
|
// Canonicalize the input url.
|
|
//
|
|
|
|
if (SHUnicodeToTChar(wszUrl, szUrlT, ARRAYSIZE(szUrlT)))
|
|
{
|
|
URL_COMPONENTS uc;
|
|
|
|
ZeroMemory(&uc, sizeof(uc));
|
|
uc.dwStructSize = sizeof(URL_COMPONENTS);
|
|
uc.dwSchemeLength = 1;
|
|
if (InternetCrackUrl(szUrlT, 0, 0, &uc))
|
|
{
|
|
// zekel should look at this
|
|
TCHAR *pchLoc = StrChr(szUrlT, TEXT('#'));
|
|
if (pchLoc)
|
|
*pchLoc = TEXT('\0');
|
|
|
|
|
|
fCached = GetUrlCacheEntryInfoEx(szUrlT, NULL, NULL, NULL, NULL, NULL, 0);
|
|
if(fCached)
|
|
{
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
TCHAR szCanonicalizedUrlT[INTERNET_MAX_URL_LENGTH];
|
|
DWORD dwLen = INTERNET_MAX_URL_LENGTH;
|
|
InternetCanonicalizeUrl(szUrlT, szCanonicalizedUrlT, &dwLen, 0);
|
|
|
|
fCached = GetUrlCacheEntryInfoEx(szCanonicalizedUrlT, NULL, NULL, NULL, NULL, NULL, 0);
|
|
|
|
if(fCached)
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CDFIDL_GetAttributes ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Returns the attributes item of the given cdf item id list.
|
|
//
|
|
// Parameters:
|
|
// [In] pIXMLElementCollectionparent - The containing element collection.
|
|
// [In] pcdfidl - A pointer to the cdf item id list.
|
|
// [In] fAttributesFilter - Determines which flags to bother
|
|
// looking at
|
|
//
|
|
// Return:
|
|
// The attributes of the given id list.
|
|
// Zero on failure. Note: Zero is a valid attribute value.
|
|
//
|
|
// Comments:
|
|
// The attribute flags returned by this function can be used directly as a
|
|
// return value by IShellFolder->GetAttributesOf().
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
ULONG
|
|
CDFIDL_GetAttributes(
|
|
IXMLElementCollection* pIXMLElementCollectionParent,
|
|
PCDFITEMIDLIST pcdfidl,
|
|
ULONG fAttributesFilter
|
|
)
|
|
{
|
|
ASSERT(pIXMLElementCollectionParent);
|
|
ASSERT(CDFIDL_IsValid(pcdfidl));
|
|
ASSERT(ILIsEmpty(_ILNext((LPITEMIDLIST)pcdfidl)));
|
|
|
|
//
|
|
// REVIEW: Need to properly determine shell attributes of cdf items.
|
|
//
|
|
|
|
ULONG uRet;
|
|
|
|
if (CDFIDL_IsFolderId(&pcdfidl->mkid))
|
|
{
|
|
uRet = SFGAO_FOLDER | SFGAO_CANLINK;
|
|
|
|
// If we weren't asked for HASSUBFOLDER don't bother looking for it
|
|
// This should be a win in non tree views (ie. std open mode)
|
|
if ((SFGAO_HASSUBFOLDER & fAttributesFilter) &&
|
|
pIXMLElementCollectionParent &&
|
|
XML_ChildContainsFolder(pIXMLElementCollectionParent,
|
|
CDFIDL_GetIndex(pcdfidl)))
|
|
{
|
|
uRet |= SFGAO_HASSUBFOLDER;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
uRet = SFGAO_CANLINK;
|
|
// If we weren't asked for NEWCONTENT don't bother looking for it
|
|
// This will be a win in non channel pane views.
|
|
// Can't test for SFGAO_NEWCONTENT since shell is never
|
|
// expressing interest in it!
|
|
if (/*(SFGAO_NEWCONTENT & fAttributeFilter) && */
|
|
CDFIDL_IsUnreadURL(CDFIDL_GetURL(pcdfidl)))
|
|
{
|
|
uRet |= SFGAO_NEWCONTENT;
|
|
}
|
|
}
|
|
|
|
return uRet;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CDFIDL_Compare ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Compares two cdf item id lists
|
|
//
|
|
// Parameters:
|
|
// [In] pcdfidl1 - A pointer to the first item id list to compare.
|
|
// [In] pcdfidl2 - A pointer to the second item id list to compare.
|
|
//
|
|
// Return:
|
|
// -1 if item 1 comes before item 2.
|
|
// 0 if the items are equal.
|
|
// 1 if item 2 comes before item 1.
|
|
//
|
|
// Comments:
|
|
// Sort Order:
|
|
// 1) Use the CompareId result of the first items in the lists.
|
|
// 2) If 1) returns 0. Compare the next two items in the lists.
|
|
// 3) If both list are empty. They are equal.
|
|
// 4) The shorter id list comes first.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
SHORT
|
|
CDFIDL_Compare(
|
|
PCDFITEMIDLIST pcdfidl1,
|
|
PCDFITEMIDLIST pcdfidl2
|
|
)
|
|
{
|
|
ASSERT(CDFIDL_IsValid(pcdfidl1));
|
|
ASSERT(CDFIDL_IsValid(pcdfidl2));
|
|
|
|
SHORT sRet;
|
|
|
|
sRet = CDFIDL_CompareId(&pcdfidl1->mkid, &pcdfidl2->mkid);
|
|
|
|
if (0 == sRet)
|
|
{
|
|
if (!ILIsEmpty(_ILNext(pcdfidl1)) && !ILIsEmpty(_ILNext(pcdfidl2)))
|
|
{
|
|
sRet = CDFIDL_Compare((PCDFITEMIDLIST)_ILNext(pcdfidl1),
|
|
(PCDFITEMIDLIST)_ILNext(pcdfidl2));
|
|
}
|
|
else if(!ILIsEmpty(_ILNext(pcdfidl1)) && ILIsEmpty(_ILNext(pcdfidl2)))
|
|
{
|
|
sRet = 1;
|
|
}
|
|
else if (ILIsEmpty(_ILNext(pcdfidl1)) && !ILIsEmpty(_ILNext(pcdfidl2)))
|
|
{
|
|
sRet = -1;
|
|
}
|
|
}
|
|
|
|
return sRet;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CDFIDL_CompareId ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Compares two item cdf item ids.
|
|
//
|
|
// Parameters:
|
|
// [In] pcdfid1 - A pointer to the first item id to compare.
|
|
// [In] pcdfid2 - A pointer to the second item id to compare.
|
|
//
|
|
// Return:
|
|
// -1 if item 1 comes before item 2.
|
|
// 0 if the items are the same.
|
|
// 1 if item 2 comes before item 1.
|
|
//
|
|
// Comments:
|
|
// Sort Order:
|
|
// 1) CDF_FolderLink (Essentially an URL for the current folder). These
|
|
// have an index of -1.
|
|
// 2) Everything else accoring to its order in the CDF. These have
|
|
// a zero-based index.
|
|
// 3) Non CDF items (should't have any).
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
SHORT
|
|
CDFIDL_CompareId(
|
|
PCDFITEMID pcdfid1,
|
|
PCDFITEMID pcdfid2
|
|
)
|
|
{
|
|
ASSERT(CDFIDL_IsValidId(pcdfid1));
|
|
ASSERT(CDFIDL_IsValidId(pcdfid2));
|
|
|
|
SHORT sRet;
|
|
|
|
if (pcdfid1->nIndex < pcdfid2->nIndex)
|
|
{
|
|
sRet = -1;
|
|
}
|
|
else if (pcdfid1->nIndex > pcdfid2->nIndex)
|
|
{
|
|
sRet = 1;
|
|
}
|
|
else
|
|
{
|
|
sRet = (short) CompareString(LOCALE_USER_DEFAULT, 0, CDFIDL_GetNameId(pcdfid1),
|
|
-1, CDFIDL_GetNameId(pcdfid2), -1);
|
|
|
|
//
|
|
// Note: CompareString returns 1 if S1 comes before S2, 2 if S1 is equal
|
|
// to S2, 3 if S2 comes before S1 and 0 on error.
|
|
//
|
|
|
|
sRet = sRet ? sRet - 2 : 0;
|
|
|
|
if (0 == sRet)
|
|
{
|
|
//
|
|
// If the URLs aren't equal just pick one at random.
|
|
//
|
|
|
|
sRet = !StrEql(CDFIDL_GetURLId(pcdfid1), CDFIDL_GetURLId(pcdfid2));
|
|
|
|
ASSERT((pcdfid1->cb == pcdfid2->cb) || 0 != sRet);
|
|
ASSERT((pcdfid1->cdfItemType == pcdfid1->cdfItemType) || 0 != sRet);
|
|
}
|
|
}
|
|
|
|
return sRet;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CDFIDL_IsValid ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Determines if the given pcdfidl is valid.
|
|
//
|
|
// Parameters:
|
|
// pcdfid - A pointer to the cdf id to check.
|
|
//
|
|
// Return:
|
|
// TRUE if the id is a cdf id.
|
|
// FALSE otherwise.
|
|
//
|
|
// Comments:
|
|
// An empty list is not valid.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
BOOL
|
|
CDFIDL_IsValid(
|
|
PCDFITEMIDLIST pcdfidl
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (pcdfidl && (pcdfidl->mkid.cb > 0))
|
|
{
|
|
bRet = TRUE;
|
|
|
|
while (pcdfidl->mkid.cb && bRet)
|
|
{
|
|
bRet = CDFIDL_IsValidId(&pcdfidl->mkid);
|
|
pcdfidl = (PCDFITEMIDLIST)_ILNext((LPITEMIDLIST)pcdfidl);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
//
|
|
// Inline helper functions.
|
|
//
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CDFIDL_IsValidId ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Inline function that returns TRUE if the given id is a pointer to a cdf
|
|
// item id.
|
|
//
|
|
// Parameters:
|
|
// pcdfid - A pointer to the cdf id to check.
|
|
//
|
|
// Return:
|
|
// TRUE if the id is a cdf id.
|
|
// FALSE otherwise.
|
|
//
|
|
// Comments:
|
|
// This function is not completely safe. If the first word pointed to
|
|
// is large but the memory block pointed to is smaller than a 8 bytes an
|
|
// access violation will occur. Also, if the first word is large enough and
|
|
// the second DWORD is equal to CDFITEM_ID but the item isn't a cdf id a
|
|
// false positive will occur.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
BOOL
|
|
CDFIDL_IsValidId(
|
|
PCDFITEMID pcdfid
|
|
)
|
|
{
|
|
ASSERT(pcdfid);
|
|
|
|
return (pcdfid->cb >= (sizeof(CDFITEMID) + sizeof(TCHAR)) &&
|
|
pcdfid->dwId == CDFITEMID_ID &&
|
|
CDFIDL_IsValidSize(pcdfid) &&
|
|
CDFIDL_IsValidType(pcdfid) &&
|
|
CDFIDL_IsValidIndex(pcdfid) &&
|
|
CDFIDL_IsValidStrings(pcdfid) );
|
|
}
|
|
|
|
inline
|
|
BOOL
|
|
CDFIDL_IsValidSize(
|
|
PCDFITEMID pcdfid
|
|
)
|
|
{
|
|
int cbName = (StrLen(CDFIDL_GetNameId(pcdfid)) + 1) *
|
|
sizeof(TCHAR);
|
|
|
|
int cbURL = (StrLen(CDFIDL_GetURLId(pcdfid)) + 1) *
|
|
sizeof(TCHAR);
|
|
|
|
#ifndef ALIGNMENT_MACHINE
|
|
return (sizeof(CDFITEMID) - sizeof(TCHAR) + cbName + cbURL == pcdfid->cb);
|
|
#else
|
|
return ((ALIGN4(sizeof(CDFITEMID) - sizeof(TCHAR) + cbName + cbURL)) == pcdfid->cb);
|
|
#endif
|
|
}
|
|
|
|
inline
|
|
BOOL
|
|
CDFIDL_IsValidType(
|
|
PCDFITEMID pcdfid
|
|
)
|
|
{
|
|
return ((CDF_Folder == (CDFITEMTYPE)pcdfid->cdfItemType) ||
|
|
(CDF_Link == (CDFITEMTYPE)pcdfid->cdfItemType) ||
|
|
(CDF_FolderLink == (CDFITEMTYPE)pcdfid->cdfItemType) );
|
|
}
|
|
|
|
inline
|
|
BOOL
|
|
CDFIDL_IsValidIndex(
|
|
PCDFITEMID pcdfid
|
|
)
|
|
{
|
|
return ( pcdfid->nIndex >= 0
|
|
||
|
|
(INDEX_CHANNEL_LINK == pcdfid->nIndex &&
|
|
CDF_FolderLink == (CDFITEMTYPE)pcdfid->cdfItemType));
|
|
}
|
|
|
|
inline
|
|
BOOL
|
|
CDFIDL_IsValidStrings(
|
|
PCDFITEMID pcdfid
|
|
)
|
|
{
|
|
//
|
|
// REVIEW: Validate pidl strings.
|
|
//
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CDFIDL_IsFolder ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Inline function that returns TRUE if the given cdfidl is a folder as far
|
|
// as the shel is concerned.
|
|
//
|
|
// Parameters:
|
|
// pcdfidl - The cdf item id list to check.
|
|
//
|
|
// Return:
|
|
// TRUE if the cdf item id list is a folder.
|
|
//
|
|
// Comments:
|
|
//
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
BOOL
|
|
CDFIDL_IsFolder(
|
|
PCDFITEMIDLIST pcdfidl
|
|
)
|
|
{
|
|
ASSERT(CDFIDL_IsValid(pcdfidl));
|
|
|
|
pcdfidl = (PCDFITEMIDLIST)ILFindLastID((LPITEMIDLIST)pcdfidl);
|
|
|
|
return CDFIDL_IsFolderId(&pcdfidl->mkid);
|
|
}
|
|
|
|
BOOL
|
|
CDFIDL_IsFolderId(
|
|
PCDFITEMID pcdfid
|
|
)
|
|
{
|
|
ASSERT(CDFIDL_IsValidId(pcdfid));
|
|
|
|
return (CDF_Folder == (CDFITEMTYPE)pcdfid->cdfItemType);
|
|
}
|
|
|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
|
|
//
|
|
// *** CDFIDL_NonCdfGetName ***
|
|
//
|
|
//
|
|
// Description:
|
|
// Gets the name stored in the given non-cdf item id list.
|
|
//
|
|
// Parameters:
|
|
// [In] pcdfidl - A pointer to a cdf item id list. Can be NULL.
|
|
// [Out] pName - A pointer to a STRRET structure. STRRET has the following
|
|
// structure:
|
|
// UINT uType - STRRET_CSTR, _OFFSET or _WSTR
|
|
// union {
|
|
// LPWSTR pOleStr;
|
|
// UINT uOffset;
|
|
// char cStr[MAX_PATH];
|
|
// }
|
|
//
|
|
// Return:
|
|
// S_OK on success. E_Fail otherwise.
|
|
//
|
|
// Comments:
|
|
// This function returns the name as a cString in the STRRET structure.
|
|
//
|
|
// ILGetDisplayName returns the full path. This function strips out the
|
|
// filename sans extension.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
#if 0
|
|
HRESULT
|
|
CDFIDL_NonCdfGetDisplayName(
|
|
LPCITEMIDLIST pidl,
|
|
LPSTRRET pName
|
|
)
|
|
{
|
|
ASSERT(pName);
|
|
|
|
HRESULT hr;
|
|
|
|
//
|
|
// REVIEW: Hack to get the name of a shell pidl.
|
|
//
|
|
|
|
if (ILGetDisplayName(pidl, pName->cStr))
|
|
{
|
|
TCHAR* p1 = pName->cStr;
|
|
TCHAR* p2 = p1;
|
|
|
|
while (*p1++); // Go to the end.
|
|
while (*--p1 != TEXT('\\')); // Back to last backslash.
|
|
while (TEXT('.') != (*p2++ = *++p1)); // Copy the name.
|
|
*--p2 = TEXT('\0'); // NULL terminate.
|
|
|
|
pName->uType = STRRET_CSTR;
|
|
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
#endif
|