//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // xmlutil.cpp // // XML item helper functions. // // History: // // 4/1/97 edwardp Created. // //////////////////////////////////////////////////////////////////////////////// // // Includes // #include "stdinc.h" #include "cdfidl.h" #include "xmlutil.h" #include "winineti.h" #include // IPersistStreamInit. // // Function prototypes. // // // XML helper functions. // //////////////////////////////////////////////////////////////////////////////// // // *** XML_MarkCacheEntrySticky *** // // Description: // Marks the cache entry for the given URL as sticky by setting its // expiration delta to be very high // // Parameters: // [In] lpszUrl - url for cache entry to make sticky // // Return: // S_OK if the url entry was successfully marked sticky // E_FAIL otherwise. // //////////////////////////////////////////////////////////////////////////////// HRESULT XML_MarkCacheEntrySticky(LPTSTR lpszURL) { char chBuf[MAX_CACHE_ENTRY_INFO_SIZE]; LPINTERNET_CACHE_ENTRY_INFO lpInfo = (LPINTERNET_CACHE_ENTRY_INFO) chBuf; DWORD dwSize = sizeof(chBuf); lpInfo->dwStructSize = dwSize; if (GetUrlCacheEntryInfo(lpszURL, lpInfo, &dwSize)) { lpInfo->dwExemptDelta = 0xFFFFFFFF; // make VERY sticky if (SetUrlCacheEntryInfo(lpszURL, lpInfo, CACHE_ENTRY_EXEMPT_DELTA_FC)) { return S_OK; } } return E_FAIL; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_SynchronousParse *** // // // Description: // Synchronously parses the given URL. // // Parameters: // [In] pIXMLDocument - An interface pointer to an XML document object. // [In] pidl - The pidl of the cdf file (contains the full path). // // Return: // S_OK if the object was parsed successfully. // E_FAIL otherwise. // // Comments: // // //////////////////////////////////////////////////////////////////////////////// HRESULT XML_SynchronousParse( IXMLDocument* pIXMLDocument, LPTSTR szPath ) { ASSERT(pIXMLDocument); ASSERT(szPath); HRESULT hr; IPersistStreamInit* pIPersistStreamInit; hr = pIXMLDocument->QueryInterface(IID_IPersistStreamInit, (void**)&pIPersistStreamInit); if (SUCCEEDED(hr)) { ASSERT(pIPersistStreamInit); IStream* pIStream; // // URLOpenBlockingStream pumps window messages! Don't use it! // //hr = URLOpenBlockingStream(NULL, szPath, &pIStream, 0, NULL); hr = SHCreateStreamOnFile(szPath, STGM_READ, &pIStream); TraceMsg(TF_CDFPARSE, "[%s SHCreateStreamOnFileW %s %s %s]", PathIsURL(szPath) ? TEXT("*** ") : TEXT(""), szPath, SUCCEEDED(hr) ? TEXT("SUCCEEDED") : TEXT("FAILED"), PathIsURL(szPath) ? TEXT("***") : TEXT("")); if (SUCCEEDED(hr)) { ASSERT(pIStream); // // Load loads and parses the file. If this call succeeds the cdf // will be displayed. If it fails none of the cdf is displayed. // hr = pIPersistStreamInit->Load(pIStream); TraceMsg(TF_CDFPARSE, "[XML Parser %s]", SUCCEEDED(hr) ? TEXT("SUCCEEDED") : TEXT("FAILED")); pIStream->Release(); // // If CDFVIEW is downloading a CDF from the net mark it as sticky // in the cache // if (PathIsURL(szPath)) { XML_MarkCacheEntrySticky(szPath); } } pIPersistStreamInit->Release(); } return hr; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_DownloadImages *** // // // Description: // // // Parameters: // // // Return: // // // Comments: // // //////////////////////////////////////////////////////////////////////////////// HRESULT XML_DownloadLogo( IXMLDocument *pIXMLDocument ) { ASSERT(pIXMLDocument); HRESULT hr; IXMLElement* pIXMLElement; LONG nIndex; hr = XML_GetFirstChannelElement(pIXMLDocument, &pIXMLElement, &nIndex); if (SUCCEEDED(hr)) { ASSERT(pIXMLElement); BSTR bstrURL = XML_GetAttribute(pIXMLElement, XML_LOGO); if (bstrURL) { hr = XML_DownloadImage(bstrURL); SysFreeString(bstrURL); } // // Download the wide logo also. // bstrURL = XML_GetAttribute(pIXMLElement, XML_LOGO_WIDE); if (bstrURL) { hr = XML_DownloadImage(bstrURL); SysFreeString(bstrURL); } pIXMLElement->Release(); } return hr; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_DownloadImages *** // // // Description: // // // Parameters: // // // Return: // // // Comments: // // //////////////////////////////////////////////////////////////////////////////// HRESULT XML_DownloadImages( IXMLDocument *pIXMLDocument ) { ASSERT(pIXMLDocument); HRESULT hr; IXMLElement* pIXMLElement; LONG nIndex; hr = XML_GetFirstChannelElement(pIXMLDocument, &pIXMLElement, &nIndex); if (SUCCEEDED(hr)) { ASSERT(pIXMLElement); hr = XML_RecursiveImageDownload(pIXMLElement); pIXMLElement->Release(); } return hr; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_RecuriveImageDownload *** // // // Description: // // // Parameters: // // // Return: // // // Comments: // // //////////////////////////////////////////////////////////////////////////////// HRESULT XML_RecursiveImageDownload( IXMLElement* pIXMLElement ) { ASSERT(pIXMLElement); HRESULT hr = S_OK; BSTR bstrTagName; HRESULT hr2 = pIXMLElement->get_tagName(&bstrTagName); if (SUCCEEDED(hr2) && bstrTagName) { if (StrEqlW(bstrTagName, WSTR_LOGO)) { BSTR bstrURL = XML_GetAttribute(pIXMLElement, XML_HREF); if (bstrURL && *bstrURL != 0) { hr = XML_DownloadImage(bstrURL); SysFreeString(bstrURL); } } else if (XML_IsCdfDisplayable(pIXMLElement)) { IXMLElementCollection* pIXMLElementCollection; hr2 = pIXMLElement->get_children(&pIXMLElementCollection); if (SUCCEEDED(hr2) && pIXMLElementCollection) { ASSERT(pIXMLElementCollection); LONG nCount; hr2 = pIXMLElementCollection->get_length(&nCount); ASSERT(SUCCEEDED(hr2) || (FAILED(hr2) && 0 == nCount)); for (int i = 0; i < nCount; i++) { IXMLElement* pIXMLElementChild; hr2 = XML_GetElementByIndex(pIXMLElementCollection, i, &pIXMLElementChild); if (SUCCEEDED(hr2)) { ASSERT (pIXMLElementChild); XML_RecursiveImageDownload(pIXMLElementChild); pIXMLElementChild->Release(); } } pIXMLElementCollection->Release(); } } SysFreeString(bstrTagName); } return hr; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_DownloadImage *** // // // Description: // // // Parameters: // // // Return: // // // Comments: // // //////////////////////////////////////////////////////////////////////////////// HRESULT XML_DownloadImage( LPCWSTR pwszURL ) { ASSERT (pwszURL); HRESULT hr; WCHAR szFileW[MAX_PATH]; hr = URLDownloadToCacheFileW(NULL, pwszURL, szFileW, ARRAYSIZE(szFileW), 0, NULL); // // Mark the logo in the cache as sticky // if (SUCCEEDED(hr)) { TCHAR szURL[INTERNET_MAX_URL_LENGTH]; SHUnicodeToTChar(pwszURL, szURL, ARRAYSIZE(szURL)); XML_MarkCacheEntrySticky(szURL); } #ifdef DEBUG TCHAR szURL[INTERNET_MAX_URL_LENGTH]; SHUnicodeToTChar(pwszURL, szURL, ARRAYSIZE(szURL)); TraceMsg(TF_CDFPARSE, "[*** Image URLDownloadToCacheFileW %s %s ***]", szURL, SUCCEEDED(hr) ? TEXT("SUCCEEDED") : TEXT("FAILED")); #endif // DEBUG return hr; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_GetDocType *** // // // Description: // Returns the type of the given xml document. // // Parameters: // [In] pIXMLDocument - A pointer to the xml document. // // Return: // DOC_CHANNEL, DOC_DESKTOPCOMPONENT, DOC_SOFTWAREUPDATE, or DOC_UNKNOWN. // // Comments: // If at the root level of a channel an ITEM contains a USAGE type of // DesktopComponent then the document is a Desktop Component otherwise // it is a channel. // //////////////////////////////////////////////////////////////////////////////// XMLDOCTYPE XML_GetDocType(IXMLDocument* pIXMLDocument) { ASSERT(pIXMLDocument); XMLDOCTYPE xdtRet; IXMLElement* pIXMLElement; LONG nIndex; HRESULT hr = XML_GetFirstDesktopComponentElement(pIXMLDocument, &pIXMLElement, &nIndex); if (SUCCEEDED(hr)) { ASSERT(pIXMLElement); xdtRet = DOC_DESKTOPCOMPONENT; pIXMLElement->Release(); } else { hr = XML_GetFirstChannelElement(pIXMLDocument, &pIXMLElement, &nIndex); if (SUCCEEDED(hr)) { ASSERT(pIXMLElement); BSTR bstr = XML_GetAttribute( pIXMLElement, XML_USAGE_SOFTWAREUPDATE ); if (bstr) { SysFreeString(bstr); xdtRet = DOC_SOFTWAREUPDATE; } else { xdtRet = DOC_CHANNEL; } pIXMLElement->Release(); } else { xdtRet = DOC_UNKNOWN; } } return xdtRet; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_GetChildElementCollection *** // // // Description: // Returns an element collection given the parent collection and an index. // // Parameters: // [In] pParentIXMLElementCollection - The parent collection. // [In] nIndex - Index to the requested collection. // [Out] ppIXMLElementCollection - A pointer that receives the // requested collection. // // Return: // S_OK if the collection is returned. // E_FAIL otherwise. // // Comments: // The caller is responsible for calling Release() on the returned interface // pointer. // //////////////////////////////////////////////////////////////////////////////// HRESULT XML_GetChildElementCollection( IXMLElementCollection *pParentIXMLElementCollection, LONG nIndex, IXMLElementCollection** ppIXMLElementCollection ) { ASSERT(pParentIXMLElementCollection); ASSERT(ppIXMLElementCollection); HRESULT hr; IXMLElement* pIXMLElement; hr = XML_GetElementByIndex(pParentIXMLElementCollection, nIndex, &pIXMLElement); if (SUCCEEDED(hr)) { ASSERT(pIXMLElement); hr = pIXMLElement->get_children(ppIXMLElementCollection); if(SUCCEEDED(hr) && !(*ppIXMLElementCollection)) hr = E_FAIL; pIXMLElement->Release(); } ASSERT((SUCCEEDED(hr) && (*ppIXMLElementCollection)) || FAILED(hr)); return hr; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_GetElementByIndex *** // // // Description: // Returns the nIndex'th element of the given collection. // // Parameters: // [In] pIXMLElementCollection - A pointer to the collection. // [In] nIndex - The index of the item to retrieve. // [Out] ppIXMLElement - A pointer that receives the item. // // Return: // S_OK if the item was retrieved. // E_FAIL otherwise. // // Comments: // The caller is responsible for calling Release() on the returned interface // pointer. // //////////////////////////////////////////////////////////////////////////////// HRESULT XML_GetElementByIndex( IXMLElementCollection* pIXMLElementCollection, LONG nIndex, IXMLElement** ppIXMLElement ) { ASSERT(pIXMLElementCollection); ASSERT(ppIXMLElement); HRESULT hr; VARIANT var1, var2; VariantInit(&var1); VariantInit(&var2); var1.vt = VT_I4; var1.lVal = nIndex; IDispatch* pIDispatch; hr = pIXMLElementCollection->item(var1, var2, &pIDispatch); if (SUCCEEDED(hr)) { ASSERT(pIDispatch); hr = pIDispatch->QueryInterface(IID_IXMLElement, (void**)ppIXMLElement); pIDispatch->Release(); } else { *ppIXMLElement = NULL; } ASSERT((SUCCEEDED(hr) && *ppIXMLElement) || (FAILED(hr) && NULL == *ppIXMLElement)); return hr; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_GetElementByName *** // // // Description: // Returns the first element with the given tag name. // // Parameters: // [In] pIXMLElementCollection - A pointer to the collection. // [In] nszNameW - The tag name of the item to retrieve. // [Out] ppIXMLElement - A pointer that receives the item. // // Return: // S_OK if the item was retrieved. // E_OUTOFMEMORY if a sys string could not be allocated. // E_FAIL otherwise. // // Comments: // The caller is responsible for calling Release() on the returned interface // pointer. // //////////////////////////////////////////////////////////////////////////////// HRESULT XML_GetElementByName( IXMLElementCollection* pIXMLElementCollection, LPWSTR szNameW, IXMLElement** ppIXMLElement ) { ASSERT(pIXMLElementCollection); ASSERT(ppIXMLElement); HRESULT hr = E_FAIL; LONG nCount; HRESULT hr2 = pIXMLElementCollection->get_length(&nCount); ASSERT(SUCCEEDED(hr2) || (FAILED(hr2) && 0 == nCount)); for (int i = 0, bElement = FALSE; (i < nCount) && !bElement; i++) { IXMLElement* pIXMLElement; hr2 = XML_GetElementByIndex(pIXMLElementCollection, i, &pIXMLElement); if (SUCCEEDED(hr2)) { ASSERT(pIXMLElement); BSTR pStr; hr2 = pIXMLElement->get_tagName(&pStr); if (SUCCEEDED(hr2) && pStr) { ASSERT(pStr); if (bElement = StrEqlW(pStr, szNameW)) { pIXMLElement->AddRef(); *ppIXMLElement = pIXMLElement; hr = S_OK; } SysFreeString(pStr); } pIXMLElement->Release(); } } hr = FAILED(hr2) ? hr2 : hr; /* Enable this when pIXMLElementCollection->item works with VT_BSTR VARIANT var1, var2; VariantInit(&var1); VariantInit(&var2); var1.vt = VT_BSTR; var1.bstrVal = SysAllocString(szNameW); var2.vt = VT_I4 var2.lVal = 1; if (var1.bstrVal) { IDispatch* pIDispatch; hr = pIXMLElementCollection->item(var1, var2, &pIDispatch); if (SUCCEEDED(hr)) { ASSERT(pIDispatch); hr = pIDispatch->QueryInterface(IID_IXMLElement, (void**)ppIXMLElement); pIDispatch->Release(); } SysFreeString(var1.bstrVal); } else { hr = E_OUTOFMEMORY; } */ ASSERT((SUCCEEDED(hr) && ppIXMLElement) || FAILED(hr)); return hr; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_GetFirstChannelElement *** // // // Description: // Returns the IXMLElement of the first channel in the XML document. // // Parameters: // [In] pIXMLDocument - A pointer to the XML document object. // [Out] ppIXMLElement - The pointer that receives the element. // [Out] pnIndex - The index of the element. // // Return: // S_OK if the first channel element was returned. // E_FAIL if the element couldn't be returned. // // Comments: // This function can't call XML_GetElementByName to find the first channel. // XML channels can have a tag name of "Channel" or "CHAN". // XML_GetElementByName wouldn't be able to determine which of the items // came first if both where present in the XML doc. // // The caller is responsible for calling Release() on the returned interface // pointer. The return pointer is not NULL'ed out on error. // //////////////////////////////////////////////////////////////////////////////// HRESULT XML_GetFirstChannelElement( IXMLDocument* pIXMLDocument, IXMLElement** ppIXMLElement, PLONG pnIndex) { ASSERT(pIXMLDocument); ASSERT(ppIXMLElement); ASSERT(pnIndex); IXMLElement *pRootElem = NULL; HRESULT hr = E_FAIL; *pnIndex = 0; hr = pIXMLDocument->get_root(&pRootElem); if (SUCCEEDED(hr) && pRootElem) { ASSERT(pRootElem); if (XML_IsChannel(pRootElem)) { *ppIXMLElement = pRootElem; hr = S_OK; } else { pRootElem->Release(); hr = E_FAIL; } } else { hr = E_FAIL; } ASSERT((SUCCEEDED(hr) && (*ppIXMLElement)) || FAILED(hr)); return hr; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_GetDesktopElementFromChannelElement *** // // // Description: // Returns the IXMLElement of the first dekstop component in the channel. // // Parameters: // [In] pChannelIXMLElement - A pointer to the XML channel element. // [Out] ppIXMLElement - The pointer that receives the element. // [Out] pnIndex - The index of the element. // // Return: // S_OK if the first desktop element was returned. // E_FAIL if the element couldn't be returned. // // Comments: // This looks for the first ITEM with a usage of DesktopComponent. // //////////////////////////////////////////////////////////////////////////////// HRESULT XML_GetDesktopElementFromChannelElement( IXMLElement* pChannelIXMLElement, IXMLElement** ppIXMLElement, PLONG pnIndex) { ASSERT(pChannelIXMLElement); ASSERT(ppIXMLElement); ASSERT(pnIndex); HRESULT hr; IXMLElementCollection* pIXMLElementCollection; hr = pChannelIXMLElement->get_children(&pIXMLElementCollection); if (SUCCEEDED(hr) && pIXMLElementCollection) { ASSERT(pIXMLElementCollection); LONG nCount; hr = pIXMLElementCollection->get_length(&nCount); ASSERT(SUCCEEDED(hr) || (FAILED(hr) && 0 == nCount)); hr = E_FAIL; for (int i = 0, bComponent = FALSE; (i < nCount) && !bComponent; i++) { IXMLElement* pIXMLElement; HRESULT hr2 = XML_GetElementByIndex(pIXMLElementCollection, i, &pIXMLElement); if (SUCCEEDED(hr2)) { ASSERT(pIXMLElement); if (bComponent = XML_IsDesktopComponent(pIXMLElement)) { pIXMLElement->AddRef(); *ppIXMLElement = pIXMLElement; *pnIndex = i; hr = S_OK; } pIXMLElement->Release(); } hr = FAILED(hr2) ? hr2 : hr; } pIXMLElementCollection->Release(); } else { hr = E_FAIL; } return hr; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_GetFirstDesktopComponentElement *** // // // Description: // Returns the IXMLElement of the first dekstop component in the channel. // // Parameters: // [In] pIXMLDocument - A pointer to the XML document object. // [Out] ppIXMLElement - The pointer that receives the element. // [Out] pnIndex - The index of the element. // // Return: // S_OK if the first channel element was returned. // E_FAIL if the element couldn't be returned. // // Comments: // This function gets the first channel and then looks for the first // top-level ITEM with a usage of DesktopComponent. // //////////////////////////////////////////////////////////////////////////////// HRESULT XML_GetFirstDesktopComponentElement( IXMLDocument* pIXMLDocument, IXMLElement** ppIXMLElement, PLONG pnIndex) { ASSERT(pIXMLDocument); ASSERT(ppIXMLElement); ASSERT(pnIndex); HRESULT hr; IXMLElement* pChannelIXMLElement; LONG nIndex; hr = XML_GetFirstChannelElement(pIXMLDocument, &pChannelIXMLElement, &nIndex); if (SUCCEEDED(hr)) { ASSERT(pChannelIXMLElement); hr = XML_GetDesktopElementFromChannelElement(pChannelIXMLElement, ppIXMLElement, pnIndex); pChannelIXMLElement->Release(); } ASSERT((SUCCEEDED(hr) && *ppIXMLElement) || FAILED(hr)); return hr; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_GetFirstDesktopComponentUsageElement *** // // // Description: // Returns the first USAGE VALUE="DesktopComponent" element of the first // desktop component. // // Parameters: // [In] pIXMLDocument - A pointer to the the document. // [Out] pIXMLElement - A pointer the receives the element. // // Return: // S_OK if the element was found. // E_FAIL if the element wasn't found. // // Comments: // // //////////////////////////////////////////////////////////////////////////////// HRESULT XML_GetFirstDesktopComponentUsageElement( IXMLDocument* pIXMLDocument, IXMLElement** ppIXMLElement ) { ASSERT(pIXMLDocument); ASSERT(ppIXMLElement); HRESULT hr; IXMLElement* pParentIXMLElement; LONG nIndex; hr = XML_GetFirstDesktopComponentElement(pIXMLDocument, &pParentIXMLElement, &nIndex); if (SUCCEEDED(hr)) { IXMLElementCollection* pIXMLElementCollection; hr = pParentIXMLElement->get_children(&pIXMLElementCollection); if (SUCCEEDED(hr) && pIXMLElementCollection) { ASSERT(pIXMLElementCollection); LONG nCount; hr = pIXMLElementCollection->get_length(&nCount); ASSERT(SUCCEEDED(hr) || (FAILED(hr) && 0 == nCount)); hr = E_FAIL; for (int i = 0, bUsage = FALSE; (i < nCount) && !bUsage; i++) { IXMLElement* pIXMLElement; HRESULT hr2 = XML_GetElementByIndex(pIXMLElementCollection, i, &pIXMLElement); if (SUCCEEDED(hr2)) { ASSERT(pIXMLElement); if (bUsage = XML_IsDesktopComponentUsage(pIXMLElement)) { pIXMLElement->AddRef(); *ppIXMLElement = pIXMLElement; //*pnIndex = i; hr = S_OK; } pIXMLElement->Release(); } hr = FAILED(hr2) ? hr2 : hr; } pIXMLElementCollection->Release(); } else { hr = E_FAIL; } pParentIXMLElement->Release(); } return hr; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_GetDesktopComponentInfo *** // // // Description: // Fills in the desktop component information structure. // // Parameters: // [In] pIXMLDocument - A ponter to the document. // [Out] pInfo - A desktop component information structure. // // Return: // S_OK if the given document is desktop component document. // E_FAIL otherwise. // // Comments: // // //////////////////////////////////////////////////////////////////////////////// HRESULT XML_GetDesktopComponentInfo( IXMLDocument* pIXMLDocument, COMPONENT* pInfo ) { ASSERT(pIXMLDocument); ASSERT(pInfo); HRESULT hr; IXMLElement* pIXMLElement; hr = XML_GetFirstDesktopComponentUsageElement(pIXMLDocument, &pIXMLElement); if (SUCCEEDED(hr)) { ASSERT(pIXMLElement); memset(pInfo, 0, sizeof(COMPONENT)); pInfo->dwSize = sizeof(COMPONENT); pInfo->fChecked = TRUE; pInfo->fDirty = TRUE; pInfo->fNoScroll = FALSE; pInfo->cpPos.dwSize = sizeof(COMPPOS); pInfo->cpPos.izIndex = COMPONENT_TOP; pInfo->dwCurItemState = IS_NORMAL; BSTR bstrValue; if (bstrValue = XML_GetAttribute(pIXMLElement, XML_OPENAS)) { if (!(0 == StrCmpIW(bstrValue, WSTR_IMAGE))) { pInfo->iComponentType = COMP_TYPE_WEBSITE; } else { pInfo->iComponentType = COMP_TYPE_PICTURE; } SysFreeString(bstrValue); } if (bstrValue = XML_GetAttribute(pIXMLElement, XML_WIDTH)) { pInfo->cpPos.dwWidth = StrToIntW(bstrValue); SysFreeString(bstrValue); } if (bstrValue = XML_GetAttribute(pIXMLElement, XML_HEIGHT)) { pInfo->cpPos.dwHeight = StrToIntW(bstrValue); SysFreeString(bstrValue); } if (bstrValue = XML_GetAttribute(pIXMLElement, XML_ITEMSTATE)) { if(!StrCmpIW(bstrValue, WSTR_NORMAL)) pInfo->dwCurItemState = IS_NORMAL; else { if(!StrCmpIW(bstrValue, WSTR_FULLSCREEN)) pInfo->dwCurItemState = IS_FULLSCREEN; else pInfo->dwCurItemState = IS_SPLIT; } SysFreeString(bstrValue); } if (bstrValue = XML_GetAttribute(pIXMLElement, XML_CANRESIZE)) { pInfo->cpPos.fCanResize = StrEqlW(bstrValue, WSTR_YES); SysFreeString(bstrValue); } else { if (bstrValue = XML_GetAttribute(pIXMLElement, XML_CANRESIZEX)) { pInfo->cpPos.fCanResizeX = StrEqlW(bstrValue, WSTR_YES); SysFreeString(bstrValue); } if (bstrValue = XML_GetAttribute(pIXMLElement, XML_CANRESIZEY)) { pInfo->cpPos.fCanResizeY = StrEqlW(bstrValue, WSTR_YES); SysFreeString(bstrValue); } } if (bstrValue = XML_GetAttribute(pIXMLElement, XML_PREFERREDLEFT)) { if (StrChrW(bstrValue, L'%')) { pInfo->cpPos.iPreferredLeftPercent = StrToIntW(bstrValue); } else { pInfo->cpPos.iLeft = StrToIntW(bstrValue); } SysFreeString(bstrValue); } if (bstrValue = XML_GetAttribute(pIXMLElement, XML_PREFERREDTOP)) { if (StrChrW(bstrValue, L'%')) { pInfo->cpPos.iPreferredTopPercent = StrToIntW(bstrValue); } else { pInfo->cpPos.iTop = StrToIntW(bstrValue); } SysFreeString(bstrValue); } IXMLElement *pIXMLElementParent; hr = pIXMLElement->get_parent(&pIXMLElementParent); if(!pIXMLElementParent) hr = E_FAIL; if (SUCCEEDED(hr)) { ASSERT(pIXMLElementParent); if (bstrValue = XML_GetAttribute(pIXMLElementParent, XML_TITLE)) { StrCpyNW(pInfo->wszFriendlyName, bstrValue, ARRAYSIZE(pInfo->wszFriendlyName)); SysFreeString(bstrValue); } if (bstrValue = XML_GetAttribute(pIXMLElementParent, XML_HREF)) { if (*bstrValue) { StrCpyNW(pInfo->wszSource, bstrValue, ARRAYSIZE(pInfo->wszSource)); SysFreeString(bstrValue); } else { hr = E_FAIL; } } if (SUCCEEDED(hr)) { IXMLElement *pIXMLChannel; LONG nIndex; hr = XML_GetFirstChannelElement(pIXMLDocument, &pIXMLChannel, &nIndex); if (SUCCEEDED(hr)) { ASSERT(pIXMLChannel); if (bstrValue = XML_GetAttribute(pIXMLChannel, XML_SELF)) { StrCpyNW(pInfo->wszSubscribedURL, bstrValue, ARRAYSIZE(pInfo->wszSubscribedURL)); SysFreeString(bstrValue); } pIXMLChannel->Release(); } } pIXMLElementParent->Release(); } pIXMLElement->Release(); } return hr; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_GetAttribute *** // // // Description: // Returns a bstr representing the requested attribute of the given element. // // Parameters: // [In] pIXMLElement - A pointer to the XML element. // [In] attribute - The requested attribute. // // Return: // A bstr with the attribute value. // NULL if there wasn't enough memory to allocated the bstr. // // Comments: // This function keeps a table of attributes and their properties. It bases // attribute look up on this table. // //////////////////////////////////////////////////////////////////////////////// BSTR XML_GetAttribute( IXMLElement* pIXMLElement, XML_ATTRIBUTE attrIndex ) { // // A table is used to read values associated with a given xml element. The // xml element can have attributes (values inside the elements tag) or child // elements (elements between tags). // // Rules: // 1) If child is NULL. Read the Attribute from the current item. // 2) If child is not NULL, read the Attribute from the child // item. // 3) If AttributeType is NULL, use the Attribute value to read the // attribute. // 4) If AttributeType is not NULL, verify that the item contains // the AttributeType attribute before using Attribute to read // the value. // 5) If the value is not found use Default as the return value. // static const struct _tagXML_ATTRIBUTE_ARRAY { LPWSTR szChildW; LPWSTR szAttributeW; LPWSTR szQualifierW; LPWSTR szQualifierValueW; XML_ATTRIBUTE attrSecondary; LPWSTR szDefaultW; BOOL fUseBaseURL; XML_ATTRIBUTE attribute; // Only used in ASSERT. } aAttribTable[] = { /* Child Attribute Qualifier Qual. Value Secondary Lookup Default Base URL Enum Check -------------- -------------- ----------- ------------ ----------------- ---------- -------- -----------------*/ {WSTR_TITLE, NULL, NULL, NULL, XML_TITLE_ATTR, WSTR_EMPTY, FALSE, XML_TITLE }, {NULL, WSTR_TITLE, NULL, NULL, XML_HREF, WSTR_EMPTY, FALSE, XML_TITLE_ATTR }, {NULL, WSTR_HREF, NULL, NULL, XML_A_HREF, WSTR_EMPTY, TRUE, XML_HREF }, {WSTR_ABSTRACT, NULL, NULL, NULL, XML_ABSTRACT_ATTR, WSTR_EMPTY, FALSE, XML_ABSTRACT }, {NULL, WSTR_ABSTRACT, NULL, NULL, XML_HREF, WSTR_EMPTY, FALSE, XML_ABSTRACT_ATTR}, {WSTR_LOGO, WSTR_HREF, WSTR_STYLE, WSTR_ICON, XML_NULL, NULL, TRUE, XML_ICON }, {WSTR_LOGO, WSTR_HREF, WSTR_STYLE, WSTR_IMAGE, XML_LOGO_DEFAULT, NULL, TRUE, XML_LOGO }, {WSTR_LOGO, WSTR_HREF, NULL, NULL, XML_NULL, NULL, TRUE, XML_LOGO_DEFAULT }, {NULL, WSTR_SELF, NULL, NULL, XML_SELF_OLD, NULL, TRUE, XML_SELF }, {WSTR_SELF, WSTR_HREF, NULL, NULL, XML_NULL, NULL, TRUE, XML_SELF_OLD }, {NULL, WSTR_BASE, NULL, NULL, XML_NULL, NULL, FALSE, XML_BASE }, {WSTR_USAGE, WSTR_VALUE, NULL, NULL, XML_SHOW, NULL, FALSE, XML_USAGE }, {WSTR_USAGE, WSTR_VALUE, WSTR_VALUE, WSTR_CHANNEL, XML_SHOW_CHANNEL, NULL, FALSE, XML_USAGE_CHANNEL}, {WSTR_USAGE, WSTR_VALUE, WSTR_VALUE, WSTR_DSKCMP, XML_SHOW_DSKCMP, NULL, FALSE, XML_USAGE_DSKCMP }, {WSTR_WIDTH, WSTR_VALUE, NULL, NULL, XML_NULL, WSTR_ZERO, FALSE, XML_WIDTH }, {WSTR_HEIGHT, WSTR_VALUE, NULL, NULL, XML_NULL, WSTR_ZERO, FALSE, XML_HEIGHT }, {WSTR_RESIZE, WSTR_VALUE, NULL, NULL, XML_NULL, NULL, FALSE, XML_CANRESIZE }, {WSTR_RESIZEX, WSTR_VALUE, NULL, NULL, XML_NULL, WSTR_YES, FALSE, XML_CANRESIZEX }, {WSTR_RESIZEY, WSTR_VALUE, NULL, NULL, XML_NULL, WSTR_YES, FALSE, XML_CANRESIZEY }, {WSTR_PREFLEFT, WSTR_VALUE, NULL, NULL, XML_NULL, NULL, FALSE, XML_PREFERREDLEFT}, {WSTR_PREFTOP, WSTR_VALUE, NULL, NULL, XML_NULL, NULL, FALSE, XML_PREFERREDTOP }, {WSTR_OPENAS, WSTR_VALUE, NULL, NULL, XML_NULL, WSTR_HTML, FALSE, XML_OPENAS }, {NULL, WSTR_SHOW, NULL, NULL, XML_NULL, NULL, FALSE, XML_SHOW }, {NULL, WSTR_SHOW, WSTR_SHOW, WSTR_CHANNEL, XML_NULL, NULL, FALSE, XML_SHOW_CHANNEL }, {NULL, WSTR_SHOW, WSTR_SHOW, WSTR_DSKCMP, XML_NULL, NULL, FALSE, XML_SHOW_DSKCMP }, {WSTR_A, WSTR_HREF, NULL, NULL, XML_INFOURI, WSTR_EMPTY, TRUE, XML_A_HREF }, {NULL, WSTR_INFOURI, NULL, NULL, XML_NULL, WSTR_EMPTY, TRUE, XML_INFOURI }, {WSTR_LOGO, WSTR_HREF, WSTR_STYLE, WSTR_IMAGEW, XML_NULL, NULL, TRUE, XML_LOGO_WIDE }, {WSTR_LOGIN, NULL, NULL, NULL, XML_NULL, NULL, FALSE, XML_LOGIN }, {WSTR_USAGE, WSTR_VALUE, WSTR_VALUE, WSTR_SOFTWAREUPDATE, XML_SHOW_SOFTWAREUPDATE, NULL, FALSE, XML_USAGE_SOFTWAREUPDATE}, {NULL, WSTR_SHOW, WSTR_SHOW, WSTR_SOFTWAREUPDATE, XML_NULL, NULL, FALSE, XML_SHOW_SOFTWAREUPDATE }, {WSTR_ITEMSTATE,WSTR_VALUE, NULL, NULL, XML_NULL, WSTR_NORMAL,FALSE, XML_ITEMSTATE }, }; ASSERT(pIXMLElement); // // REVIEW: aAttribTable attribute field only used in debug builds. // ASSERT(attrIndex == aAttribTable[attrIndex].attribute); BSTR bstrRet = NULL; if (NULL == aAttribTable[attrIndex].szAttributeW) { bstrRet = XML_GetGrandChildContent(pIXMLElement, aAttribTable[attrIndex].szChildW); } else if (NULL != aAttribTable[attrIndex].szChildW) { bstrRet = XML_GetChildAttribute(pIXMLElement, aAttribTable[attrIndex].szChildW, aAttribTable[attrIndex].szAttributeW, aAttribTable[attrIndex].szQualifierW, aAttribTable[attrIndex].szQualifierValueW); } else { bstrRet = XML_GetElementAttribute(pIXMLElement, aAttribTable[attrIndex].szAttributeW, aAttribTable[attrIndex].szQualifierW, aAttribTable[attrIndex].szQualifierValueW); } // // If the title or tooltip aren't displayable on the local system use the // URL in their place. // if (bstrRet && (XML_TITLE == attrIndex || XML_TITLE_ATTR == attrIndex || XML_ABSTRACT == attrIndex)) { if (!StrLocallyDisplayable(bstrRet)) { SysFreeString(bstrRet); bstrRet = NULL; } } // // Special cases: // TITLE can also be an attribute. // ABSTRACT can also be an attribute. // LOGO elements don't have to have the TYPE="IMAGE" // SELF is now an attribute SELF_OLD can be removed in the future. // USAGE can also be specified via the SHOW attribute. // USAGE_CHANNEL should also check for SHOW="Channel". // USAGE_DSKCMP should also check for SHOW="DesktopComponent" // if (NULL == bstrRet && XML_NULL != aAttribTable[attrIndex].attrSecondary) { bstrRet = XML_GetAttribute(pIXMLElement, aAttribTable[attrIndex].attrSecondary); } // // Combine URL if required. // if (bstrRet && aAttribTable[attrIndex].fUseBaseURL) { BSTR bstrBaseURL = XML_GetBaseURL(pIXMLElement); if (bstrBaseURL) { BSTR bstrCombinedURL = XML_CombineURL(bstrBaseURL, bstrRet); if (bstrCombinedURL) { SysFreeString(bstrRet); bstrRet = bstrCombinedURL; } SysFreeString(bstrBaseURL); } } /* The following prevent long urls from over-running the pidl buffer */ if (bstrRet && (attrIndex == XML_HREF) && (SysStringLen(bstrRet) > INTERNET_MAX_URL_LENGTH)) { SysReAllocStringLen(&bstrRet, bstrRet, INTERNET_MAX_URL_LENGTH-1); } // // Set default return value. // if (NULL == bstrRet && aAttribTable[attrIndex].szDefaultW) bstrRet = SysAllocString(aAttribTable[attrIndex].szDefaultW); return bstrRet; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_GetFirstChildContent *** // // Description: // Returns a bstr value from first child of the given element. // // Parameters: // [In] pIXMLElement - A pointer to the element. // The caller is responsible for freeing the returned bstr. // // Comments: // If pIElement represents // // Harvey is a Cool Cat<B>this will be ignored</B> // // Then this function will return // // "Harvey is a Cool Cat" // // REVIEW THIS IS A TEMPORARY ROUTINE UNTIL THE XML PARSER SUPPORTS THIS DIRECTLY // //////////////////////////////////////////////////////////////////////////////// BSTR XML_GetFirstChildContent( IXMLElement* pIXMLElement ) { ASSERT(pIXMLElement); BSTR bstrRet = NULL; IXMLElementCollection* pIXMLElementCollection; if ((SUCCEEDED(pIXMLElement->get_children(&pIXMLElementCollection))) && pIXMLElementCollection) { ASSERT(pIXMLElementCollection); LONG nCount; HRESULT hr = pIXMLElementCollection->get_length(&nCount); ASSERT(SUCCEEDED(hr) || (FAILED(hr) && 0 == nCount)); if (nCount >= 1) { IXMLElement* pChildIXMLElement; if (SUCCEEDED(XML_GetElementByIndex(pIXMLElementCollection, 0, &pChildIXMLElement))) { ASSERT(pChildIXMLElement); if (FAILED(pChildIXMLElement->get_text(&bstrRet))) { bstrRet = NULL; } pChildIXMLElement->Release(); } } pIXMLElementCollection->Release(); } return bstrRet; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_GetGrandChildContent *** // // Description: // Returns a bstr value from the requested child of the given element. // // Parameters: // [In] pIXMLElement - A pointer to the element. // [In] szChildW - The name of the child element. // The caller is responsible for freeing the returned bstr. // // Comments: // If pIElement represents // // // Harvey is a Cool Cat // // // Then this function will return // // "Harvey is a Cool Cat" for "TITLE", // //////////////////////////////////////////////////////////////////////////////// BSTR XML_GetGrandChildContent( IXMLElement* pIXMLElement, LPWSTR szChildW ) { ASSERT(pIXMLElement); ASSERT(szChildW); BSTR bstrRet = NULL; IXMLElementCollection* pIXMLElementCollection; if ((SUCCEEDED(pIXMLElement->get_children(&pIXMLElementCollection))) && pIXMLElementCollection) { ASSERT(pIXMLElementCollection); LONG nCount; HRESULT hr = pIXMLElementCollection->get_length(&nCount); ASSERT(SUCCEEDED(hr) || (FAILED(hr) && 0 == nCount)); for (int i = 0; (i < nCount) && !bstrRet; i++) { IXMLElement* pChildIXMLElement; if (SUCCEEDED(XML_GetElementByIndex(pIXMLElementCollection, i, &pChildIXMLElement))) { ASSERT(pChildIXMLElement); BSTR bstrTagName; if (SUCCEEDED(pChildIXMLElement->get_tagName(&bstrTagName)) && bstrTagName) { ASSERT(bstrTagName); if (StrEqlW(bstrTagName, szChildW)) { bstrRet = XML_GetFirstChildContent(pChildIXMLElement); // // If the tag exists, but it is empty, return the empty // string. // if (NULL == bstrRet) bstrRet = SysAllocString(L""); } SysFreeString(bstrTagName); } pChildIXMLElement->Release(); } } pIXMLElementCollection->Release(); } return bstrRet; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_GetChildAttribute *** // // // Description: // Returns a bstr value from the requested child of the given element. // // Parameters: // [In] pIXMLElement - A pointer to the element. // [In] szChildW - The name of the child element. // [In] szAttributeW - The name of the attribute. // [In] szQualifierW - The name of the attribute qualifier. // [In] szQualifierValueW - The required value of the qaulifier. // // Return: // A bstr of the value contained in the child element if it is found. // NULL if the child element or its value isn't found. // // Comments: // This function will return atributes found in the child elements of the // given element. For example: // // If pIElement represents // // // // <Author VALUE="bar"> // <Logo HRREF="url" TYPE="ICON"> // </Channel> // // Then this function will return // // "foo" for "TITLE", "VALUE", "", "" // "bar" for "AUTHOR", "VALUE", "", "" // "url" for "LOGO", "HREF", "TYPE", "ICON" // // NULL when the names have any other values. // // The caller is responsible for freeing the returned bstr. // //////////////////////////////////////////////////////////////////////////////// BSTR XML_GetChildAttribute( IXMLElement* pIXMLElement, LPWSTR szChildW, LPWSTR szAttributeW, LPWSTR szQualifierW, LPWSTR szQualifierValueW ) { ASSERT(pIXMLElement); ASSERT(szChildW); ASSERT(szAttributeW); BSTR bstrRet = NULL; IXMLElementCollection* pIXMLElementCollection; if ((SUCCEEDED(pIXMLElement->get_children(&pIXMLElementCollection))) && pIXMLElementCollection) { ASSERT(pIXMLElementCollection); LONG nCount; // // REVIEW: hr only used in debug builds. // HRESULT hr = pIXMLElementCollection->get_length(&nCount); ASSERT(SUCCEEDED(hr) || (FAILED(hr) && 0 == nCount)); for (int i = 0; (i < nCount) && !bstrRet; i++) { IXMLElement* pChildIXMLElement; if (SUCCEEDED(XML_GetElementByIndex(pIXMLElementCollection, i, &pChildIXMLElement))) { ASSERT(pChildIXMLElement); BSTR bstrTagName; if (SUCCEEDED(pChildIXMLElement->get_tagName(&bstrTagName)) && bstrTagName) { ASSERT(bstrTagName); if (StrEqlW(bstrTagName, szChildW)) { bstrRet = XML_GetElementAttribute(pChildIXMLElement, szAttributeW, szQualifierW, szQualifierValueW); } SysFreeString(bstrTagName); } pChildIXMLElement->Release(); } } pIXMLElementCollection->Release(); } return bstrRet; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_GetElementAttribute *** // // // Description: // Returns the bstr value of of the requested attribute if it is found. // // Parameters: // [In] pIXMLElement - The element that contains the attribute. // [In] szAttributeW - The name of the attribute. // [In] szQualifierW - The type qualifier for the atribute. // [In] szQualifierValueW - The required value of the qaulifier. // // Return: // A bstr containig the attributes value if it was found. // NULL if the attribute wasn't found. // // Comments: // The function will return attributes found inside of tags. For // example: // // If pIXMLElement represents // // <Channel HREF="foo" Cloneable="NO"> // <USAGE VALUE="Channel"> // <USAGE VALUE="Screen Saver"> // // Then this function will return // // "foo" for "HREF", "", "" // "NO" for "Cloneable", "", "" // "CHANNEL" for "VALUE", "VALUE", "CHANNEL" // NULL for "VALUE", "VALUE", "NONE" // "foo" for "HREF", "CLONEABLE", "NO" // // The caller is responsible for freeing the returned bstr. // //////////////////////////////////////////////////////////////////////////////// BSTR XML_GetElementAttribute( IXMLElement* pIXMLElement, LPWSTR szAttributeW, LPWSTR szQualifierW, LPWSTR szQualifierValueW ) { ASSERT(pIXMLElement); ASSERT(szAttributeW); ASSERT((NULL == szQualifierW && NULL == szQualifierValueW) || (szQualifierW && szQualifierValueW)); BSTR bstrRet = NULL; VARIANT var; VariantInit(&var); if (NULL == szQualifierW) { if (SUCCEEDED(pIXMLElement->getAttribute(szAttributeW, &var))) { ASSERT(var.vt == VT_BSTR || NULL == var.bstrVal); bstrRet = var.bstrVal; } } else { if (SUCCEEDED(pIXMLElement->getAttribute(szQualifierW, &var))) { ASSERT(var.vt == VT_BSTR || NULL == var.bstrVal); if(var.bstrVal) { if (0 == StrCmpIW(var.bstrVal, szQualifierValueW)) { bstrRet = XML_GetElementAttribute(pIXMLElement, szAttributeW, NULL, NULL); } } VariantClear(&var); } } return bstrRet; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_GetScreenSaverURL *** // // // Description: // Returns the screen saver URL of the first screen saver component in the channel. // // Parameters: // [In] pXMLDocument - An XML document // [Out] pbstrSSURL - The pointer that receives the screen saver URL. // // Return: // S_OK if the screen saver URL was returned. // E_FAIL if the screen saver URL couldn't be returned. // // Comments: // This function gets the first screen saver element and then looks // for the first top-level ITEM with a usage of ScreenSaver. // //////////////////////////////////////////////////////////////////////////////// HRESULT XML_GetScreenSaverURL( IXMLDocument * pXMLDocument, BSTR * pbstrSSURL) { HRESULT hr; ASSERT(pXMLDocument); ASSERT(pbstrSSURL); IXMLElement* pIXMLElement; LONG lDontCare; hr = XML_GetFirstChannelElement(pXMLDocument, &pIXMLElement, &lDontCare); if (SUCCEEDED(hr)) { IXMLElement* pSSElement; ASSERT(pIXMLElement); hr = XML_GetScreenSaverElement(pIXMLElement, &pSSElement); if (SUCCEEDED(hr)) { ASSERT(pSSElement); *pbstrSSURL = XML_GetAttribute(pSSElement, XML_HREF); hr = *pbstrSSURL ? S_OK : E_FAIL; pSSElement->Release(); } pIXMLElement->Release(); } return hr; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_GetScreenSaverElement *** // // // Description: // Returns the IXMLElement of the first screen saver component in the channel. // // Parameters: // [In] pXMLElemet - An XML element // [Out] ppIXMLElement - The pointer that receives the screen saver element. // // Return: // S_OK if the first screen saver element was returned. // E_FAIL if the element couldn't be returned. // // Comments: // This function gets the first screen saver element and then looks // for the first top-level ITEM with a usage of ScreenSaver. // //////////////////////////////////////////////////////////////////////////////// HRESULT XML_GetScreenSaverElement( IXMLElement * pXMLElement, IXMLElement ** ppScreenSaverElement) { ASSERT(pXMLElement); ASSERT(ppScreenSaverElement); IXMLElementCollection * pIXMLElementCollection; HRESULT hr; hr = pXMLElement->get_children(&pIXMLElementCollection); if (SUCCEEDED(hr) && pIXMLElementCollection) { LONG nCount; hr = pIXMLElementCollection->get_length(&nCount); ASSERT(SUCCEEDED(hr) || (FAILED(hr) && 0 == nCount)); hr = E_FAIL; BOOL bScreenSaver = FALSE; for (int i = 0; (i < nCount) && !bScreenSaver; i++) { IXMLElement * pIXMLElement; HRESULT hr2 = XML_GetElementByIndex(pIXMLElementCollection, i, &pIXMLElement); if (SUCCEEDED(hr2)) { ASSERT(pIXMLElement != NULL); if (bScreenSaver = XML_IsScreenSaver(pIXMLElement)) { pIXMLElement->AddRef(); *ppScreenSaverElement = pIXMLElement; hr = S_OK; } pIXMLElement->Release(); } hr = FAILED(hr2) ? hr2 : hr; } pIXMLElementCollection->Release(); } else hr = E_FAIL; ASSERT((SUCCEEDED(hr) && *ppScreenSaverElement) || FAILED(hr)); return hr; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_GetSubscriptionInfo *** // // // Description: // Fills a structure with the subscription info for the given element. // // Parameters: // [In] pIXMLElement - An xml element. The element doesn't have to be a // subscription element. // [Out] psi - The subscription info structure used by the // subscription manager. // // Return: // S_OK if any information was obtained. // // Comments: // This function uses a webcheck API that fills a task trigger with // subscription information. // // This function assumes that the psi->pTrigger points to a TASK_TRIGGER. // //////////////////////////////////////////////////////////////////////////////// HRESULT XML_GetSubscriptionInfo( IXMLElement* pIXMLElement, SUBSCRIPTIONINFO* psi ) { ASSERT(pIXMLElement); ASSERT(psi); ASSERT(psi->pTrigger); HRESULT hr = E_FAIL; #ifndef UNIX HINSTANCE hinst = LoadLibrary(TEXT("webcheck.dll")); if (hinst) { typedef (*PFTRIGGERFUNCTION)(IXMLElement* pIXMLElement, TASK_TRIGGER* ptt); PFTRIGGERFUNCTION XMLSheduleElementToTaskTrigger; XMLSheduleElementToTaskTrigger = (PFTRIGGERFUNCTION) GetProcAddress(hinst, "XMLScheduleElementToTaskTrigger"); if (XMLSheduleElementToTaskTrigger) { ((TASK_TRIGGER*)(psi->pTrigger))->cbTriggerSize = sizeof(TASK_TRIGGER); hr = XMLSheduleElementToTaskTrigger(pIXMLElement, (TASK_TRIGGER*)psi->pTrigger); if (FAILED(hr)) psi->pTrigger = NULL; } FreeLibrary(hinst); } // See if there is a screen saver available. IXMLElement * pScreenSaverElement; if (SUCCEEDED(XML_GetScreenSaverElement( pIXMLElement, &pScreenSaverElement))) { psi->fUpdateFlags |= SUBSINFO_CHANNELFLAGS; psi->fChannelFlags |= CHANNEL_AGENT_PRECACHE_SCRNSAVER; pScreenSaverElement->Release(); } BSTR bstrLogin = XML_GetAttribute(pIXMLElement, XML_LOGIN); if (bstrLogin) { psi->bNeedPassword = TRUE; psi->fUpdateFlags |= SUBSINFO_NEEDPASSWORD; //this member is now valid SysFreeString(bstrLogin); } #endif /* !UNIX */ return hr; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_GetBaseURL *** // // // Description: // Returns the base url for the given collection. // // Parameters: // [In] pIXMLElement - A pointer to an XML element. // // Return: // A bstr containing the base URL if there is one. // NULL if ther isn't a base URL. // // Comments: // If the current element has a BASE attribute return this attributes value. // Else return the BASE attribute of its parent. // //////////////////////////////////////////////////////////////////////////////// BSTR XML_GetBaseURL( IXMLElement* pIXMLElement ) { ASSERT(pIXMLElement); BSTR bstrRet = XML_GetAttribute(pIXMLElement, XML_BASE); if (NULL == bstrRet) { IXMLElement* pParentIXMLElement; if (SUCCEEDED(pIXMLElement->get_parent(&pParentIXMLElement)) && pParentIXMLElement) { ASSERT(pParentIXMLElement); bstrRet = XML_GetBaseURL(pParentIXMLElement); pParentIXMLElement->Release(); } } return bstrRet; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_CombineURL *** // // // Description: // Combine the given URL with the base URL. // // Parameters: // [In] bstrBaseURL - The base URL. // [In] bstrRelURL - The relative URL. // // Return: // A combination of the base and relative URL. // // Comments: // // //////////////////////////////////////////////////////////////////////////////// BSTR XML_CombineURL( BSTR bstrBaseURL, BSTR bstrRelURL ) { ASSERT(bstrBaseURL); ASSERT(bstrRelURL); BSTR bstrRet = NULL; WCHAR wszCombinedURL[INTERNET_MAX_URL_LENGTH]; DWORD cch = ARRAYSIZE(wszCombinedURL); if (InternetCombineUrlW(bstrBaseURL, bstrRelURL, wszCombinedURL, &cch, 0)) bstrRet = SysAllocString(wszCombinedURL); return bstrRet; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_IsCdfDisplayable *** // // // Description: // Determines if the given item should be displayed in the cdf view. // // Parameters: // [In] pIXMLElement - A pointer to the IXMLElement interface of an object. // // Return: // TRUE if the object should be displayed. // FALSE otherwise. // // Comments: // aCDFTypes contains the tag names of XML items that the cdf shell // shell extension displays. // //////////////////////////////////////////////////////////////////////////////// BOOL XML_IsCdfDisplayable( IXMLElement* pIXMLElement ) { #define KEYWORDS (sizeof(aCDFTypes) / sizeof(aCDFTypes[0])) static const LPWSTR aCDFTypes[] = { WSTR_ITEM, WSTR_CHANNEL, WSTR_SOFTDIST }; ASSERT(pIXMLElement); BOOL bRet = FALSE; BSTR pStr; HRESULT hr = pIXMLElement->get_tagName(&pStr); if (SUCCEEDED(hr) && pStr) { ASSERT(pStr); for(int i = 0; (i < KEYWORDS) && !bRet; i++) bRet = StrEqlW(pStr, aCDFTypes[i]); if (bRet) bRet = XML_IsUsageChannel(pIXMLElement); // // Special processing. // if (bRet && StrEqlW(pStr, WSTR_SOFTDIST)) bRet = XML_IsSoftDistDisplayable(pIXMLElement); SysFreeString(pStr); } return bRet; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_IsSoftDistDisplayable *** // // // Description: // Determins if the given software distribution element should be displayed. // // Parameters: // [In] pIXMLElement - Pointer to the software distribution xml element. // // Return: // TRUE if the element should be displayed. // FALSE if the element shouldn't be displayed. // // Comments: // This function asks the software disribution COM object if this software // distribution tag should be displayed on this users machine. // //////////////////////////////////////////////////////////////////////////////// BOOL XML_IsSoftDistDisplayable( IXMLElement* pIXMLElement ) { ASSERT(pIXMLElement); ISoftDistExt* pISoftDistExt; HRESULT hr = CoCreateInstance(CLSID_SoftDistExt, NULL, CLSCTX_INPROC_SERVER, IID_ISoftDistExt, (void**)&pISoftDistExt); if (SUCCEEDED(hr)) { ASSERT(pISoftDistExt); hr = pISoftDistExt->ProcessSoftDist(NULL, pIXMLElement, 0); pISoftDistExt->Release(); } return SUCCEEDED(hr) ? TRUE : FALSE; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_IsUsageChannel *** // // // Description: // Determines if this item should be displayed in channel view based on its // usage tag. // // Parameters: // [In] pIXMLelement - A pointer to the element. // // Return: // TRUE if the item should be displayed in the channel view. // FALSE otherwise. // // Comments: // If an element doesn't have a USAGE tag then it gets displayed. If an // element has any numberf of usage tags one of them must have a value of // CHANNEL or will not get displayed. // //////////////////////////////////////////////////////////////////////////////// BOOL XML_IsUsageChannel( IXMLElement* pIXMLElement ) { ASSERT(pIXMLElement); BOOL bRet; // // First check if there are any USAGE elements. // BSTR bstrUsage = XML_GetAttribute(pIXMLElement, XML_USAGE); if (bstrUsage) { // // See if USAGE is CHANNEL. // if (StrEqlW(bstrUsage, WSTR_CHANNEL)) { bRet = TRUE; } else { // // Check if there are any other USAGE tags with value CHANNEL. // BSTR bstrChannel = XML_GetAttribute(pIXMLElement, XML_USAGE_CHANNEL); if (bstrChannel) { SysFreeString(bstrChannel); bRet = TRUE; } else { bRet = FALSE; } } SysFreeString(bstrUsage); } else { bRet = TRUE; // No USAGE tag defaults channel usage. } return bRet; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_IsChannel *** // // // Description: // Determines if the given XML item is a channel. // // Parameters: // [In] pIXMLElement - A pointer to the IXMLElement interface of an object. // // Return: // TRUE if the object is a channel. // FALSE otherwise. // // Comments: // // //////////////////////////////////////////////////////////////////////////////// BOOL XML_IsChannel( IXMLElement* pIXMLElement ) { ASSERT(pIXMLElement); BOOL bRet = FALSE; BSTR pStr; HRESULT hr = pIXMLElement->get_tagName(&pStr); if (SUCCEEDED(hr) && pStr) { ASSERT(pStr); bRet = StrEqlW(pStr, WSTR_CHANNEL); SysFreeString(pStr); } return bRet; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_IsDesktopComponent *** // // // Description: // Determines if the given XML item is a desktop component. // // Parameters: // [In] pIXMLElement - A pointer to the IXMLElement interface of an object. // // Return: // TRUE if the object is a desktop component. // FALSE otherwise. // // Comments: // // //////////////////////////////////////////////////////////////////////////////// BOOL XML_IsDesktopComponent( IXMLElement* pIXMLElement ) { ASSERT(pIXMLElement); BOOL bRet; BSTR bstr = XML_GetAttribute(pIXMLElement, XML_USAGE_DSKCMP); if (bstr) { SysFreeString(bstr); bRet = TRUE; } else { bRet = FALSE; } return bRet; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_IsScreenSaver *** // // // Description: // Determines if the given XML item is a screen saver. // // Parameters: // [In] pIXMLElement - A pointer to the IXMLElement interface of an object. // // Return: // TRUE if the object is a screen saver // FALSE otherwise. // // Comments: // // //////////////////////////////////////////////////////////////////////////////// BOOL XML_IsScreenSaver( IXMLElement* pIXMLElement ) { ASSERT(pIXMLElement); BOOL bRet; BSTR bstrUsage = XML_GetAttribute(pIXMLElement, XML_USAGE); if (bstrUsage) { bRet = ( (StrCmpIW(bstrUsage, WSTR_SCRNSAVE) == 0) || (StrCmpIW(bstrUsage, WSTR_SMARTSCRN) == 0) ); SysFreeString(bstrUsage); } else { bRet = FALSE; } return bRet; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_IsDesktopComponentUsage *** // // // Description: // Determines if the given XML item is a desktop component usage element. // // Parameters: // [In] pIXMLElement - A pointer to the IXMLElement interface of an object. // // Return: // TRUE if the object is a desktop component usage element. // FALSE otherwise. // // Comments: // // //////////////////////////////////////////////////////////////////////////////// BOOL XML_IsDesktopComponentUsage( IXMLElement* pIXMLElement ) { ASSERT(pIXMLElement); BOOL bRet = FALSE; BSTR bstrName; if (SUCCEEDED(pIXMLElement->get_tagName(&bstrName)) && bstrName) { ASSERT(bstrName); if (StrEqlW(bstrName, WSTR_USAGE)) { BSTR bstrValue = XML_GetElementAttribute(pIXMLElement, WSTR_VALUE, NULL, NULL); if (bstrValue) { bRet = (0 == StrCmpIW(bstrValue, WSTR_DSKCMP)); SysFreeString(bstrValue); } } SysFreeString(bstrName); } return bRet; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_IsFolder *** // // // Description: // Determines if the given item is a folder. // // Parameters: // [In] pIXMLElement - A pointer to the IXMLElement interface of an object. // // Return: // TRUE if the object contains other cdf displayable objects. // FALSE otherwise. // // Comments: // An item is a folder if at least one of its children is displayable as a // cdf item. // //////////////////////////////////////////////////////////////////////////////// BOOL XML_IsFolder( IXMLElement* pIXMLElement ) { ASSERT(pIXMLElement); BOOL bRet = FALSE; IXMLElementCollection* pIXMLElementCollection; HRESULT hr = pIXMLElement->get_children(&pIXMLElementCollection); if (SUCCEEDED(hr) && pIXMLElementCollection) { ASSERT(pIXMLElementCollection); LONG nCount; hr = pIXMLElementCollection->get_length(&nCount); ASSERT(SUCCEEDED(hr) || (FAILED(hr) && 0 == nCount)); for (int i = 0; (i < nCount) && !bRet; i++) { IXMLElement* pIXMLElementTemp; hr = XML_GetElementByIndex(pIXMLElementCollection, i, &pIXMLElementTemp); if (SUCCEEDED(hr)) { ASSERT(pIXMLElementTemp); if (XML_IsCdfDisplayable(pIXMLElementTemp)) bRet = TRUE; pIXMLElementTemp->Release(); } } pIXMLElementCollection->Release(); } return bRet; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_ContainsFolder *** // // // Description: // Determines if there are any cdf folders in the given collection. // // Parameters: // [In] pIXMLElementCollection - A pointer to the collection. // // Return: // TRUE if the collection contains a cf folder. // FALSE otherwise. // // Comments: // // //////////////////////////////////////////////////////////////////////////////// BOOL XML_ContainsFolder( IXMLElementCollection* pIXMLElementCollection ) { ASSERT(pIXMLElementCollection); BOOL bContainsFolder = FALSE; LONG nCount; HRESULT hr = pIXMLElementCollection->get_length(&nCount); ASSERT(SUCCEEDED(hr) || (FAILED(hr) && 0 == nCount)); for (int i = 0; (i < nCount) && !bContainsFolder; i++) { IXMLElement* pIXMLElement; hr = XML_GetElementByIndex(pIXMLElementCollection, i, &pIXMLElement); if (SUCCEEDED(hr)) { ASSERT(pIXMLElement); bContainsFolder = XML_IsFolder(pIXMLElement); pIXMLElement->Release(); } } return bContainsFolder; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_ChildContainsFolder *** // // // Description: // // // Parameters: // // // Return: // // // Comments: // // //////////////////////////////////////////////////////////////////////////////// BOOL XML_ChildContainsFolder( IXMLElementCollection *pIXMLElementCollectionParent, ULONG nIndexChild ) { BOOL bRet = FALSE; IXMLElement* pIXMLElement; HRESULT hr = XML_GetElementByIndex(pIXMLElementCollectionParent, nIndexChild, &pIXMLElement); if (SUCCEEDED(hr)) { ASSERT(pIXMLElement); IXMLElementCollection* pIXMLElementCollection; hr = pIXMLElement->get_children(&pIXMLElementCollection); if (SUCCEEDED(hr) && pIXMLElementCollection) { ASSERT(pIXMLElementCollection); bRet = XML_ContainsFolder(pIXMLElementCollection); pIXMLElementCollection->Release(); } pIXMLElement->Release(); } return bRet; } #ifdef DEBUG //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_IsCdfidlMemberOf *** // // // Description: // Checks if the cdf item id list is associated with a member of the given // element collection. // // Parameters: // [In] pIXMLElementCollection - The element collection to check. // [In] pcdfidl - A pointer to cdf item id list // // Return: // TRUE if the given id list can be associated with an elemnt of the given // collection. // FALSE otherwise. // // Comments: // This function checks if the last id in the list could have been // generated from its corresponding element in the element collection. // //////////////////////////////////////////////////////////////////////////////// BOOL XML_IsCdfidlMemberOf( IXMLElementCollection* pIXMLElementCollection, PCDFITEMIDLIST pcdfidl ) { ASSERT(CDFIDL_IsValid(pcdfidl)); BOOL bRet = FALSE; // // pIXMLElementCollection is NULL when a Folder hasn't been initialized. // It isn't always neccessary to parse the cdf to get pidl info from // the pidl. pIXMLElement collection will be NULL in low memory situations // also. Don't return FALSE for these cases. Also check for special // pidls that aren't in element collections. // if (pIXMLElementCollection && CDFIDL_GetIndexId(&pcdfidl->mkid) != INDEX_CHANNEL_LINK) { IXMLElement* pIXMLElement; HRESULT hr = XML_GetElementByIndex(pIXMLElementCollection, CDFIDL_GetIndexId(&pcdfidl->mkid), &pIXMLElement); if (SUCCEEDED(hr)) { ASSERT(pIXMLElement); PCDFITEMIDLIST pcdfidlElement; pcdfidlElement = CDFIDL_CreateFromXMLElement(pIXMLElement, CDFIDL_GetIndexId(&pcdfidl->mkid)); if (pcdfidlElement) { ASSERT(CDFIDL_IsValid(pcdfidlElement)); bRet = (0 == CDFIDL_CompareId(&pcdfidl->mkid, &pcdfidlElement->mkid)); CDFIDL_Free(pcdfidlElement); } pIXMLElement->Release(); } } else { bRet = TRUE; } return bRet; } #endif //DEBUG //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // // *** XML_IsStrEqualW *** // // // Description: // Determines if two WCHAR strings are equal. // // Parameters: // [In] p1 - The first string to compare. // [In] p2 - The second string to compare. // // Return: // TRUE if the strings are equal. // FALSE otherwise. // // Comments: // lstrcmpW doesn't work on W95 so this function has its own strcmp logic. // //////////////////////////////////////////////////////////////////////////////// #if 0 inline BOOL XML_IsStrEqualW( LPWSTR p1, LPWSTR p2 ) { ASSERT(p1); ASSERT(p2); while ((*p1 == *p2) && *p1 && *p2) { p1++; p2++; } return (*p1 == *p2); } #endif