//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // 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 cbName = StrLenW(pCdfItem->bstrName) + 1; // // Get the number of chars of the URL of the item including the terminating // null character. // USHORT cbURL = 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) + (cbName + cbURL) * 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) + cbName + cbURL - sizeof(TCHAR); if(cbActaulItemId < cbItemId) memset((LPBYTE)pcdfidl + cbActaulItemId, 0, 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, cbName); SHUnicodeToTChar(pCdfItem->bstrURL, pcdfidl->mkid.szName + cbName, cbURL); #else pszTempName = (LPTSTR)ALIGN4((ULONG_PTR)(pcdfidl->mkid.szName)); SHUnicodeToTChar(pCdfItem->bstrName, pszTempName, cbName); pszTempName = (LPTSTR)((ULONG_PTR)(pcdfidl->mkid.szName+cbName)); SHUnicodeToTChar(pCdfItem->bstrURL, pszTempName, cbURL); #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); #ifdef UNICODE #ifdef SHDOCVW_UNICODE //open this when shdocvw becomes unicode IMalloc* pIMalloc; HRESULT hr = SHGetMalloc(&pIMalloc); if (SUCCEEDED(hr)) { ASSERT(pIMalloc); pName->uType = STRRET_WSTR; LPTSTR pszName = CDFIDL_GetName(pcdfidl); pName->pOleStr = (LPWSTR)pIMalloc->Alloc(ARRAYSIZE(pszName)); if (pName->pOleStr) lstrcpyW(pName->pOleStr, pszName); pIMalloc->Release(); } #else pName->uType = STRRET_CSTR; LPTSTR pszName = CDFIDL_GetName(pcdfidl); SHTCharToAnsi(pszName, pName->cStr, ARRAYSIZE(pName->cStr)); #endif #else pName->uType = STRRET_OFFSET; pName->uOffset = (UINT)((LPBYTE)CDFIDL_GetName(pcdfidl) - (LPBYTE)pcdfidl); #endif 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)]; StrCpy(szVisited, ASTR_HISTORY_PREFIX); StrCatN(szVisited, CDFIDL_GetUserName(), ARRAYSIZE(szVisited)); int len = StrLen(szVisited); StrCpyN(szVisited + len++, TEXT("@"), ARRAYSIZE(szVisited) - len); //len++; //bug, this will introduce a null char... StrCpyN(szVisited + len++, szCanonicalizedUrl, ARRAYSIZE(szVisited) - 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; memset(&uc, 0, 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