|
|
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ //
// 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
|