//======================================================================= // // Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved. // // File: iuxml.cpp // // Description: // // Implementation for the CIUXml class // //======================================================================= #include "iuengine.h" #include "iuxml.h" #include #include #include #include #include #include "schemakeys.h" #include "schemamisc.h" #include "v3applog.h" #define QuitIfNull(p) {if (NULL == p) {hr = E_INVALIDARG; LOG_ErrorMsg(hr); return hr;}} #define QuitIfFail(x) {hr = x; if (FAILED(hr)) goto CleanUp;} #define ReturnIfFail(x) {hr = x; if (FAILED(hr)) {LOG_ErrorMsg(hr); return hr;}} #define SkipIfFail(x) {hr = x; if (FAILED(hr)) {hr = S_FALSE; continue;}} const TCHAR IDENT_IUSCHEMA[] = _T("IUSchema"); const TCHAR IDENT_IUSCHEMA_SYSTEMSPEC[] = _T("SystemSpecSchema"); const TCHAR IDENT_IUSCHEMA_ITEMS[] = _T("ResultSchema"); const WCHAR CORP_PLATFORM_DIR_NT4[] = L"x86WinNT4"; const WCHAR CORP_PLATFORM_DIR_NT5[] = L"x86win2k"; const WCHAR CORP_PLATFORM_DIR_W98[] = L"x86Win98"; const WCHAR CORP_PLATFORM_DIR_W95[] = L"x86Win95"; const WCHAR CORP_PLATFORM_DIR_WINME[] = L"x86WinME"; const WCHAR CORP_PLATFORM_DIR_X86WHI[] = L"x86WinXP"; const WCHAR CORP_PLATFROM_DIR_IA64WHI[] = L"ia64WinXP"; // Initial length of the node array "m_ppNodeArray" const DWORD MAX_NODES = 16; // Initial length of the node array "m_ppNodeListArray" const DWORD MAX_NODELISTS = 16; // Bitmap of existence of all possible system info classes const DWORD COMPUTERSYSTEM = 0x00000001; const DWORD REGKEYS = 0x00000010; const DWORD PLATFORM = 0x00000100; const DWORD LOCALE = 0x00001000; const DWORD DEVICES = 0x00010000; // The following are constants used for V3 history migration: // // Log line types #define LOG_V2 "V2" // line format for items migrated from V2 #define LOG_V3CAT "V3CAT" // V3 Beta format (version 1) #define LOG_V3_2 "V3_2" // V3 log line format (version 2) #define LOG_PSS "PSS" // Entry for PSS // LOG_V2 format // V2|DATE|TIME|LOGSTRING| // // LOG_V3CAT format // V3CAT|PUID|OPERATION|TITLE|VERSION|DATESTRING|TIMESTRING|RECTYPE|RESULT|ERRORCODE|ERRORSTRING| // // LOG_V3_2 format // V3_2|PUID|OPERATION|TITLE|VERSION|TIMESTAMP|RECTYPE|RESULT|ERRORCODE|ERRORSTRING| // // LOG_PSS format // PSS|PUID|OPERATION|TITLE|VERSION|TIMESTAMP|RECTYPE|RESULT|ERRORCODE|ERRORSTRING| // // operation type #define LOG_INSTALL "INSTALL" // result #define LOG_SUCCESS "SUCCESS" #define LOG_FAIL "FAIL" #define LOG_STARTED "STARTED" // started but reboot was required: exclusive items only const WCHAR C_V3_CLIENTINFO[] = L"WU_V3"; ///////////////////////////////////////////////////////////////////////////// // CIUXml ///////////////////////////////////////////////////////////////////////////// // Constructor // ///////////////////////////////////////////////////////////////////////////// CIUXml::CIUXml() : m_dwSizeNodeArray(MAX_NODES), m_dwSizeNodeListArray(MAX_NODELISTS), m_ppNodeArray(NULL), m_ppNodeListArray(NULL) { m_hHeap = GetProcessHeap(); } ///////////////////////////////////////////////////////////////////////////// // Destructor // ///////////////////////////////////////////////////////////////////////////// CIUXml::~CIUXml() { DWORD dwIndex; if (NULL != m_ppNodeArray) { for (dwIndex = 0; dwIndex < m_dwSizeNodeArray; dwIndex++) { SafeReleaseNULL(m_ppNodeArray[dwIndex]); } HeapFree(m_hHeap, 0, m_ppNodeArray); m_ppNodeArray = NULL; } if (NULL != m_ppNodeListArray) { for (dwIndex = 0; dwIndex < m_dwSizeNodeListArray; dwIndex++) { SafeReleaseNULL(m_ppNodeListArray[dwIndex]); } HeapFree(m_hHeap, 0, m_ppNodeListArray); m_ppNodeListArray = NULL; } } ///////////////////////////////////////////////////////////////////////////// // SafeCloseHandleNode() // // User can explicitly can this function to release a node for reuse when // writing a xml doc. ///////////////////////////////////////////////////////////////////////////// void CIUXml::SafeCloseHandleNode(HANDLE_NODE& hNode) { if (HANDLE_NODE_INVALID != hNode) { SafeReleaseNULL(m_ppNodeArray[hNode]); hNode = HANDLE_NODE_INVALID; } } ///////////////////////////////////////////////////////////////////////////// // SafeFindCloseHandle() // // User can explicitly can this function to release a nodelist for reuse when // reading a xml doc. ///////////////////////////////////////////////////////////////////////////// void CIUXml::SafeFindCloseHandle(HANDLE_NODELIST& hNodeList) { if (HANDLE_NODELIST_INVALID != hNodeList) { SafeReleaseNULL(m_ppNodeListArray[hNodeList]); hNodeList = HANDLE_NODELIST_INVALID; } } ///////////////////////////////////////////////////////////////////////////// // InitNodeArray() // // Allocate or re-allocate memory for the node array "m_ppNodeArray" ///////////////////////////////////////////////////////////////////////////// HRESULT CIUXml::InitNodeArray(BOOL fRealloc /*= FALSE*/) { if (fRealloc) // re-allocation { IXMLDOMNode** ppNodeArrayTemp = (IXMLDOMNode**)HeapReAlloc(m_hHeap, HEAP_ZERO_MEMORY, m_ppNodeArray, m_dwSizeNodeArray * sizeof(IXMLDOMNode*)); if (NULL == ppNodeArrayTemp) { return E_OUTOFMEMORY; } else { m_ppNodeArray = ppNodeArrayTemp; } } else // initial allocation { m_ppNodeArray = (IXMLDOMNode**)HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, m_dwSizeNodeArray * sizeof(IXMLDOMNode*)); if (NULL == m_ppNodeArray) { return E_OUTOFMEMORY; } } return S_OK; } ///////////////////////////////////////////////////////////////////////////// // InitNodeListArray() // // Allocate or re-allocate memory for the nodelist array "m_ppNodeListArray" ///////////////////////////////////////////////////////////////////////////// HRESULT CIUXml::InitNodeListArray(BOOL fRealloc /*= FALSE*/) { if (fRealloc) // re-allocation { IXMLDOMNodeList** ppNodeListArrayTemp = (IXMLDOMNodeList**)HeapReAlloc(m_hHeap, HEAP_ZERO_MEMORY, m_ppNodeListArray, m_dwSizeNodeListArray * sizeof(IXMLDOMNodeList*)); if (NULL == ppNodeListArrayTemp) { return E_OUTOFMEMORY; } else { m_ppNodeListArray = ppNodeListArrayTemp; } } else // initial allocation { m_ppNodeListArray = (IXMLDOMNodeList**)HeapAlloc(m_hHeap, HEAP_ZERO_MEMORY, m_dwSizeNodeListArray * sizeof(IXMLDOMNodeList*)); if (NULL == m_ppNodeListArray) { return E_OUTOFMEMORY; } } return S_OK; } ///////////////////////////////////////////////////////////////////////////// // GetNodeHandle() // // Look for the first un-used node from the "m_ppNodeArray" array, // including the memory allocation, if needed. ///////////////////////////////////////////////////////////////////////////// HANDLE_NODE CIUXml::GetNodeHandle() { HRESULT hr; DWORD dwIndex; // // allocate memory for "m_ppNodeArray" array if this is the first time using it // if (NULL == m_ppNodeArray) { QuitIfFail(InitNodeArray()); return 0; // return the first element of the array } // // find the next node to use, or, if any node was used but closed, reuse it // for (dwIndex = 0; dwIndex < m_dwSizeNodeArray; dwIndex++) { if (NULL == m_ppNodeArray[dwIndex]) { return dwIndex; } } // // all pre-allocated nodes are used up, so re-allocate longer array // m_dwSizeNodeArray += m_dwSizeNodeArray; // double the size QuitIfFail(InitNodeArray(TRUE)); // re-allocation return dwIndex; CleanUp: return HANDLE_NODE_INVALID; } ///////////////////////////////////////////////////////////////////////////// // GetNodeListHandle() // // Look for the first un-used nodelist from the "m_ppNodeListArray" array, // including the memory allocation, if needed. ///////////////////////////////////////////////////////////////////////////// HANDLE_NODELIST CIUXml::GetNodeListHandle() { HRESULT hr; DWORD dwIndex; // // allocate memory for "m_ppNodeListArray" array if this is the first time using it // if (NULL == m_ppNodeListArray) { QuitIfFail(InitNodeListArray()); return 0; // return the first element of the array } // // find the next nodelist to use, or, if any nodelist was used but closed, reuse it // for (dwIndex = 0; dwIndex < m_dwSizeNodeListArray; dwIndex++) { if (NULL == m_ppNodeListArray[dwIndex]) { return dwIndex; } } // // all pre-allocated nodelists are used up, so re-allocate longer array // m_dwSizeNodeListArray += m_dwSizeNodeListArray; // double the size QuitIfFail(InitNodeListArray(TRUE)); // re-allocation return dwIndex; CleanUp: return HANDLE_NODELIST_INVALID; } ///////////////////////////////////////////////////////////////////////////// // GetDOMNodebyHandle() // // Retrieve the xml node with the given index of m_ppNodeArray ///////////////////////////////////////////////////////////////////////////// IXMLDOMNode* CIUXml::GetDOMNodebyHandle(HANDLE_NODE hNode) { if (NULL != m_ppNodeArray && HANDLE_NODE_INVALID != hNode) { return m_ppNodeArray[hNode]; } return NULL; } ///////////////////////////////////////////////////////////////////////////// // FindFirstDOMNode() // // Retrieve the first xml node with the given tag name under the given parent node ///////////////////////////////////////////////////////////////////////////// HANDLE_NODELIST CIUXml::FindFirstDOMNode(IXMLDOMNode* pParentNode, BSTR bstrName, IXMLDOMNode** ppNode) { USES_IU_CONVERSION; HRESULT hr = S_OK; if (NULL == pParentNode) { hr = E_INVALIDARG; return HANDLE_NODELIST_INVALID; } DWORD dwIndex; dwIndex = GetNodeListHandle(); if (HANDLE_NODELIST_INVALID != dwIndex) { LONG lLength; QuitIfFail(pParentNode->selectNodes(bstrName, &m_ppNodeListArray[dwIndex])); if (NULL == m_ppNodeListArray[dwIndex]) { goto CleanUp; } QuitIfFail(m_ppNodeListArray[dwIndex]->get_length(&lLength)); if (lLength <= 0) { goto CleanUp; } QuitIfFail(m_ppNodeListArray[dwIndex]->nextNode(ppNode)); if (NULL == *ppNode) { goto CleanUp; } return dwIndex; } CleanUp: *ppNode = NULL; return HANDLE_NODELIST_INVALID; } ///////////////////////////////////////////////////////////////////////////// // FindFirstDOMNode() // // Retrieve the handle of first xml node with the given tag name under the given parent node ///////////////////////////////////////////////////////////////////////////// HANDLE_NODELIST CIUXml::FindFirstDOMNode(IXMLDOMNode* pParentNode, BSTR bstrName, HANDLE_NODE* phNode) { USES_IU_CONVERSION; HRESULT hr = S_OK; if (NULL == pParentNode) { hr = E_INVALIDARG; return HANDLE_NODELIST_INVALID; } DWORD dwIndex1, dwIndex2; dwIndex1 = GetNodeListHandle(); if (HANDLE_NODELIST_INVALID != dwIndex1) { LONG lLength; QuitIfFail(pParentNode->selectNodes(bstrName, &m_ppNodeListArray[dwIndex1])); if (NULL == m_ppNodeListArray[dwIndex1]) { goto CleanUp; } QuitIfFail(m_ppNodeListArray[dwIndex1]->get_length(&lLength)); if (lLength <= 0) { goto CleanUp; } dwIndex2 = GetNodeHandle(); if (HANDLE_NODE_INVALID != dwIndex2) { QuitIfFail(m_ppNodeListArray[dwIndex1]->nextNode(&m_ppNodeArray[dwIndex2])); if (NULL == m_ppNodeArray[dwIndex2]) { goto CleanUp; } *phNode = dwIndex2; return dwIndex1; } } CleanUp: *phNode = HANDLE_NODE_INVALID; return HANDLE_NODELIST_INVALID; } ///////////////////////////////////////////////////////////////////////////// // FindFirstDOMNode() // // Retrieve the first xml node with the given tag name in the given xml doc ///////////////////////////////////////////////////////////////////////////// HANDLE_NODELIST CIUXml::FindFirstDOMNode(IXMLDOMDocument* pDoc, BSTR bstrName, IXMLDOMNode** ppNode) { USES_IU_CONVERSION; HRESULT hr = S_OK; if (NULL == pDoc) { hr = E_INVALIDARG; return HANDLE_NODELIST_INVALID; } DWORD dwIndex; IXMLDOMNode *pParentNode = NULL; dwIndex = GetNodeListHandle(); if (HANDLE_NODELIST_INVALID != dwIndex) { LONG lLength; QuitIfFail(pDoc->QueryInterface(IID_IXMLDOMNode, (void**)&pParentNode)); QuitIfFail(pParentNode->selectNodes(bstrName, &m_ppNodeListArray[dwIndex])); if (NULL == m_ppNodeListArray[dwIndex]) { goto CleanUp; } QuitIfFail(m_ppNodeListArray[dwIndex]->get_length(&lLength)); if (lLength <= 0) { goto CleanUp; } QuitIfFail(m_ppNodeListArray[dwIndex]->nextNode(ppNode)); if (NULL == *ppNode) { goto CleanUp; } SafeReleaseNULL(pParentNode); return dwIndex; } CleanUp: *ppNode = NULL; SafeReleaseNULL(pParentNode); return HANDLE_NODELIST_INVALID; } ///////////////////////////////////////////////////////////////////////////// // FindFirstDOMNode() // // Retrieve the handle of first xml node with the given tag name in the given xml doc ///////////////////////////////////////////////////////////////////////////// HANDLE_NODELIST CIUXml::FindFirstDOMNode(IXMLDOMDocument* pDoc, BSTR bstrName, HANDLE_NODE* phNode) { USES_IU_CONVERSION; HRESULT hr = S_OK; if (NULL == pDoc) { hr = E_INVALIDARG; return HANDLE_NODELIST_INVALID; } DWORD dwIndex1, dwIndex2; IXMLDOMNode *pParentNode = NULL; dwIndex1 = GetNodeListHandle(); if (HANDLE_NODELIST_INVALID != dwIndex1) { LONG lLength; QuitIfFail(pDoc->QueryInterface(IID_IXMLDOMNode, (void**)&pParentNode)); QuitIfFail(pParentNode->selectNodes(bstrName, &m_ppNodeListArray[dwIndex1])); if (NULL == m_ppNodeListArray[dwIndex1]) { goto CleanUp; } QuitIfFail(m_ppNodeListArray[dwIndex1]->get_length(&lLength)); if (lLength <= 0) { goto CleanUp; } dwIndex2 = GetNodeHandle(); if (HANDLE_NODE_INVALID != dwIndex2) { QuitIfFail(m_ppNodeListArray[dwIndex1]->nextNode(&m_ppNodeArray[dwIndex2])); if (NULL == m_ppNodeArray[dwIndex2]) { goto CleanUp; } *phNode = dwIndex2; SafeReleaseNULL(pParentNode); return dwIndex1; } } CleanUp: *phNode = HANDLE_NODE_INVALID; SafeReleaseNULL(pParentNode); return HANDLE_NODELIST_INVALID; } ///////////////////////////////////////////////////////////////////////////// // FindNextDOMNode() // // Retrieve the next xml node with the given tag name under the given parent node ///////////////////////////////////////////////////////////////////////////// HRESULT CIUXml::FindNextDOMNode(HANDLE_NODELIST hNodeList, IXMLDOMNode** ppNode) { HRESULT hr = E_FAIL; if (HANDLE_NODELIST_INVALID != hNodeList) { hr = m_ppNodeListArray[hNodeList]->nextNode(ppNode); } if (FAILED(hr) || NULL == *ppNode) { *ppNode = NULL; return E_FAIL; } return hr; } ///////////////////////////////////////////////////////////////////////////// // FindNextDOMNode() // // Retrieve the handle of next xml node with the given tag name under the given parent node ///////////////////////////////////////////////////////////////////////////// HRESULT CIUXml::FindNextDOMNode(HANDLE_NODELIST hNodeList, HANDLE_NODE* phNode) { HRESULT hr = E_FAIL; DWORD dwIndex = HANDLE_NODE_INVALID; if (HANDLE_NODELIST_INVALID != hNodeList) { dwIndex = GetNodeHandle(); if (HANDLE_NODE_INVALID != dwIndex) { hr = m_ppNodeListArray[hNodeList]->nextNode(&m_ppNodeArray[dwIndex]); } } if (FAILED(hr) || NULL == m_ppNodeArray[dwIndex]) { *phNode = HANDLE_NODE_INVALID; return E_FAIL; } *phNode = dwIndex; return hr; } ///////////////////////////////////////////////////////////////////////////// // CreateDOMNodeWithHandle() // // Create an xml node of the given type // Return: index of the node array "m_ppNodeArray"; or -1 if failure. ///////////////////////////////////////////////////////////////////////////// HANDLE_NODE CIUXml::CreateDOMNodeWithHandle(IXMLDOMDocument* pDoc, SHORT nType, BSTR bstrName, BSTR bstrNamespaceURI /*= NULL*/) { USES_IU_CONVERSION; HRESULT hr = S_OK; if (NULL == pDoc) { hr = E_INVALIDARG; return HANDLE_NODE_INVALID; } DWORD dwIndex; VARIANT vType; VariantInit(&vType); vType.vt = VT_I2; vType.iVal = nType; dwIndex = GetNodeHandle(); if (HANDLE_NODE_INVALID != dwIndex) { QuitIfFail(pDoc->createNode(vType, bstrName, bstrNamespaceURI, &m_ppNodeArray[dwIndex])); return dwIndex; } CleanUp: return HANDLE_NODE_INVALID; } ///////////////////////////////////////////////////////////////////////////// // CXmlSystemSpec ///////////////////////////////////////////////////////////////////////////// // Constructor // // Create IXMLDOMDocument* for SystemSpec ///////////////////////////////////////////////////////////////////////////// CXmlSystemSpec::CXmlSystemSpec() : m_pDocSystemSpec(NULL), m_pNodeSystemInfo(NULL), m_pNodeComputerSystem(NULL), m_pNodeRegKeysSW(NULL), m_pNodePlatform(NULL), m_pNodeDevices(NULL) { LOG_Block("CXmlSystemSpec()"); HRESULT hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void **) &m_pDocSystemSpec); if (FAILED(hr)) { LOG_ErrorMsg(hr); } else { IXMLDOMNode* pNodeXML = NULL; BSTR bstrNameSpaceSchema = NULL; // // create the node // pNodeXML = CreateDOMNode(m_pDocSystemSpec, NODE_PROCESSING_INSTRUCTION, KEY_XML); if (NULL == pNodeXML) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocSystemSpec, pNodeXML)); // // process the iuident.txt to find the SystemSpec schema path // TCHAR szIUDir[MAX_PATH]; TCHAR szIdentFile[MAX_PATH]; LPTSTR pszSystemSpecSchema = NULL; LPTSTR pszNameSpaceSchema = NULL; pszSystemSpecSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR)); if (NULL == pszSystemSpecSchema) { LOG_ErrorMsg(E_OUTOFMEMORY); goto CleanUp; } pszNameSpaceSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR)); if (NULL == pszNameSpaceSchema) { LOG_ErrorMsg(E_OUTOFMEMORY); goto CleanUp; } GetIndustryUpdateDirectory(szIUDir); hr = PathCchCombine(szIdentFile, ARRAYSIZE(szIdentFile), szIUDir,IDENTTXT); if (FAILED(hr)) { LOG_ErrorMsg(hr); goto CleanUp; } if (GetPrivateProfileString(IDENT_IUSCHEMA, IDENT_IUSCHEMA_SYSTEMSPEC, _T(""), pszSystemSpecSchema, INTERNET_MAX_URL_LENGTH, szIdentFile) == INTERNET_MAX_URL_LENGTH - 1) { LOG_Error(_T("SystemSpec schema buffer overflow")); goto CleanUp; } if ('\0' == pszSystemSpecSchema[0]) { // no SystemSpec schema path specified in iuident.txt LOG_Error(_T("No schema path specified in iuident.txt for SystemSpec")); goto CleanUp; } hr = StringCchPrintfEx(pszNameSpaceSchema, INTERNET_MAX_URL_LENGTH, NULL, NULL, MISTSAFE_STRING_FLAGS, _T("x-schema:%s"), pszSystemSpecSchema); if (FAILED(hr)) { LOG_ErrorMsg(hr); goto CleanUp; } bstrNameSpaceSchema = T2BSTR(pszNameSpaceSchema); // // create the node with the path of the schema // m_pNodeSystemInfo = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_SYSTEMINFO, bstrNameSpaceSchema); SafeSysFreeString(bstrNameSpaceSchema); if (NULL == m_pNodeSystemInfo) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocSystemSpec, m_pNodeSystemInfo)); CleanUp: SafeReleaseNULL(pNodeXML); SafeHeapFree(pszSystemSpecSchema); SafeHeapFree(pszNameSpaceSchema); } } ///////////////////////////////////////////////////////////////////////////// // Destructor // // Release IXMLDOMDocument* for SystemSpec ///////////////////////////////////////////////////////////////////////////// CXmlSystemSpec::~CXmlSystemSpec() { SafeReleaseNULL(m_pNodeDevices); SafeReleaseNULL(m_pNodePlatform); SafeReleaseNULL(m_pNodeRegKeysSW); SafeReleaseNULL(m_pNodeComputerSystem); SafeReleaseNULL(m_pNodeSystemInfo); SafeReleaseNULL(m_pDocSystemSpec); } ///////////////////////////////////////////////////////////////////////////// // AddComputerSystem() ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlSystemSpec::AddComputerSystem(BSTR bstrManufacturer, BSTR bstrModel, BSTR bstrSupportSite /*= NULL*/, INT iAdmin /*= -1*/, INT iWUDisabled /*= -1*/, INT iAUEnabled /*= -1*/, BSTR bstrPID) { LOG_Block("AddComputerSystem()"); HRESULT hr = E_FAIL; m_pNodeComputerSystem = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_COMPUTERSYSTEM); if (NULL == m_pNodeComputerSystem) return hr; // // Manufacturer and Model are now optional (RAID#337879 IU: can't get latest IU controls to work with IU site) // if (NULL != bstrManufacturer) { ReturnIfFail(SetAttribute(m_pNodeComputerSystem, KEY_MANUFACTURER, bstrManufacturer)); } if (NULL != bstrModel) { ReturnIfFail(SetAttribute(m_pNodeComputerSystem, KEY_MODEL, bstrModel)); } if (NULL != bstrSupportSite) { ReturnIfFail(SetAttribute(m_pNodeComputerSystem, KEY_SUPPORTSITE, bstrSupportSite)); } if (NULL != bstrPID) { ReturnIfFail(SetAttribute(m_pNodeComputerSystem, KEY_PID, bstrPID)); } if (-1 != iAdmin) { ReturnIfFail(SetAttribute(m_pNodeComputerSystem, KEY_ADMINISTRATOR, iAdmin)); } if (-1 != iWUDisabled) { ReturnIfFail(SetAttribute(m_pNodeComputerSystem, KEY_WU_DISABLED, iWUDisabled)); } if (-1 != iAUEnabled) { ReturnIfFail(SetAttribute(m_pNodeComputerSystem, KEY_AU_ENABLED, iAUEnabled)); } ReturnIfFail(InsertNode(m_pNodeSystemInfo, m_pNodeComputerSystem)); return hr; } ///////////////////////////////////////////////////////////////////////////// // AddDriveSpace() ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlSystemSpec::AddDriveSpace(BSTR bstrDrive, INT iKBytes) { LOG_Block("AddDriveSpace()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeDriveSpace = NULL; pNodeDriveSpace = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_DRIVESPACE); if (NULL == pNodeDriveSpace) goto CleanUp; CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDriveSpace, KEY_DRIVE, bstrDrive)); CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDriveSpace, KEY_KBYTES, iKBytes)); CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeComputerSystem, pNodeDriveSpace)); CleanUp: SafeReleaseNULL(pNodeDriveSpace); return hr; } ///////////////////////////////////////////////////////////////////////////// // AddReg() ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlSystemSpec::AddReg(BSTR bstrProvider) { LOG_Block("AddReg()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeRegKeys = NULL; IXMLDOMNode* pNodeRegKeysHKLM = NULL; IXMLDOMNode* pNodeRegValue = NULL; IXMLDOMNode* pNodeRegValueText = NULL; if (NULL == m_pNodeRegKeysSW) { // // create the node // pNodeRegKeys = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_REGKEYS); if (NULL == pNodeRegKeys) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeSystemInfo, pNodeRegKeys)); // // create the node // pNodeRegKeysHKLM = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_REG_HKLM); if (NULL == pNodeRegKeysHKLM) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeRegKeys, pNodeRegKeysHKLM)); // // create the node // m_pNodeRegKeysSW = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_REG_SW); if (NULL == m_pNodeRegKeysSW) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeRegKeysHKLM, m_pNodeRegKeysSW)); } // // add the node // pNodeRegValue = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_VALUE); if (NULL == pNodeRegValue) goto CleanUp; pNodeRegValueText = CreateDOMNode(m_pDocSystemSpec, NODE_TEXT, NULL); if (NULL == pNodeRegValueText) goto CleanUp; CleanUpIfFailedAndSetHrMsg(SetValue(pNodeRegValueText, bstrProvider)); CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeRegValue, pNodeRegValueText)); CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeRegKeysSW, pNodeRegValue)); CleanUp: if (FAILED(hr)) SafeReleaseNULL(m_pNodeRegKeysSW); SafeReleaseNULL(pNodeRegKeys); SafeReleaseNULL(pNodeRegKeysHKLM); SafeReleaseNULL(pNodeRegValue); SafeReleaseNULL(pNodeRegValueText); return hr; } ///////////////////////////////////////////////////////////////////////////// // AddPlatform() ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlSystemSpec::AddPlatform(BSTR bstrName) { LOG_Block("AddPlatform()"); HRESULT hr = E_FAIL; m_pNodePlatform = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_PLATFORM); if (NULL == m_pNodePlatform) return hr; ReturnIfFail(SetAttribute(m_pNodePlatform, KEY_NAME, bstrName)); ReturnIfFail(InsertNode(m_pNodeSystemInfo, m_pNodePlatform)); return hr; } ///////////////////////////////////////////////////////////////////////////// // AddProcessor() ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlSystemSpec::AddProcessor(BSTR bstrProcessor) { LOG_Block("AddProcessor()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeProcessor = NULL; IXMLDOMNode* pNodeProcessorText = NULL; pNodeProcessor = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_PROCESSORARCHITECTURE); if (NULL == pNodeProcessor) goto CleanUp; pNodeProcessorText = CreateDOMNode(m_pDocSystemSpec, NODE_TEXT, NULL); if (NULL == pNodeProcessorText) goto CleanUp; CleanUpIfFailedAndSetHrMsg(SetValue(pNodeProcessorText, bstrProcessor)); CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeProcessor, pNodeProcessorText)); CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodePlatform, pNodeProcessor)); CleanUp: SafeReleaseNULL(pNodeProcessor); SafeReleaseNULL(pNodeProcessorText); return hr; } ///////////////////////////////////////////////////////////////////////////// // AddVersion() ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlSystemSpec::AddVersion(INT iMajor /*= -1*/, INT iMinor /*= -1*/, INT iBuild /*= -1*/, INT iSPMajor /*= -1*/, INT iSPMinor /*= -1*/, BSTR bstrTimeStamp /*= NULL*/) { LOG_Block("AddVersion()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeVersion = NULL; // // create the node // pNodeVersion = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_VERSION); if (NULL == pNodeVersion) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodePlatform, pNodeVersion)); // // set the "major" attribute // if (-1 != iMajor) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeVersion, KEY_MAJOR, iMajor)); } // // set the "minor" attribute // if (-1 != iMinor) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeVersion, KEY_MINOR, iMinor)); } // // set the "build" attribute // if (-1 != iBuild) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeVersion, KEY_BUILD, iBuild)); } // // set the "servicePackMajor" attribute // if (-1 != iSPMajor) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeVersion, KEY_SERVICEPACKMAJOR, iSPMajor)); } // // set the "servicePackMinor" attribute // if (-1 != iSPMinor) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeVersion, KEY_SERVICEPACKMINOR, iSPMinor)); } // // set the "timestamp" attribute // if (NULL != bstrTimeStamp) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeVersion, KEY_TIMESTAMP, bstrTimeStamp)); } CleanUp: SafeReleaseNULL(pNodeVersion); return hr; } ///////////////////////////////////////////////////////////////////////////// // AddSuite() ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlSystemSpec::AddSuite(BSTR bstrSuite) { LOG_Block("AddSuite()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeSuite = NULL; IXMLDOMNode* pNodeSuiteText = NULL; pNodeSuite = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_SUITE); if (NULL == pNodeSuite) goto CleanUp; pNodeSuiteText = CreateDOMNode(m_pDocSystemSpec, NODE_TEXT, NULL); if (NULL == pNodeSuiteText) goto CleanUp; CleanUpIfFailedAndSetHrMsg(SetValue(pNodeSuiteText, bstrSuite)); CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeSuite, pNodeSuiteText)); CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodePlatform, pNodeSuite)); CleanUp: SafeReleaseNULL(pNodeSuite); SafeReleaseNULL(pNodeSuiteText); return hr; } ///////////////////////////////////////////////////////////////////////////// // AddProductType() ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlSystemSpec::AddProductType(BSTR bstrProductType) { LOG_Block("AddProductType()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeProductType = NULL; IXMLDOMNode* pNodeProductTypeText = NULL; pNodeProductType = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_PRODUCTTYPE); if (NULL == pNodeProductType) goto CleanUp; pNodeProductTypeText = CreateDOMNode(m_pDocSystemSpec, NODE_TEXT, NULL); if (NULL == pNodeProductTypeText) goto CleanUp; CleanUpIfFailedAndSetHrMsg(SetValue(pNodeProductTypeText, bstrProductType)); CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeProductType, pNodeProductTypeText)); CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodePlatform, pNodeProductType)); CleanUp: SafeReleaseNULL(pNodeProductType); SafeReleaseNULL(pNodeProductTypeText); return hr; } ///////////////////////////////////////////////////////////////////////////// // AddLocale() // // We need to pass back a handle to differentiate different node ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlSystemSpec::AddLocale(BSTR bstrContext, HANDLE_NODE* phNodeLocale) { LOG_Block("AddLocale()"); HRESULT hr = E_FAIL; *phNodeLocale = CreateDOMNodeWithHandle(m_pDocSystemSpec, NODE_ELEMENT, KEY_LOCALE); if (HANDLE_NODE_INVALID == *phNodeLocale) return hr; hr = SetAttribute(m_ppNodeArray[*phNodeLocale], KEY_CONTEXT, bstrContext); if (FAILED(hr)) { SafeCloseHandleNode(*phNodeLocale); LOG_ErrorMsg(hr); return hr; } ReturnIfFail(InsertNode(m_pNodeSystemInfo, m_ppNodeArray[*phNodeLocale])); return hr; } ///////////////////////////////////////////////////////////////////////////// // AddLanguage() ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlSystemSpec::AddLanguage(HANDLE_NODE hNodeLocale, BSTR bstrLocale) { LOG_Block("AddLanguage()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeLanguage = NULL; IXMLDOMNode* pNodeLanguageText = NULL; pNodeLanguage = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_LANGUAGE); if (NULL == pNodeLanguage) goto CleanUp; pNodeLanguageText = CreateDOMNode(m_pDocSystemSpec, NODE_TEXT, NULL); if (NULL == pNodeLanguageText) goto CleanUp; CleanUpIfFailedAndSetHrMsg(SetValue(pNodeLanguageText, bstrLocale)); CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeLanguage, pNodeLanguageText)); CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[hNodeLocale], pNodeLanguage)); CleanUp: SafeReleaseNULL(pNodeLanguage); SafeReleaseNULL(pNodeLanguageText); return hr; } ///////////////////////////////////////////////////////////////////////////// // AddDevice() // // We need to pass back a handle to differentiate different node ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlSystemSpec::AddDevice(BSTR bstrDeviceInstance, /*= NULL - optional attribute*/ INT iIsPrinter /*= -1*/, BSTR bstrProvider /*= NULL*/, BSTR bstrMfgName /*= NULL*/, BSTR bstrDriverName /*= NULL*/, HANDLE_NODE* phNodeDevice) { LOG_Block("AddDevice()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodePrinterInfo = NULL; if (NULL == m_pNodeDevices) { // // create the node // m_pNodeDevices = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_DEVICES); if (NULL == m_pNodeDevices) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeSystemInfo, m_pNodeDevices)); } // // add the node // *phNodeDevice = CreateDOMNodeWithHandle(m_pDocSystemSpec, NODE_ELEMENT, KEY_DEVICE); if (HANDLE_NODE_INVALID == *phNodeDevice) goto CleanUp; if (NULL != bstrDeviceInstance && 0 < lstrlenW(bstrDeviceInstance)) { // // set optional deviceInstance attribute of // CleanUpIfFailedAndSetHrMsg(SetAttribute(m_ppNodeArray[*phNodeDevice], KEY_DEVICEINSTANCE, bstrDeviceInstance)); } if (-1 != iIsPrinter) { // // set isPrinter attribute of // CleanUpIfFailedAndSetHrMsg(SetAttribute(m_ppNodeArray[*phNodeDevice], KEY_ISPRINTER, iIsPrinter)); // // Add a node within // pNodePrinterInfo = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, KEY_PRINTERINFO); if (NULL != pNodePrinterInfo) { if (NULL != bstrProvider) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodePrinterInfo, KEY_DRIVERPROVIDER, bstrProvider)); } if (NULL != bstrMfgName) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodePrinterInfo, KEY_MFGNAME, bstrMfgName)); } if (NULL != bstrDriverName) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodePrinterInfo, KEY_DRIVERNAME, bstrDriverName)); } CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[*phNodeDevice], pNodePrinterInfo)); } } // // insert to // CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeDevices, m_ppNodeArray[*phNodeDevice])); CleanUp: SafeReleaseNULL(pNodePrinterInfo); return hr; } ///////////////////////////////////////////////////////////////////////////// // AddHWID() ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlSystemSpec::AddHWID(HANDLE_NODE hNodeDevice, BOOL fIsCompatible, UINT iRank, BSTR bstrHWID, BSTR bstrDriverVer /*= NULL*/) { LOG_Block("AddHWID()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeHWID = NULL; IXMLDOMNode* pNodeHWIDText = NULL; BSTR bstrNameHWID = NULL; if (fIsCompatible) { bstrNameHWID = SysAllocString(L"compid"); } else { bstrNameHWID = SysAllocString(L"hwid"); } pNodeHWID = CreateDOMNode(m_pDocSystemSpec, NODE_ELEMENT, bstrNameHWID); if (NULL == pNodeHWID) goto CleanUp; CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeHWID, KEY_RANK, iRank)); if (NULL != bstrDriverVer) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeHWID, KEY_DRIVERVER, bstrDriverVer)); } pNodeHWIDText = CreateDOMNode(m_pDocSystemSpec, NODE_TEXT, NULL); if (NULL == pNodeHWIDText) goto CleanUp; CleanUpIfFailedAndSetHrMsg(SetValue(pNodeHWIDText, bstrHWID)); CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeHWID, pNodeHWIDText)); CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[hNodeDevice], pNodeHWID)); CleanUp: SafeReleaseNULL(pNodeHWID); SafeReleaseNULL(pNodeHWIDText); SysFreeString(bstrNameHWID); return hr; } ///////////////////////////////////////////////////////////////////////////// // GetSystemSpecBSTR() ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlSystemSpec::GetSystemSpecBSTR(BSTR *pbstrXmlSystemSpec) { LOG_Block("GetSystemSpecBSTR()"); // // convert XML DOC into BSTR // HRESULT hr = m_pDocSystemSpec->get_xml(pbstrXmlSystemSpec); if (FAILED(hr)) { LOG_ErrorMsg(hr); } return hr; } ///////////////////////////////////////////////////////////////////////////// // CXmlSystemClass ///////////////////////////////////////////////////////////////////////////// // Constructor // // Create IXMLDOMDocument* for SystemInfoClasses ///////////////////////////////////////////////////////////////////////////// CXmlSystemClass::CXmlSystemClass() : m_pDocSystemClass(NULL) { } ///////////////////////////////////////////////////////////////////////////// // Destructor // // Release IXMLDOMDocument* for SystemInfoClasses ///////////////////////////////////////////////////////////////////////////// CXmlSystemClass::~CXmlSystemClass() { SafeReleaseNULL(m_pDocSystemClass); } ///////////////////////////////////////////////////////////////////////////// // LoadXMLDocument() // // Load an XML Document from string ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlSystemClass::LoadXMLDocument(BSTR bstrXml, BOOL fOfflineMode) { LOG_Block("LoadXMLDocument()"); SafeReleaseNULL(m_pDocSystemClass); HRESULT hr = LoadXMLDoc(bstrXml, &m_pDocSystemClass, fOfflineMode); if (FAILED(hr)) { LOG_ErrorMsg(hr); } return hr; } ///////////////////////////////////////////////////////////////////////////// // GetClasses() // // Return the bitmap of existence of all possible system info classes ///////////////////////////////////////////////////////////////////////////// DWORD CXmlSystemClass::GetClasses() { LOG_Block("GetClasses()"); DWORD dwResult = 0; IXMLDOMNodeList* pNodeList = NULL; BSTR bstrNameComputerSystem = SysAllocString(L"classes/computerSystem"); BSTR bstrNameRegKeys = SysAllocString(L"classes/regKeys"); BSTR bstrNamePlatform = SysAllocString(L"classes/platform"); BSTR bstrNameLocale = SysAllocString(L"classes/locale"); BSTR bstrNameDevices = SysAllocString(L"classes/devices"); pNodeList = FindDOMNodeList(m_pDocSystemClass, bstrNameComputerSystem); if (NULL != pNodeList) { dwResult |= COMPUTERSYSTEM; SafeReleaseNULL(pNodeList); } pNodeList = FindDOMNodeList(m_pDocSystemClass, bstrNameRegKeys); if (NULL != pNodeList) { dwResult |= REGKEYS; SafeReleaseNULL(pNodeList); } pNodeList = FindDOMNodeList(m_pDocSystemClass, bstrNamePlatform); if (NULL != pNodeList) { dwResult |= PLATFORM; SafeReleaseNULL(pNodeList); } pNodeList = FindDOMNodeList(m_pDocSystemClass, bstrNameLocale); if (NULL != pNodeList) { dwResult |= LOCALE; SafeReleaseNULL(pNodeList); } pNodeList = FindDOMNodeList(m_pDocSystemClass, bstrNameDevices); if (NULL != pNodeList) { dwResult |= DEVICES; SafeReleaseNULL(pNodeList); } SysFreeString(bstrNameComputerSystem); SysFreeString(bstrNameRegKeys); SysFreeString(bstrNamePlatform); SysFreeString(bstrNameLocale); SysFreeString(bstrNameDevices); return dwResult; } ///////////////////////////////////////////////////////////////////////////// // CXmlCatalog ///////////////////////////////////////////////////////////////////////////// // Constructor // // Create IXMLDOMDocument* for Catalog ///////////////////////////////////////////////////////////////////////////// CXmlCatalog::CXmlCatalog() : m_pDocCatalog(NULL) { } ///////////////////////////////////////////////////////////////////////////// // Destructor // // Release IXMLDOMDocument* for Catalog ///////////////////////////////////////////////////////////////////////////// CXmlCatalog::~CXmlCatalog() { SafeReleaseNULL(m_pDocCatalog); } ///////////////////////////////////////////////////////////////////////////// // LoadXMLDocument() // // Load an XML Document from string ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::LoadXMLDocument(BSTR bstrXml, BOOL fOfflineMode) { LOG_Block("LoadXMLDocument()"); SafeReleaseNULL(m_pDocCatalog); HRESULT hr = LoadXMLDoc(bstrXml, &m_pDocCatalog, fOfflineMode); if (FAILED(hr)) { LOG_ErrorMsg(hr); } return hr; } ///////////////////////////////////////////////////////////////////////////// // GetItemCount() // // Gets a Count of How Many Items are in this Catalog ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::GetItemCount(LONG *plItemCount) { LOG_Block("GetItemCount()"); HRESULT hr = E_FAIL; IXMLDOMNodeList *pItemList = NULL; QuitIfNull(plItemCount); QuitIfNull(m_pDocCatalog); IXMLDOMNode *pParentNode = NULL; CleanUpIfFailedAndSetHrMsg(m_pDocCatalog->QueryInterface(IID_IXMLDOMNode, (void**)&pParentNode)); CleanUpIfFailedAndSetHrMsg(pParentNode->selectNodes(KEY_ITEM_SEARCH, &pItemList)); if (NULL == pItemList) goto CleanUp; CleanUpIfFailedAndSetHrMsg(pItemList->get_length(plItemCount)); CleanUp: SafeReleaseNULL(pParentNode); SafeReleaseNULL(pItemList); return hr; } ///////////////////////////////////////////////////////////////////////////// // GetProviders() // // Find a list of node in catalog xml ///////////////////////////////////////////////////////////////////////////// IXMLDOMNodeList* CXmlCatalog::GetProviders() { LOG_Block("GetProviders()"); IXMLDOMNodeList* pNodeList = NULL; pNodeList = FindDOMNodeList(m_pDocCatalog, KEY_CATALOG_PROVIDER); return pNodeList; } ///////////////////////////////////////////////////////////////////////////// // GetFirstProvider() // // Find the first provider in catalog xml doc ///////////////////////////////////////////////////////////////////////////// HANDLE_NODELIST CXmlCatalog::GetFirstProvider(HANDLE_NODE* phNodeProvider) { LOG_Block("GetFirstProvider()"); HANDLE_NODELIST hNodeListProvider = FindFirstDOMNode(m_pDocCatalog, KEY_CATALOG_PROVIDER, phNodeProvider); return hNodeListProvider; } ///////////////////////////////////////////////////////////////////////////// // GetNextProvider() // // Find the next provider in catalog xml doc ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::GetNextProvider(HANDLE_NODELIST hNodeListProvider, HANDLE_NODE* phNodeProvider) { LOG_Block("GetNextProvider()"); return FindNextDOMNode(hNodeListProvider, phNodeProvider); } ///////////////////////////////////////////////////////////////////////////// // GetFirstItem() // // Find the first item in provider (parent) node ///////////////////////////////////////////////////////////////////////////// HANDLE_NODELIST CXmlCatalog::GetFirstItem(HANDLE_NODE hNodeProvider, HANDLE_NODE* phNodeItem) { LOG_Block("GetFirstItem()"); HANDLE_NODELIST hNodeListItem = FindFirstDOMNode(m_ppNodeArray[hNodeProvider], KEY_ITEM, phNodeItem); return hNodeListItem; } ///////////////////////////////////////////////////////////////////////////// // GetNextItem() // // Find the next item in provider (parent) node ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::GetNextItem(HANDLE_NODELIST hNodeListItem, HANDLE_NODE* phNodeItem) { LOG_Block("GetNextItem()"); return FindNextDOMNode(hNodeListItem, phNodeItem); } ///////////////////////////////////////////////////////////////////////////// // GetFirstItemDependency() // // Find the first dependency item in Item Dependencies node ///////////////////////////////////////////////////////////////////////////// HANDLE_NODELIST CXmlCatalog::GetFirstItemDependency(HANDLE_NODE hNodeItem, HANDLE_NODE* phNodeItem) { LOG_Block("GetFirstItemDependency"); HRESULT hr; QuitIfNull(phNodeItem); IXMLDOMNode* pNodeDependencies = NULL; IXMLDOMNode* pNodeIdentity = NULL; HANDLE_NODELIST hNodeListItem = HANDLE_NODELIST_INVALID; hr = FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_DEPENDENCIES, &pNodeDependencies); QuitIfFail(hr); hNodeListItem = FindFirstDOMNode(pNodeDependencies, KEY_IDENTITY, &pNodeIdentity); if (HANDLE_NODELIST_INVALID != hNodeListItem) { // We found at least one Identity in this Dependencies key, Try to find the matching // Item in the Catalog and if found return as the phNodeItem FindItemByIdentity(pNodeIdentity, phNodeItem); } CleanUp: SafeReleaseNULL(pNodeIdentity); SafeReleaseNULL(pNodeDependencies); return hNodeListItem; } ///////////////////////////////////////////////////////////////////////////// // GetNextItemDependency() // // Find the next dependency item in the Item Dependencies node ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::GetNextItemDependency(HANDLE_NODELIST hNodeListItem, HANDLE_NODE* phNodeItem) { LOG_Block("GetNextItemDependency"); HRESULT hr; QuitIfNull(phNodeItem); IXMLDOMNode* pNodeIdentity = NULL; hr = FindNextDOMNode(hNodeListItem, &pNodeIdentity); // This function is supposed to return S_FALSE when no more items are available // but FindNextDOMNode returns E_FAIL when it can't find the next node. So we won't // look at the return. // CleanUpIfFailedAndMsg(hr); if (NULL != pNodeIdentity) { // We found another Identity in this Dependencies Key hr = FindItemByIdentity(pNodeIdentity, phNodeItem); } else { hr = S_FALSE; // indicate to caller there are no more identities. } SafeReleaseNULL(pNodeIdentity); return hr; } ///////////////////////////////////////////////////////////////////////////// // CloseItemList() // // Release the item nodelist ///////////////////////////////////////////////////////////////////////////// void CXmlCatalog::CloseItemList(HANDLE_NODELIST hNodeListItem) { SafeFindCloseHandle(hNodeListItem); } ///////////////////////////////////////////////////////////////////////////// // GetIdentity() // // Retrieve the unique name (identity) of the given provider or item ///////////////////////////////////////////////////////////////////////////// // // public version // HRESULT CXmlCatalog::GetIdentity(HANDLE_NODE hNode, BSTR* pbstrName, BSTR* pbstrPublisherName, BSTR* pbstrGUID) { LOG_Block("GetIdentity()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeIdentity = NULL; CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNode], KEY_IDENTITY, &pNodeIdentity)); hr = Get3IdentiStrFromIdentNode(pNodeIdentity, pbstrName, pbstrPublisherName, pbstrGUID); CleanUp: SafeReleaseNULL(pNodeIdentity); return hr; } ///////////////////////////////////////////////////////////////////////////// // GetIdentityStr() // // Retrieve the string that can be used to uniquely identify an object // based on its node. // // This function defines the logic about what components can be used // to define the uniqueness of an item based on the 3 parts of data from // GetIdentity(). // // The created string will be language neutral. That is, it can not // ensure the uniqueness for two items having the same node // except different only on part inside // ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::GetIdentityStr(HANDLE_NODE hNode, BSTR* pbstrUniqIdentifierString) { IXMLDOMNode* pIdentityNode = NULL; HRESULT hr = E_INVALIDARG; if (FindNode(m_ppNodeArray[hNode], KEY_IDENTITY, &pIdentityNode) && NULL != pIdentityNode) { hr = UtilGetUniqIdentityStr(pIdentityNode, pbstrUniqIdentifierString, 0x0); SafeReleaseNULL(pIdentityNode); } return hr; } HRESULT CXmlCatalog::GetIdentityStrForPing(HANDLE_NODE hNode, BSTR* pbstrUniqIdentifierString) { IXMLDOMNode* pIdentityNode = NULL; HRESULT hr = E_INVALIDARG; if (FindNode(m_ppNodeArray[hNode], KEY_IDENTITY, &pIdentityNode) && NULL != pIdentityNode) { // // first, based on OP team's requirement, we try to look for in the identity tag. // if it's there, use use that. If not, we use the publisherName.itemname thing. // if (FAILED(hr = GetAttribute(pIdentityNode, KEY_ITEMID, pbstrUniqIdentifierString)) || NULL == *pbstrUniqIdentifierString) { // hr = UtilGetUniqIdentityStr(pIdentityNode, pbstrUniqIdentifierString, SKIP_SERVICEPACK_VER); hr = E_INVALIDARG; } SafeReleaseNULL(pIdentityNode); } return hr; } ///////////////////////////////////////////////////////////////////////////// // GetBSTRItemForCallback() // // Create an item node as the passed-in node, have child nodes identity and // platform (anything uniquely idenitify this item) then output this // item node data as string, then delete the crated node // ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::GetBSTRItemForCallback(HANDLE_NODE hItem, BSTR* pbstrXmlItemForCallback) { HRESULT hr = E_INVALIDARG; IXMLDOMNode* pNewItemNode = NULL; IXMLDOMNode* pNewIdentityNode = NULL; IXMLDOMNode* pNewPlatformNode = NULL; IXMLDOMNode* pOldIdentityNode = NULL; IXMLDOMNode* pOldPlatformNode = NULL; IXMLDOMNode* p1 = NULL, *p2 = NULL; LOG_Block("CXmlCatalog::GetBSTRItemForCallback()"); if (FAILED(hr = m_ppNodeArray[hItem]->cloneNode(VARIANT_FALSE, &pNewItemNode)) || FAILED(hr = FindSingleDOMNode(m_ppNodeArray[hItem], KEY_IDENTITY, &pOldIdentityNode)) || NULL == pOldIdentityNode || FAILED(hr = pOldIdentityNode->cloneNode(VARIANT_TRUE, &pNewIdentityNode)) || NULL == pNewIdentityNode || FAILED(hr = pNewItemNode->appendChild(pNewIdentityNode, &p1)) || NULL == p1) { if (S_FALSE == hr) hr = E_INVALIDARG; LOG_ErrorMsg(hr); goto CleanUp; } // // platform is optional // FindSingleDOMNode(m_ppNodeArray[hItem], KEY_PLATFORM, &pOldPlatformNode); if (pOldPlatformNode) { if (FAILED(hr = pOldPlatformNode->cloneNode(VARIANT_TRUE, &pNewPlatformNode)) || NULL == pNewPlatformNode || FAILED(hr = pNewItemNode->appendChild(pNewPlatformNode, &p2)) || NULL == p2) { LOG_ErrorMsg(hr); goto CleanUp; } } pNewItemNode->get_xml(pbstrXmlItemForCallback); CleanUp: SafeReleaseNULL(pOldIdentityNode); SafeReleaseNULL(pOldPlatformNode); SafeReleaseNULL(pNewIdentityNode); SafeReleaseNULL(pNewPlatformNode); SafeReleaseNULL(p1); SafeReleaseNULL(p2); SafeReleaseNULL(pNewItemNode); return hr; } ///////////////////////////////////////////////////////////////////////////// // IsPrinterDriver() // // Retrieves from the Catalog whether this Item is a Printer Driver // ///////////////////////////////////////////////////////////////////////////// BOOL CXmlCatalog::IsPrinterDriver(HANDLE_NODE hNode) { LOG_Block("IsPrinterDriver()"); BOOL fRet = FALSE; HRESULT hr; IXMLDOMNode* pNodeDetection = NULL; IXMLDOMNode* pNodeCompatibleHardware = NULL; IXMLDOMNode* pNodeDevice = NULL; hr = FindSingleDOMNode(m_ppNodeArray[hNode], KEY_DETECTION, &pNodeDetection); CleanUpIfFailedAndMsg(hr); hr = FindSingleDOMNode(pNodeDetection, KEY_COMPATIBLEHARDWARE, &pNodeCompatibleHardware); CleanUpIfFailedAndMsg(hr); hr = FindSingleDOMNode(pNodeCompatibleHardware, KEY_DEVICE, &pNodeDevice); CleanUpIfFailedAndMsg(hr); int intIsPrinter = 0; GetAttribute(pNodeDevice, KEY_ISPRINTER, &intIsPrinter); if (1 == intIsPrinter) { fRet = TRUE; } else { fRet = FALSE; } CleanUp: SafeReleaseNULL(pNodeDevice); SafeReleaseNULL(pNodeCompatibleHardware); SafeReleaseNULL(pNodeDetection); return fRet; } ///////////////////////////////////////////////////////////////////////////// // GetDriverInfo() // // Retrieves the Driver Information from the Catalog for this Item. Returns // the Display Name and HWID for this driver - This is passed to the CDM // installer // ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::GetDriverInfo(HANDLE_NODE hNode, BSTR* pbstrHWID, BSTR* pbstrDisplayName) { HRESULT hr; LOG_Block("GetDriverInfo()"); QuitIfNull(pbstrHWID); QuitIfNull(pbstrDisplayName); *pbstrHWID = NULL; *pbstrDisplayName = NULL; IXMLDOMNode* pNodeDetection = NULL; IXMLDOMNode* pNodeCompatibleHardware = NULL; IXMLDOMNode* pNodeDevice = NULL; IXMLDOMNode* pNodeHWID = NULL; IXMLDOMNode* pNodeDescription = NULL; IXMLDOMNode* pNodeDescriptionText = NULL; IXMLDOMNode* pNodeTitle = NULL; hr = FindSingleDOMNode(m_ppNodeArray[hNode], KEY_DETECTION, &pNodeDetection); CleanUpIfFailedAndMsg(hr); hr = FindSingleDOMNode(pNodeDetection, KEY_COMPATIBLEHARDWARE, &pNodeCompatibleHardware); CleanUpIfFailedAndMsg(hr); hr = FindSingleDOMNode(pNodeCompatibleHardware, KEY_DEVICE, &pNodeDevice); CleanUpIfFailedAndMsg(hr); hr = FindSingleDOMNode(pNodeDevice, KEY_HWID, &pNodeHWID); CleanUpIfFailedAndMsg(hr); GetText(pNodeHWID, pbstrHWID); hr = FindSingleDOMNode(pNodeDetection, KEY_DESCRIPTION, &pNodeDescription); CleanUpIfFailedAndMsg(hr); hr = FindSingleDOMNode(pNodeDescription, KEY_DESCRIPTIONTEXT, &pNodeDescriptionText); CleanUpIfFailedAndMsg(hr); hr = FindSingleDOMNode(pNodeDescriptionText, KEY_TITLE, &pNodeTitle); CleanUpIfFailedAndMsg(hr); GetText(pNodeTitle, pbstrDisplayName); CleanUp: if (FAILED(hr)) { SafeSysFreeString(*pbstrHWID); SafeSysFreeString(*pbstrDisplayName); } SafeReleaseNULL(pNodeTitle); SafeReleaseNULL(pNodeDescriptionText); SafeReleaseNULL(pNodeDescription); SafeReleaseNULL(pNodeHWID); SafeReleaseNULL(pNodeDevice); SafeReleaseNULL(pNodeCompatibleHardware); SafeReleaseNULL(pNodeDetection); return hr; } ///////////////////////////////////////////////////////////////////////////// // GetPrinterDriverInfo() // // Retrieves the Printer Driver Information from the Catalog for this Item. // Returns the DriverName and the Architecture - This is passed to the CDM // installer // ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::GetPrinterDriverInfo(HANDLE_NODE hNode, BSTR* pbstrDriverName, BSTR* pbstrArchitecture) { HRESULT hr; LOG_Block("GetPrinterDriverInfo()"); QuitIfNull(pbstrDriverName); QuitIfNull(pbstrArchitecture); IXMLDOMNode* pNodeDetection = NULL; IXMLDOMNode* pNodeCompatibleHardware = NULL; IXMLDOMNode* pNodeDevice = NULL; IXMLDOMNode* pNodePrinterInfo = NULL; hr = FindSingleDOMNode(m_ppNodeArray[hNode], KEY_DETECTION, &pNodeDetection); CleanUpIfFailedAndMsg(hr); hr = FindSingleDOMNode(pNodeDetection, KEY_COMPATIBLEHARDWARE, &pNodeCompatibleHardware); CleanUpIfFailedAndMsg(hr); hr = FindSingleDOMNode(pNodeCompatibleHardware, KEY_DEVICE, &pNodeDevice); CleanUpIfFailedAndMsg(hr); hr = FindSingleDOMNode(pNodeDevice, KEY_PRINTERINFO, &pNodePrinterInfo); CleanUpIfFailedAndMsg(hr); GetAttribute(pNodePrinterInfo, KEY_DRIVERNAME, pbstrDriverName); // NOTE: Currently the CatalogSchema site is not returning // architecture for printers, and the schema doesn't require it // CDM is using a default string for now based on compile architecture // so we'll leave pbstrArchitecture NULL.. CleanUp: SafeReleaseNULL(pNodePrinterInfo); SafeReleaseNULL(pNodeDevice); SafeReleaseNULL(pNodeCompatibleHardware); SafeReleaseNULL(pNodeDetection); return hr; } ///////////////////////////////////////////////////////////////////////////// // GetDriverInfoEx() // // Combines functionality of IsPrinterDriver, GetDriverInfo, and // GetPrinterDriverInfo plus retreives MfgName and DriverProvider. // Used by FindMatchingDriver() // // If SUCCEEDES pbstrHWID, pbstrDriverVer, and pbstrDisplayName // are always returned. // If SUCCEEDES && *pFIsPrinter == TRUE then pbstrDriverName, // pbstrDriverProvider, and pbstrMfgName are returned. // // Currently pbstrArchitecture is never returned. // ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::GetDriverInfoEx( HANDLE_NODE hNode, BOOL* pfIsPrinter, BSTR* pbstrHWID, BSTR* pbstrDriverVer, BSTR* pbstrDisplayName, BSTR* pbstrDriverName, BSTR* pbstrDriverProvider, BSTR* pbstrMfgName, BSTR* pbstrArchitecture) { HRESULT hr; LOG_Block("GetDriverInfoEx()"); QuitIfNull(pbstrHWID); QuitIfNull(pbstrDriverVer); QuitIfNull(pbstrDisplayName); QuitIfNull(pbstrDriverName); QuitIfNull(pbstrDriverProvider); QuitIfNull(pbstrMfgName); QuitIfNull(pbstrArchitecture); *pbstrHWID = NULL; *pbstrDriverVer = NULL; *pbstrDisplayName = NULL; *pbstrDriverName = NULL; *pbstrDriverProvider = NULL; *pbstrMfgName = NULL; *pbstrArchitecture = NULL; IXMLDOMNode* pNodeDetection = NULL; IXMLDOMNode* pNodeCompatibleHardware = NULL; IXMLDOMNode* pNodeDevice = NULL; IXMLDOMNode* pNodeHWID = NULL; IXMLDOMNode* pNodeDescription = NULL; IXMLDOMNode* pNodeDescriptionText = NULL; IXMLDOMNode* pNodeTitle = NULL; IXMLDOMNode* pNodePrinterInfo = NULL; hr = FindSingleDOMNode(m_ppNodeArray[hNode], KEY_DETECTION, &pNodeDetection); CleanUpIfFailedAndMsg(hr); hr = FindSingleDOMNode(pNodeDetection, KEY_COMPATIBLEHARDWARE, &pNodeCompatibleHardware); CleanUpIfFailedAndMsg(hr); hr = FindSingleDOMNode(pNodeCompatibleHardware, KEY_DEVICE, &pNodeDevice); CleanUpIfFailedAndMsg(hr); // // Is it a printer? // int intIsPrinter = 0; GetAttribute(pNodeDevice, KEY_ISPRINTER, &intIsPrinter); if (1 == intIsPrinter) { *pfIsPrinter = TRUE; } else { *pfIsPrinter = FALSE; } // // HWID and Driver Description // hr = FindSingleDOMNode(pNodeDevice, KEY_HWID, &pNodeHWID); CleanUpIfFailedAndMsg(hr); hr = GetText(pNodeHWID, pbstrHWID); CleanUpIfFailedAndMsg(hr); hr = GetAttribute(pNodeHWID, KEY_DRIVERVER, pbstrDriverVer); CleanUpIfFailedAndMsg(hr); hr = FindSingleDOMNode(m_ppNodeArray[hNode], KEY_DESCRIPTION, &pNodeDescription); CleanUpIfFailedAndMsg(hr); hr = FindSingleDOMNode(pNodeDescription, KEY_DESCRIPTIONTEXT, &pNodeDescriptionText); CleanUpIfFailedAndMsg(hr); hr = FindSingleDOMNode(pNodeDescriptionText, KEY_TITLE, &pNodeTitle); CleanUpIfFailedAndMsg(hr); hr = GetText(pNodeTitle, pbstrDisplayName); CleanUpIfFailedAndMsg(hr); if (*pfIsPrinter) { // // Printer Attributes // hr = FindSingleDOMNode(pNodeDevice, KEY_PRINTERINFO, &pNodePrinterInfo); CleanUpIfFailedAndMsg(hr); hr = GetAttribute(pNodePrinterInfo, KEY_DRIVERNAME, pbstrDriverName); CleanUpIfFailedAndMsg(hr); hr = GetAttribute(pNodePrinterInfo, KEY_DRIVERPROVIDER, pbstrDriverProvider); CleanUpIfFailedAndMsg(hr); hr = GetAttribute(pNodePrinterInfo, KEY_MFGNAME, pbstrMfgName); CleanUpIfFailedAndMsg(hr); // NOTE: Currently the CatalogSchema site is not returning // architecture for printers, and the schema doesn't require it // CDM is using a default string for now based on compile architecture // so we'll leave pbstrArchitecture NULL.. } CleanUp: if (FAILED(hr)) { SafeSysFreeString(*pbstrHWID); SafeSysFreeString(*pbstrDriverVer); SafeSysFreeString(*pbstrDisplayName); SafeSysFreeString(*pbstrDriverName); SafeSysFreeString(*pbstrDriverProvider); SafeSysFreeString(*pbstrMfgName); SafeSysFreeString(*pbstrArchitecture); } SafeReleaseNULL(pNodeTitle); SafeReleaseNULL(pNodeDescriptionText); SafeReleaseNULL(pNodeDescription); SafeReleaseNULL(pNodeHWID); SafeReleaseNULL(pNodeDevice); SafeReleaseNULL(pNodeCompatibleHardware); SafeReleaseNULL(pNodeDetection); SafeReleaseNULL(pNodePrinterInfo); return hr; } ///////////////////////////////////////////////////////////////////////////// // GetItemPlatformStr() // // The input node pointer points to a node has as its child. // This function will retrieve the node from and // convert the data inside into a string that can be used to // uniquely identify a platform. // ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::GetItemFirstPlatformStr(HANDLE_NODE hNodeItem, BSTR* pbstrPlatform) { HRESULT hr; IXMLDOMNode* pNodePlatform = NULL; LOG_Block("GetItemFirstPlatformStr"); USES_IU_CONVERSION; // // get the first platform node from this item node // hr = FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_PLATFORM, &pNodePlatform); CleanUpIfFailedAndMsg(hr); // // get platform data from this ndoe and convert it into string // hr = GetPlatformStrForPing(pNodePlatform, pbstrPlatform); CleanUp: SafeReleaseNULL(pNodePlatform); // // since platform is not a required element in , so we should not // return error if not found // if (HRESULT_FROM_WIN32(ERROR_NOT_FOUND) == hr) { *pbstrPlatform = NULL; hr = S_FALSE; } return hr; } ///////////////////////////////////////////////////////////////////////////// // GetItemAllPlatformStr() // // The input node pointer points to an item node that has node(s). // This function will retrieve every node from this item node and // convert the data inside into a string that can be used to // uniquely identify a platform. // ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::GetItemAllPlatformStr(HANDLE_NODE hNodeItem, BSTR** ppbPlatforms, UINT* pnPlatformCount) { LOG_Block("GetItemAllPlatformStr"); HRESULT hr; IXMLDOMNodeList* pPlatformList = NULL; IXMLDOMElement* pElement = NULL; IXMLDOMNode* pNodePlatform = NULL; long lCount = 0; int i; BSTR* pbstrPlatformList = NULL; // // get list of platform nodes // hr = m_ppNodeArray[hNodeItem]->QueryInterface(IID_IXMLDOMElement, (void**)&pElement); CleanUpIfFailedAndMsg(hr); hr = pElement->getElementsByTagName(KEY_PLATFORM, &pPlatformList); CleanUpIfFailedAndMsg(hr); hr = pPlatformList->get_length(&lCount); CleanUpIfFailedAndMsg(hr); if (0 == lCount) { goto CleanUp; } pbstrPlatformList = (BSTR*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lCount * sizeof(BSTR*)); CleanUpFailedAllocSetHrMsg(pbstrPlatformList); // // loop through each suite, if any // pPlatformList->reset(); for (i = 0; i < lCount; i++) { hr = pPlatformList->get_item(i, &pNodePlatform); CleanUpIfFailedAndMsg(hr); if (pNodePlatform) { hr = pNodePlatform->get_text(&(pbstrPlatformList[i])); CleanUpIfFailedAndMsg(hr); pNodePlatform->Release(); pNodePlatform = NULL; } } hr = S_OK; CleanUp: SafeReleaseNULL(pNodePlatform); SafeReleaseNULL(pPlatformList); SafeReleaseNULL(pElement); if (SUCCEEDED(hr)) { *pnPlatformCount = lCount; *ppbPlatforms = pbstrPlatformList; } else { if (NULL != pbstrPlatformList) { *pnPlatformCount = 0; // // release all possibly allocated memory // for (i = 0; i < lCount; i++) { SafeSysFreeString(pbstrPlatformList[i]); } HeapFree(GetProcessHeap(), 0, pbstrPlatformList); } } return hr; } ///////////////////////////////////////////////////////////////////////////// // GetItemPlatformStr() // // The input node pointer points to a node has as its child. // This function will retrieve the node from and // convert the data inside into a string that can be used to // uniquely identify a platform. // ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::GetPlatformStr(IXMLDOMNode* pNodePlatform, BSTR* pbstrPlatform) { return UtilGetPlatformStr(pNodePlatform, pbstrPlatform, 0x0); } HRESULT CXmlCatalog::GetPlatformStrForPing(IXMLDOMNode* pNodePlatform, BSTR* pbstrPlatform) { return UtilGetPlatformStr(pNodePlatform, pbstrPlatform, SKIP_SUITES | SKIP_SERVICEPACK_VER); } ///////////////////////////////////////////////////////////////////////////// // // get data from a version node and convert them into a string with // format: // VersionStr = [,[,]] // = [.[.]] // = [.] // // Assumption: // pszVersion points to a buffer LARGE ENOUGH to store // any legal version number. // ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::getVersionStr(IXMLDOMNode* pNodeVersion, LPTSTR pszVersion) { return UtilGetVersionStr(pNodeVersion, pszVersion, 0x0); } HRESULT CXmlCatalog::getVersionStrWithoutSvcPack(IXMLDOMNode* pNodeVersion, LPTSTR pszVersion) { return UtilGetVersionStr(pNodeVersion, pszVersion, SKIP_SERVICEPACK_VER); } ///////////////////////////////////////////////////////////////////////////// // GetItemFirstLanguageStr() // // The input node pointer points to a node has as its child. // This function will retrieve the first node from // node // ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::GetItemFirstLanguageStr(HANDLE_NODE hNodeItem, BSTR* pbstrLanguage) { LOG_Block("GetItemFirstLanguageStr"); IXMLDOMNode* pNodeIdentity = NULL; IXMLDOMNode* pNodeLanguage = NULL; HRESULT hr = m_ppNodeArray[hNodeItem]->selectSingleNode(KEY_IDENTITY, &pNodeIdentity); CleanUpIfFailedAndMsg(hr); if (pNodeIdentity) { if (HANDLE_NODELIST_INVALID == FindFirstDOMNode(pNodeIdentity, KEY_LANGUAGE, &pNodeLanguage)) { hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND); goto CleanUp; } else { hr = pNodeLanguage->get_text(pbstrLanguage); CleanUpIfFailedAndMsg(hr); } } CleanUp: SafeReleaseNULL(pNodeLanguage); SafeReleaseNULL(pNodeIdentity); // // since language is not a required element in , so we should not // return error if not found // if (HRESULT_FROM_WIN32(ERROR_NOT_FOUND) == hr) { *pbstrLanguage = NULL; hr = S_FALSE; } return hr; } ///////////////////////////////////////////////////////////////////////////// // GetItemAllLanguageStr() // // The input node pointer points to a node has as its child. // This function will retrieve every node from node and // convert the data into an BSTR array to return. // ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::GetItemAllLanguageStr(HANDLE_NODE hNodeItem, BSTR** ppbstrLanguage, UINT* pnLangCount) { LOG_Block("GetItemAllLanguageStr"); HRESULT hr; IXMLDOMNode* pNodeIdentity = NULL; IXMLDOMNodeList* pLanguageList = NULL; IXMLDOMElement* pElement = NULL; IXMLDOMNode* pNodeLanguage = NULL; long lCount = 0; int i; BSTR* pbstrLanguageList = NULL; hr = m_ppNodeArray[hNodeItem]->selectSingleNode(KEY_IDENTITY, &pNodeIdentity); CleanUpIfFailedAndMsg(hr); // // get list of nodes // hr = pNodeIdentity->QueryInterface(IID_IXMLDOMElement, (void**)&pElement); CleanUpIfFailedAndMsg(hr); hr = pElement->getElementsByTagName(KEY_LANGUAGE, &pLanguageList); CleanUpIfFailedAndMsg(hr); hr = pLanguageList->get_length(&lCount); CleanUpIfFailedAndMsg(hr); if (0 == lCount) { goto CleanUp; } pbstrLanguageList = (BSTR*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, lCount * sizeof(BSTR*)); CleanUpFailedAllocSetHrMsg(pbstrLanguageList); // // loop through each suite, if any // pLanguageList->reset(); for (i = 0; i < lCount; i++) { hr = pLanguageList->get_item(i, &pNodeLanguage); CleanUpIfFailedAndMsg(hr); if (pNodeLanguage) { hr = pNodeLanguage->get_text(&(pbstrLanguageList[i])); CleanUpIfFailedAndMsg(hr); pNodeLanguage->Release(); pNodeLanguage = NULL; } } hr = S_OK; CleanUp: SafeReleaseNULL(pNodeLanguage); SafeReleaseNULL(pLanguageList); SafeReleaseNULL(pElement); SafeReleaseNULL(pNodeIdentity); if (SUCCEEDED(hr)) { *pnLangCount = lCount; *ppbstrLanguage = pbstrLanguageList; } else { if (NULL != pbstrLanguageList) { *pnLangCount = 0; // // release all possibly allocated memory // for (i = 0; i < lCount; i++) { SafeSysFreeString(pbstrLanguageList[i]); } HeapFree(GetProcessHeap(), 0, pbstrLanguageList); } } return hr; } ///////////////////////////////////////////////////////////////////////////// // GetItemFirstCodeBase() // // Find the first codebase (path) of the given item ///////////////////////////////////////////////////////////////////////////// HANDLE_NODELIST CXmlCatalog::GetItemFirstCodeBase(HANDLE_NODE hNodeItem, BSTR* pbstrCodeBase, BSTR* pbstrName, BSTR* pbstrCRC, BOOL* pfPatchAvailable, LONG* plSize) { LOG_Block("GetItemFirstCodeBase()"); HRESULT hr = E_FAIL; QuitIfNull(pbstrCodeBase); QuitIfNull(pbstrName); QuitIfNull(pbstrCRC); QuitIfNull(pfPatchAvailable); QuitIfNull(plSize); IXMLDOMNode* pNodeInstall = NULL; IXMLDOMNode* pNodeCodeBaseSize = NULL; HANDLE_NODE hNodeCodeBase = HANDLE_NODE_INVALID; HANDLE_NODELIST hNodeListCodeBase = HANDLE_NODELIST_INVALID; *pbstrCodeBase = NULL; *pbstrName = NULL; *pbstrCRC = NULL; *pfPatchAvailable = FALSE; *plSize = -1; BSTR bstrSize = NULL; CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_INSTALLATION, &pNodeInstall)); hNodeListCodeBase = FindFirstDOMNode(pNodeInstall, KEY_CODEBASE, &hNodeCodeBase); if (HANDLE_NODELIST_INVALID == hNodeListCodeBase) goto CleanUp; CleanUpIfFailedAndSetHrMsg(GetAttribute(m_ppNodeArray[hNodeCodeBase], KEY_HREF, pbstrCodeBase)); CleanUpIfFailedAndSetHrMsg(GetAttribute(m_ppNodeArray[hNodeCodeBase], KEY_PATCHAVAILABLE, pfPatchAvailable)); GetAttribute(m_ppNodeArray[hNodeCodeBase], KEY_CRC, pbstrCRC); // optional attribute, don't fail if its not there. GetAttribute(m_ppNodeArray[hNodeCodeBase], KEY_NAME, pbstrName); FindSingleDOMNode(m_ppNodeArray[hNodeCodeBase], KEY_SIZE, &pNodeCodeBaseSize); GetText(pNodeCodeBaseSize, &bstrSize); if (NULL != bstrSize) { *plSize = MyBSTR2L(bstrSize); SysFreeString(bstrSize); } CleanUp: SafeReleaseNULL(pNodeInstall); SafeReleaseNULL(pNodeCodeBaseSize); if (FAILED(hr)) { SafeSysFreeString(*pbstrCodeBase); SafeSysFreeString(*pbstrName); SafeSysFreeString(*pbstrCRC); *pfPatchAvailable = FALSE; *plSize = -1; } return hNodeListCodeBase; } ///////////////////////////////////////////////////////////////////////////// // GetItemNextCodeBase() // // Find the next codebase (path) of the given item ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::GetItemNextCodeBase(HANDLE_NODELIST hNodeListCodeBase, BSTR* pbstrCodeBase, BSTR* pbstrName, BSTR* pbstrCRC, BOOL* pfPatchAvailable, LONG* plSize) { LOG_Block("GetItemNextCodeBase()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeCodeBaseSize = NULL; HANDLE_NODE hNodeCodeBase = HANDLE_NODE_INVALID; if (NULL == pbstrCodeBase || NULL == pbstrName || NULL == pbstrCRC || NULL == pfPatchAvailable || NULL == plSize) { return E_INVALIDARG; } *pbstrCodeBase = NULL; *pbstrName = NULL; *pbstrCRC = NULL; *pfPatchAvailable = FALSE; *plSize = -1; BSTR bstrSize = NULL; if (SUCCEEDED(hr = FindNextDOMNode(hNodeListCodeBase, &hNodeCodeBase))) { CleanUpIfFailedAndSetHrMsg(GetAttribute(m_ppNodeArray[hNodeCodeBase], KEY_HREF, pbstrCodeBase)); CleanUpIfFailedAndSetHrMsg(GetAttribute(m_ppNodeArray[hNodeCodeBase], KEY_PATCHAVAILABLE, pfPatchAvailable)); GetAttribute(m_ppNodeArray[hNodeCodeBase], KEY_NAME, pbstrName); GetAttribute(m_ppNodeArray[hNodeCodeBase], KEY_CRC, pbstrCRC); FindSingleDOMNode(m_ppNodeArray[hNodeCodeBase], KEY_SIZE, &pNodeCodeBaseSize); GetText(pNodeCodeBaseSize, &bstrSize); if (NULL != bstrSize) { *plSize = MyBSTR2L(bstrSize); } } CleanUp: SafeReleaseNULL(pNodeCodeBaseSize); SafeSysFreeString(bstrSize); if (FAILED(hr)) { SafeSysFreeString(*pbstrCodeBase); SafeSysFreeString(*pbstrCRC); SafeSysFreeString(*pbstrName); *pfPatchAvailable = FALSE; *plSize = -1; } return hr; } ///////////////////////////////////////////////////////////////////////////// // GetItemInstallInfo() // // Retrieve the installation information of the given item ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::GetItemInstallInfo(HANDLE_NODE hNodeItem, BSTR* pbstrInstallerType, BOOL* pfExclusive, BOOL* pfReboot, LONG* plNumCommands) { LOG_Block("GetItemInstallInfo()"); HRESULT hr = E_FAIL; QuitIfNull(pbstrInstallerType); QuitIfNull(pfExclusive); QuitIfNull(pfReboot); QuitIfNull(plNumCommands); *pbstrInstallerType = NULL; *plNumCommands = 0; // may not be any, so initialize to 0 IXMLDOMNode* pNodeInstall = NULL; IXMLDOMNodeList* pNodeListCommands = NULL; CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_INSTALLATION, &pNodeInstall)); CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeInstall, KEY_INSTALLERTYPE, pbstrInstallerType)); CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeInstall, KEY_EXCLUSIVE, pfExclusive)); CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeInstall, KEY_NEEDSREBOOT, pfReboot)); pNodeListCommands = FindDOMNodeList(pNodeInstall, KEY_COMMAND); if (NULL != pNodeListCommands) { CleanUpIfFailedAndSetHrMsg(pNodeListCommands->get_length(plNumCommands)); } CleanUp: if (FAILED(hr)) { SafeSysFreeString(*pbstrInstallerType); } SafeReleaseNULL(pNodeInstall); SafeReleaseNULL(pNodeListCommands); return hr; } ///////////////////////////////////////////////////////////////////////////// // GetItemInstallCommand() // // Find the installation command and switches of the given item ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::GetItemInstallCommand(HANDLE_NODE hNodeItem, INT iOrder, BSTR* pbstrCommandType, BSTR* pbstrCommand, BSTR* pbstrSwitches, BSTR* pbstrInfSection) { LOG_Block("GetItemInstallCommand()"); USES_IU_CONVERSION; HRESULT hr = E_FAIL; QuitIfNull(pbstrCommandType); QuitIfNull(pbstrCommand); QuitIfNull(pbstrSwitches); QuitIfNull(pbstrInfSection); *pbstrCommandType = NULL; *pbstrCommand = NULL; *pbstrSwitches = NULL; *pbstrInfSection = NULL; IXMLDOMNode* pNodeInstall = NULL; IXMLDOMNode* pNodeCommand = NULL; IXMLDOMNode* pNodeSwitches = NULL; BSTR bstrNameCommandTemp = SysAllocString(L"command[@order = "); TCHAR szCommand[64]; hr = StringCchPrintfEx(szCommand, ARRAYSIZE(szCommand), NULL, NULL, MISTSAFE_STRING_FLAGS, _T("%ls\"%d\"]"), bstrNameCommandTemp, iOrder); CleanUpIfFailedAndSetHrMsg(hr); BSTR bstrNameCommand = SysAllocString(T2OLE(szCommand)); CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_INSTALLATION, &pNodeInstall)); CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(pNodeInstall, bstrNameCommand, &pNodeCommand)); CleanUpIfFailedAndSetHrMsg(GetText(pNodeCommand, pbstrCommand)); CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeCommand, KEY_COMMANDTYPE, pbstrCommandType)); CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeCommand, KEY_INFINSTALL, pbstrInfSection)); if (SUCCEEDED(FindSingleDOMNode(pNodeCommand, KEY_SWITCHES, &pNodeSwitches))) { CleanUpIfFailedAndSetHrMsg(GetText(pNodeSwitches, pbstrSwitches)); } CleanUp: if (FAILED(hr)) { SafeSysFreeString(*pbstrCommandType); SafeSysFreeString(*pbstrCommand); SafeSysFreeString(*pbstrSwitches); SafeSysFreeString(*pbstrInfSection); } SafeReleaseNULL(pNodeInstall); SafeReleaseNULL(pNodeCommand); SafeReleaseNULL(pNodeSwitches); SysFreeString(bstrNameCommand); SysFreeString(bstrNameCommandTemp); return hr; } ///////////////////////////////////////////////////////////////////////////// // CloseItem() // // Release the item node ///////////////////////////////////////////////////////////////////////////// void CXmlCatalog::CloseItem(HANDLE_NODE hNodeItem) { SafeCloseHandleNode(hNodeItem); } ///////////////////////////////////////////////////////////////////////////// // GetTotalEstimatedSize() // // Get the Total Estimated Download Size of all Items based on Codebase Size HRESULT CXmlCatalog::GetTotalEstimatedSize(LONG *plTotalSize) { LOG_Block("GetTotalEstimatedSize()"); HRESULT hr = E_FAIL; BSTR bstrCodebaseSize = NULL; IXMLDOMNodeList *pItemList = NULL; IXMLDOMNodeList *pCodebaseList = NULL; IXMLDOMNode *pNodeItem = NULL; IXMLDOMNode *pNodeInstall = NULL; IXMLDOMNode *pNodeCodebase = NULL; IXMLDOMNode *pNodeSize = NULL; LONG lItemCount = 0; LONG lCodebaseCount = 0; LONG lTotalSize = 0; QuitIfNull(plTotalSize); *plTotalSize = 0; IXMLDOMNode *pParentNode = NULL; CleanUpIfFailedAndSetHrMsg(m_pDocCatalog->QueryInterface(IID_IXMLDOMNode, (void**)&pParentNode)); CleanUpIfFailedAndSetHrMsg(pParentNode->selectNodes(KEY_ITEM_SEARCH, &pItemList)); if (NULL == pItemList) goto CleanUp; CleanUpIfFailedAndSetHrMsg(pItemList->get_length(&lItemCount)); if (0 == lItemCount) goto CleanUp; // no items // Loop through each Item CleanUpIfFailedAndSetHrMsg(pItemList->nextNode(&pNodeItem)); while (NULL != pNodeItem) { // Get Installation Element CleanUpIfFailedAndSetHrMsg(pNodeItem->selectSingleNode(KEY_INSTALLATION, &pNodeInstall)); if (NULL == pNodeInstall) goto CleanUp; CleanUpIfFailedAndSetHrMsg(pNodeInstall->selectNodes(KEY_CODEBASE, &pCodebaseList)); if (NULL == pCodebaseList) goto CleanUp; CleanUpIfFailedAndSetHrMsg(pCodebaseList->get_length(&lCodebaseCount)); if (0 == lCodebaseCount) goto CleanUp; // must be at least 1 cab // Loop through each Codebase Getting the Size for Each one CleanUpIfFailedAndSetHrMsg(pCodebaseList->nextNode(&pNodeCodebase)); while (NULL != pNodeCodebase) { // Get the Size Element CleanUpIfFailedAndSetHrMsg(pNodeCodebase->selectSingleNode(KEY_SIZE, &pNodeSize)); if (NULL != pNodeSize) { pNodeSize->get_text(&bstrCodebaseSize); if (NULL != bstrCodebaseSize) { // Add this Codebase's size to the total download size lTotalSize += (DWORD) MyBSTR2L(bstrCodebaseSize); SafeSysFreeString(bstrCodebaseSize); } } SafeReleaseNULL(pNodeSize); SafeReleaseNULL(pNodeCodebase); CleanUpIfFailedAndSetHrMsg(pCodebaseList->nextNode(&pNodeCodebase)); } SafeReleaseNULL(pCodebaseList); SafeReleaseNULL(pNodeInstall); SafeReleaseNULL(pNodeItem); CleanUpIfFailedAndSetHrMsg(pItemList->nextNode(&pNodeItem)); // get the next Item Node } // Update the Total Size after completing.. if we fail anywhere through here // we'll return 0. *plTotalSize = lTotalSize; CleanUp: SafeReleaseNULL(pParentNode); SafeReleaseNULL(pItemList); SafeReleaseNULL(pCodebaseList); SafeReleaseNULL(pNodeItem); SafeReleaseNULL(pNodeInstall); SafeReleaseNULL(pNodeCodebase); SafeReleaseNULL(pNodeSize); return hr; } ///////////////////////////////////////////////////////////////////////////// // FindItemByIdentity() // // Input: // pNodeIdentity - a pointer to an Identity Node to match against an Items // identity in the Catalog. We will search through each item // till we find a match with the supplied identity // // Output: // phNodeItem - Handle of the found Item // ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::FindItemByIdentity(IXMLDOMNode* pNodeIdentity, HANDLE_NODE* phNodeItem) { LOG_Block("FindItemByIdentity()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeIdentityDes = NULL; *phNodeItem = HANDLE_NODE_INVALID; HANDLE_NODE hNodeItem = HANDLE_NODE_INVALID; HANDLE_NODELIST hNodeList = HANDLE_NODELIST_INVALID; hNodeList = FindFirstDOMNode(m_pDocCatalog, KEY_ITEM_SEARCH, &hNodeItem); if (HANDLE_NODELIST_INVALID != hNodeList) { CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_IDENTITY, &pNodeIdentityDes)); if (AreNodesEqual(pNodeIdentityDes, pNodeIdentity)) { *phNodeItem = hNodeItem; goto CleanUp; } SafeReleaseNULL(pNodeIdentityDes); SafeReleaseNULL(m_ppNodeArray[hNodeItem]); while (SUCCEEDED(FindNextDOMNode(hNodeList, &hNodeItem))) { CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_IDENTITY, &pNodeIdentityDes)); if (AreNodesEqual(pNodeIdentityDes, pNodeIdentity)) { *phNodeItem = hNodeItem; goto CleanUp; } SafeReleaseNULL(pNodeIdentityDes); SafeReleaseNULL(m_ppNodeArray[hNodeItem]); } } CleanUp: CloseItemList(hNodeList); SafeReleaseNULL(pNodeIdentityDes); if (HANDLE_NODE_INVALID == *phNodeItem) { LOG_Error(_T("Can't find the matching Item Node in Catalog")); hr = E_FAIL; } return hr; } /* ///////////////////////////////////////////////////////////////////////////// // IfSameIdentity() // // Return TRUE if the two nodes are identical. Return FALSE otherwise. ///////////////////////////////////////////////////////////////////////////// BOOL CXmlCatalog::IfSameIdentity(IXMLDOMNode* pNodeIdentity1, IXMLDOMNode* pNodeIdentity2) { LOG_Block("IfSameIdentity()"); BOOL fResult = FALSE; BSTR bstrNameGUID = SysAllocString(L"guid"); BSTR bstrNameIDName = SysAllocString(L"name"); BSTR bstrNameIDPublisherName = SysAllocString(L"publisherName"); BSTR bstrNameType = SysAllocString(L"type"); BSTR bstrNameVersion = SysAllocString(L"version"); BSTR bstrNameLanguage = SysAllocString(L"language"); // // compare node // if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameGUID)) { goto CleanUp; } // // compare node // if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameIDPublisherName)) { goto CleanUp; } // // compare "name" attribute, this is a required attribute // if (!IfHasSameAttribute(pNodeIdentity1, pNodeIdentity2, bstrNameIDName, FALSE)) { goto CleanUp; } // // compare node // if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameType)) { goto CleanUp; } // // compare node, which really means "file version" here // if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameVersion)) { goto CleanUp; } // // compare node // if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameLanguage)) { goto CleanUp; } fResult = TRUE; CleanUp: SysFreeString(bstrNameGUID); SysFreeString(bstrNameIDName); SysFreeString(bstrNameIDPublisherName); SysFreeString(bstrNameType); SysFreeString(bstrNameVersion); SysFreeString(bstrNameLanguage); if (!fResult) { LOG_XML(_T("Different \'s found.")); } else { LOG_XML(_T("Same \'s found.")); } return fResult; } */ ///////////////////////////////////////////////////////////////////////////// // GetItemLanguage() // // Get the Language Entity from the Item Identity ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::GetItemLanguage(HANDLE_NODE hNodeItem, BSTR* pbstrLanguage) { HRESULT hr = S_OK; if (HANDLE_NODE_INVALID == hNodeItem || NULL == pbstrLanguage) { return E_INVALIDARG; } IXMLDOMNode *pNodeIdentity = NULL; IXMLDOMNode *pNodeLanguage = NULL; hr = FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_IDENTITY, &pNodeIdentity); if (FAILED(hr)) goto CleanUp; hr = FindSingleDOMNode(pNodeIdentity, KEY_LANGUAGE, &pNodeLanguage); if (FAILED(hr)) goto CleanUp; hr = GetText(pNodeLanguage, pbstrLanguage); if (FAILED(hr)) goto CleanUp; CleanUp: SafeReleaseNULL(pNodeLanguage); SafeReleaseNULL(pNodeIdentity); return hr; } ///////////////////////////////////////////////////////////////////////////// // GetCorpItemPlatformStr() // // Get the Simplified Platform String for an Item (uses the first available platform element) ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlCatalog::GetCorpItemPlatformStr(HANDLE_NODE hNodeItem, BSTR* pbstrPlatformStr) { HRESULT hr = S_OK; if (HANDLE_NODE_INVALID == hNodeItem || NULL == pbstrPlatformStr) { return E_INVALIDARG; } IXMLDOMNode *pNodePlatform = NULL; IXMLDOMNode *pNodePlatformArchitecture = NULL; IXMLDOMNode *pNodePlatformVersion = NULL; BSTR bstrPlatformName = NULL; BSTR bstrArchitecture = NULL; int iMajor = 0; int iMinor = 0; hr = FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_PLATFORM, &pNodePlatform); if (FAILED(hr)) goto CleanUp; hr = GetAttribute(pNodePlatform, KEY_NAME, &bstrPlatformName); if (FAILED(hr)) goto CleanUp; hr = FindSingleDOMNode(pNodePlatform, KEY_PROCESSORARCHITECTURE, &pNodePlatformArchitecture); if (FAILED(hr)) goto CleanUp; hr = FindSingleDOMNode(pNodePlatform, KEY_VERSION, &pNodePlatformVersion); if (FAILED(hr)) goto CleanUp; if (NULL != bstrPlatformName && 0 != SysStringLen(bstrPlatformName)) { if (CSTR_EQUAL == CompareStringW(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), NORM_IGNORECASE, bstrPlatformName, -1, L"VER_PLATFORM_WIN32_NT", -1)) { // this is an NT platform hr = GetAttribute(pNodePlatformVersion, KEY_MAJOR, &iMajor); if (FAILED(hr)) goto CleanUp; if (4 == iMajor) { // WinNT4 *pbstrPlatformStr = SysAllocString(CORP_PLATFORM_DIR_NT4); } else // 5 == iMajor { hr = GetAttribute(pNodePlatformVersion, KEY_MINOR, &iMinor); if (FAILED(hr)) goto CleanUp; if (iMinor > 0) { hr = GetText(pNodePlatformArchitecture, &bstrArchitecture); if (FAILED(hr)) goto CleanUp; // whistler if (CSTR_EQUAL == CompareStringW(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), NORM_IGNORECASE, bstrArchitecture, -1, L"x86", -1)) { // x86WinXP *pbstrPlatformStr = SysAllocString(CORP_PLATFORM_DIR_X86WHI); } else { // ia64WinXP *pbstrPlatformStr = SysAllocString(CORP_PLATFROM_DIR_IA64WHI); } } else { // x86Win2k *pbstrPlatformStr = SysAllocString(CORP_PLATFORM_DIR_NT5); } } } else // VER_PLATFORM_WIN32_WINDOWS { // this is a Win9x platform hr = GetAttribute(pNodePlatformVersion, KEY_MINOR, &iMinor); if (FAILED(hr)) goto CleanUp; if (iMinor >= 90) { // x86WinME *pbstrPlatformStr = SysAllocString(CORP_PLATFORM_DIR_WINME); } else if (iMinor > 0 && iMinor < 90) { // x86Win98 *pbstrPlatformStr = SysAllocString(CORP_PLATFORM_DIR_W98); } else { // x86Win95 *pbstrPlatformStr = SysAllocString(CORP_PLATFORM_DIR_W95); } } } CleanUp: SysFreeString(bstrPlatformName); SysFreeString(bstrArchitecture); SafeReleaseNULL(pNodePlatformVersion); SafeReleaseNULL(pNodePlatformArchitecture); SafeReleaseNULL(pNodePlatform); return hr; } ///////////////////////////////////////////////////////////////////////////// // CXmlItems ///////////////////////////////////////////////////////////////////////////// // Constructor // // Create IXMLDOMDocument* for Items; this is for write only ///////////////////////////////////////////////////////////////////////////// CXmlItems::CXmlItems() : m_pDocItems(NULL), m_pNodeItems(NULL) { LOG_Block("CXmlItems()"); Init(); } ///////////////////////////////////////////////////////////////////////////// // Constructor // // Create IXMLDOMDocument* for Items; take TRUE for read, FALSE for write ///////////////////////////////////////////////////////////////////////////// CXmlItems::CXmlItems(BOOL fRead) : m_pDocItems(NULL), m_pNodeItems(NULL) { LOG_Block("CXmlItems(BOOL fRead)"); // // for writing Items only // if (!fRead) { Init(); } } ///////////////////////////////////////////////////////////////////////////// // // Initialize XML DOC node pointers before writing ///////////////////////////////////////////////////////////////////////////// void CXmlItems::Init() { LOG_Block("Init()"); HRESULT hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void **) &m_pDocItems); if (FAILED(hr)) { LOG_ErrorMsg(hr); } else { IXMLDOMNode* pNodeXML = NULL; BSTR bstrNameSpaceSchema = NULL; // // create the node // pNodeXML = CreateDOMNode(m_pDocItems, NODE_PROCESSING_INSTRUCTION, KEY_XML); if (NULL == pNodeXML) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocItems, pNodeXML)); // // process the iuident.txt to find the Items schema path // TCHAR szIUDir[MAX_PATH]; TCHAR szIdentFile[MAX_PATH]; LPTSTR pszItemsSchema = NULL; LPTSTR pszNameSpaceSchema = NULL; pszItemsSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR)); if (NULL == pszItemsSchema) { LOG_ErrorMsg(E_OUTOFMEMORY); goto CleanUp; } pszNameSpaceSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR)); if (NULL == pszNameSpaceSchema) { LOG_ErrorMsg(E_OUTOFMEMORY); goto CleanUp; } GetIndustryUpdateDirectory(szIUDir); hr = PathCchCombine(szIdentFile, ARRAYSIZE(szIdentFile), szIUDir, IDENTTXT); if (FAILED(hr)) { LOG_ErrorMsg(hr); goto CleanUp; } GetPrivateProfileString(IDENT_IUSCHEMA, IDENT_IUSCHEMA_ITEMS, _T(""), pszItemsSchema, INTERNET_MAX_URL_LENGTH, szIdentFile); if ('\0' == pszItemsSchema[0]) { // no Items schema path specified in iuident.txt LOG_Error(_T("No schema path specified in iuident.txt for Items")); goto CleanUp; } hr = StringCchPrintfEx(pszNameSpaceSchema, INTERNET_MAX_URL_LENGTH, NULL, NULL, MISTSAFE_STRING_FLAGS, _T("x-schema:%s"), pszItemsSchema); if (FAILED(hr)) { LOG_ErrorMsg(hr); goto CleanUp; } bstrNameSpaceSchema = T2BSTR(pszNameSpaceSchema); // // create the node with the path of the schema // m_pNodeItems = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_ITEMS, bstrNameSpaceSchema); if (NULL == m_pNodeItems) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocItems, m_pNodeItems)); CleanUp: SafeReleaseNULL(pNodeXML); SysFreeString(bstrNameSpaceSchema); SafeHeapFree(pszItemsSchema); SafeHeapFree(pszNameSpaceSchema); } } ///////////////////////////////////////////////////////////////////////////// // Destructor // // Release IXMLDOMDocument* for Items ///////////////////////////////////////////////////////////////////////////// CXmlItems::~CXmlItems() { SafeReleaseNULL(m_pNodeItems); SafeReleaseNULL(m_pDocItems); } ///////////////////////////////////////////////////////////////////////////// // Clear() // // Reset IXMLDOMDocument* for Items ///////////////////////////////////////////////////////////////////////////// void CXmlItems::Clear() { SafeReleaseNULL(m_pNodeItems); SafeReleaseNULL(m_pDocItems); } ///////////////////////////////////////////////////////////////////////////// // LoadXMLDocument() // // Load an XML Document from string ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::LoadXMLDocument(BSTR bstrXml) { LOG_Block("LoadXMLDocument()"); SafeReleaseNULL(m_pDocItems); HRESULT hr = LoadXMLDoc(bstrXml, &m_pDocItems); if (FAILED(hr)) { LOG_ErrorMsg(hr); } return hr; } ///////////////////////////////////////////////////////////////////////////// // LoadXMLDocumentFile() // // Load an XML Document from the specified file ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::LoadXMLDocumentFile(BSTR bstrFilePath) { LOG_Block("LoadXMLDocumentFile()"); SafeReleaseNULL(m_pDocItems); HRESULT hr = LoadDocument(bstrFilePath, &m_pDocItems); if (FAILED(hr)) { LOG_ErrorMsg(hr); } return hr; } ///////////////////////////////////////////////////////////////////////////// // SaveXMLDocument() // // Save an XML Document to the specified location ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::SaveXMLDocument(BSTR bstrFilePath) { LOG_Block("SaveXMLDocument()"); HRESULT hr = SaveDocument(m_pDocItems, bstrFilePath); if (FAILED(hr)) { LOG_ErrorMsg(hr); } return hr; } ///////////////////////////////////////////////////////////////////////////// // AddGlobalErrorCodeIfNoItems() // // Add the errorCode attribute for if there's no child node ///////////////////////////////////////////////////////////////////////////// HANDLE_NODELIST CXmlItems::AddGlobalErrorCodeIfNoItems(DWORD dwErrorCode) { LOG_Block("AddGlobalErrorCodeIfNoItems()"); HRESULT hr = S_OK; IXMLDOMNode* pNodeItem = NULL; HANDLE_NODE hNodeItemStatus = HANDLE_NODE_INVALID; FindFirstDOMNode(m_pDocItems, KEY_ITEM_ITEMSTATUS, &hNodeItemStatus); if (HANDLE_NODE_INVALID == hNodeItemStatus) { // // set the "errorCode" attribute // FindFirstDOMNode(m_pDocItems, KEY_ITEMS, &pNodeItem); if (NULL != pNodeItem) { hr = SetAttribute(pNodeItem, KEY_ERRORCODE, dwErrorCode); } } SafeReleaseNULL(pNodeItem); return hr; } ///////////////////////////////////////////////////////////////////////////// // GetFirstItem() // // Find the first item in Items xml doc ///////////////////////////////////////////////////////////////////////////// HANDLE_NODELIST CXmlItems::GetFirstItem(HANDLE_NODE* phNodeItem) { LOG_Block("GetFirstItem()"); HANDLE_NODELIST hNodeListItem = FindFirstDOMNode(m_pDocItems, KEY_ITEM_ITEMSTATUS, phNodeItem); return hNodeListItem; } ///////////////////////////////////////////////////////////////////////////// // GetNextItem() // // Find the next item in Items xml doc ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::GetNextItem(HANDLE_NODELIST hNodeListItem, HANDLE_NODE* phNodeItem) { LOG_Block("GetNextItem()"); return FindNextDOMNode(hNodeListItem, phNodeItem); } ///////////////////////////////////////////////////////////////////////////// // CloseItemList() // // Release the item nodelist ///////////////////////////////////////////////////////////////////////////// void CXmlItems::CloseItemList(HANDLE_NODELIST hNodeListItem) { SafeFindCloseHandle(hNodeListItem); } ///////////////////////////////////////////////////////////////////////////// // GetItemDownloadPath() // // Retrieve the download path of the given item ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::GetItemDownloadPath(HANDLE_NODE hNodeItem, BSTR* pbstrDownloadPath) { LOG_Block("GetItemDownloadPath()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeDownloadPath = NULL; CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_DOWNLOADPATH, &pNodeDownloadPath)); CleanUpIfFailedAndSetHrMsg(GetText(pNodeDownloadPath, pbstrDownloadPath)); CleanUp: SafeReleaseNULL(pNodeDownloadPath); return hr; } ///////////////////////////////////////////////////////////////////////////// // GetItemDownloadPath() // // Retrieve the download path of the given item in catalog ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::GetItemDownloadPath(CXmlCatalog* pCatalog, HANDLE_NODE hNodeItem, BSTR* pbstrDownloadPath) { LOG_Block("GetItemDownloadPath() for an item in catalog"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeItem = NULL; IXMLDOMNode* pNodeDownloadPath = NULL; HANDLE_NODE hNodeItemsItem = HANDLE_NODE_INVALID; if (NULL != (pNodeItem = pCatalog->GetDOMNodebyHandle(hNodeItem))) { hr = FindItem(pNodeItem, &hNodeItemsItem, TRUE); } else { LOG_Error(_T("Can't retrieve valid item node from catalog xml")); hr = E_FAIL; goto CleanUp; } if (FAILED(hr) || HANDLE_NODE_INVALID == hNodeItemsItem) { LOG_Error(_T("Can't find item from Items xml")); goto CleanUp; } CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItemsItem], KEY_DOWNLOADPATH, &pNodeDownloadPath)); CleanUpIfFailedAndSetHrMsg(GetText(pNodeDownloadPath, pbstrDownloadPath)); CleanUp: SafeReleaseNULL(pNodeDownloadPath); return hr; } ///////////////////////////////////////////////////////////////////////////// // CloseItem() // // Release the item node ///////////////////////////////////////////////////////////////////////////// void CXmlItems::CloseItem(HANDLE_NODE hNodeItem) { SafeCloseHandleNode(hNodeItem); } ///////////////////////////////////////////////////////////////////////////// // FindItem() // // Input: // pNodeItem - the node of the install items xml; we need // to find the corresponding node in the existing // items xml with the identical , and // nodes. // Output: // phNodeItem - the handle we pass back to differentiate different // node in the existing items xml ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::FindItem(IXMLDOMNode* pNodeItem, HANDLE_NODE* phNodeItem, BOOL fIdentityOnly /*= FALSE*/) { LOG_Block("FindItem()"); HRESULT hr1, hr2, hr = E_FAIL; IXMLDOMNode* pNodeIdentitySrc = NULL; IXMLDOMNode* pNodeIdentityDes = NULL; IXMLDOMNode* pNodePlatformSrc = NULL; IXMLDOMNode* pNodePlatformDes = NULL; IXMLDOMNode* pNodeClientSrc = NULL; IXMLDOMNode* pNodeClientDes = NULL; *phNodeItem = HANDLE_NODE_INVALID; HANDLE_NODE hNodeItem = HANDLE_NODE_INVALID; HANDLE_NODELIST hNodeList = HANDLE_NODELIST_INVALID; hNodeList = FindFirstDOMNode(m_pDocItems, KEY_ITEM_ITEMSTATUS, &hNodeItem); if (HANDLE_NODELIST_INVALID != hNodeList) { CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_IDENTITY, &pNodeIdentityDes)); CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(pNodeItem, KEY_IDENTITY, &pNodeIdentitySrc)); if (AreNodesEqual(pNodeIdentityDes, pNodeIdentitySrc)) { if (fIdentityOnly) { // // we now found the match // *phNodeItem = hNodeItem; goto CleanUp; } else { hr1 = FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_PLATFORM, &pNodePlatformDes); hr2 = FindSingleDOMNode(pNodeItem, KEY_PLATFORM, &pNodePlatformSrc); if ((FAILED(hr1) && FAILED(hr2)) || (SUCCEEDED(hr1) && SUCCEEDED(hr2) && AreNodesEqual(pNodePlatformDes, pNodePlatformSrc))) { CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_CLIENT, &pNodeClientDes)); CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(pNodeItem, KEY_CLIENT, &pNodeClientSrc)); if (AreNodesEqual(pNodeClientDes, pNodeClientSrc)) { // // we now found the match // *phNodeItem = hNodeItem; goto CleanUp; } } } } SafeReleaseNULL(pNodeClientDes); SafeReleaseNULL(pNodeClientSrc); SafeReleaseNULL(pNodePlatformDes); SafeReleaseNULL(pNodePlatformSrc); SafeReleaseNULL(pNodeIdentityDes); SafeReleaseNULL(pNodeIdentitySrc); SafeReleaseNULL(m_ppNodeArray[hNodeItem]); while (SUCCEEDED(FindNextDOMNode(hNodeList, &hNodeItem))) { CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_IDENTITY, &pNodeIdentityDes)); CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(pNodeItem, KEY_IDENTITY, &pNodeIdentitySrc)); if (AreNodesEqual(pNodeIdentityDes, pNodeIdentitySrc)) { if (fIdentityOnly) { // // we now found the match // *phNodeItem = hNodeItem; goto CleanUp; } else { hr1 = FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_PLATFORM, &pNodePlatformDes); hr2 = FindSingleDOMNode(pNodeItem, KEY_PLATFORM, &pNodePlatformSrc); if ((FAILED(hr1) && FAILED(hr2)) || (SUCCEEDED(hr1) && SUCCEEDED(hr2) && AreNodesEqual(pNodePlatformDes, pNodePlatformSrc))) { CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_CLIENT, &pNodeClientDes)); CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(pNodeItem, KEY_CLIENT, &pNodeClientSrc)); if (AreNodesEqual(pNodeClientDes, pNodeClientSrc)) { // // we now found the match // *phNodeItem = hNodeItem; break; } } } } SafeReleaseNULL(pNodeClientDes); SafeReleaseNULL(pNodeClientSrc); SafeReleaseNULL(pNodePlatformDes); SafeReleaseNULL(pNodePlatformSrc); SafeReleaseNULL(pNodeIdentityDes); SafeReleaseNULL(pNodeIdentitySrc); SafeReleaseNULL(m_ppNodeArray[hNodeItem]); } } CleanUp: CloseItemList(hNodeList); SafeReleaseNULL(pNodeClientDes); SafeReleaseNULL(pNodeClientSrc); SafeReleaseNULL(pNodePlatformDes); SafeReleaseNULL(pNodePlatformSrc); SafeReleaseNULL(pNodeIdentityDes); SafeReleaseNULL(pNodeIdentitySrc); if (HANDLE_NODE_INVALID == *phNodeItem) { LOG_Error(_T("Can't find the identical item node in existing Items xml")); hr = E_FAIL; } return hr; } ///////////////////////////////////////////////////////////////////////////// // FindItem() // // Input: // pCatalog - the pointer to the CXmlCatalog object // hNodeItem - the handle of the node of the catalog xml; we need // to find the corresponding node in the existing // items xml with the identical , and // nodes. // Output: // phNodeItem - the handle we pass back to differentiate different // node in items xml ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::FindItem(CXmlCatalog* pCatalog, HANDLE_NODE hNodeItem, HANDLE_NODE* phNodeItem) { LOG_Block("FindItem() by handle"); IXMLDOMNode* pNode = NULL; if (NULL != (pNode = pCatalog->GetDOMNodebyHandle(hNodeItem))) { return FindItem(pNode, phNodeItem, TRUE); } LOG_Error(_T("Can't retrieve valid item node from catalog xml")); return E_FAIL; } /* ///////////////////////////////////////////////////////////////////////////// // IfSameClientInfo() // // Return TRUE if the two nodes are identical. Return FALSE otherwise. ///////////////////////////////////////////////////////////////////////////// BOOL CXmlItems::IfSameClientInfo(IXMLDOMNode* pNodeClient1, IXMLDOMNode* pNodeClient2) { LOG_Block("IfSameClientInfo()"); BSTR bstrText1 = NULL, bstrText2 = NULL; BOOL fResult = FALSE; GetText(pNodeClient1, &bstrText1); GetText(pNodeClient2, &bstrText2); if (NULL != bstrText1 && NULL != bstrText2) { fResult = CompareBSTRsEqual(bstrText1, bstrText2); } SysFreeString(bstrText1); SysFreeString(bstrText2); if (!fResult) { LOG_XML(_T("Different \'s found.")); } else { LOG_XML(_T("Same \'s found.")); } return fResult; } ///////////////////////////////////////////////////////////////////////////// // IfSameIdentity() // // Return TRUE if the two nodes are identical. Return FALSE otherwise. ///////////////////////////////////////////////////////////////////////////// BOOL CXmlItems::IfSameIdentity(IXMLDOMNode* pNodeIdentity1, IXMLDOMNode* pNodeIdentity2) { LOG_Block("IfSameIdentity()"); BOOL fResult = FALSE; BSTR bstrNameGUID = SysAllocString(L"guid"); BSTR bstrNameIDName = SysAllocString(L"name"); BSTR bstrNameIDPublisherName = SysAllocString(L"publisherName"); BSTR bstrNameType = SysAllocString(L"type"); BSTR bstrNameVersion = SysAllocString(L"version"); BSTR bstrNameLanguage = SysAllocString(L"language"); // // compare node // if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameGUID)) { goto CleanUp; } // // compare node // if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameIDPublisherName)) { goto CleanUp; } // // compare "name" attribute, this is a required attribute // if (!IfHasSameAttribute(pNodeIdentity1, pNodeIdentity2, bstrNameIDName, FALSE)) { goto CleanUp; } // // compare node // if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameType)) { goto CleanUp; } // // compare node, which really means "file version" here // if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameVersion)) { goto CleanUp; } // // compare node // if (!IfHasSameElement(pNodeIdentity1, pNodeIdentity2, bstrNameLanguage)) { goto CleanUp; } fResult = TRUE; CleanUp: SysFreeString(bstrNameGUID); SysFreeString(bstrNameIDName); SysFreeString(bstrNameIDPublisherName); SysFreeString(bstrNameType); SysFreeString(bstrNameVersion); SysFreeString(bstrNameLanguage); if (!fResult) { LOG_XML(_T("Different \'s found.")); } else { LOG_XML(_T("Same \'s found.")); } return fResult; } ///////////////////////////////////////////////////////////////////////////// // IfSamePlatform() // // Return TRUE if the two nodes are identical. Return FALSE otherwise. ///////////////////////////////////////////////////////////////////////////// BOOL CXmlItems::IfSamePlatform(IXMLDOMNode* pNodePlatform1, IXMLDOMNode* pNodePlatform2) { LOG_Block("IfSamePlatform()"); HRESULT hr1 = S_OK, hr2 = S_OK; BSTR bstrPlatform1 = NULL, bstrPlatform2 = NULL; BOOL fResult = FALSE; hr1 = pNodePlatform1->get_xml(&bstrPlatform1); hr2 = pNodePlatform2->get_xml(&bstrPlatform2); if (FAILED(hr1) || FAILED(hr2) || !CompareBSTRsEqual(bstrPlatform1, bstrPlatform2)) goto CleanUp; fResult = TRUE; CleanUp: SysFreeString(bstrPlatform1); SysFreeString(bstrPlatform2); return fResult; } */ ///////////////////////////////////////////////////////////////////////////// // MergeItemDownloaded() // // Insert items with download history into existing history (insert in front) ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::MergeItemDownloaded(CXmlItems *pHistoryDownload) { LOG_Block("MergeItemDownloaded()"); HRESULT hr = S_OK; IXMLDOMNode* pNodeItem = NULL; IXMLDOMNode* pNodeItemNew = NULL; IXMLDOMNode* pNodeItemRef = NULL; IXMLDOMNode* pNodeXML = NULL; BSTR bstrNameSpaceSchema = NULL; LPTSTR pszItemsSchema = NULL; LPTSTR pszNameSpaceSchema = NULL; HANDLE_NODE hNodeItem = HANDLE_NODE_INVALID; HANDLE_NODELIST hNodeListItem = HANDLE_NODELIST_INVALID; hNodeListItem = pHistoryDownload->GetFirstItem(&hNodeItem); if (HANDLE_NODELIST_INVALID != hNodeListItem) { // // if this is the first time writing history // (e.g. the log file does not exist yet), do // initialization for m_pDocItems here... // if (NULL == m_pDocItems) { hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void **) &m_pDocItems); if (FAILED(hr)) { LOG_ErrorMsg(hr); } else { // // create the node // pNodeXML = CreateDOMNode(m_pDocItems, NODE_PROCESSING_INSTRUCTION, KEY_XML); if (NULL == pNodeXML) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocItems, pNodeXML)); // // process the iuident.txt to find the Items schema path // TCHAR szIUDir[MAX_PATH]; TCHAR szIdentFile[MAX_PATH]; pszItemsSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR)); if (NULL == pszItemsSchema) { hr = E_OUTOFMEMORY; LOG_ErrorMsg(hr); goto CleanUp; } pszNameSpaceSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR)); if (NULL == pszNameSpaceSchema) { hr = E_OUTOFMEMORY; LOG_ErrorMsg(hr); goto CleanUp; } GetIndustryUpdateDirectory(szIUDir); hr = PathCchCombine(szIdentFile, ARRAYSIZE(szIdentFile), szIUDir, IDENTTXT); if (FAILED(hr)) { LOG_ErrorMsg(hr); goto CleanUp; } GetPrivateProfileString(IDENT_IUSCHEMA, IDENT_IUSCHEMA_ITEMS, _T(""), pszItemsSchema, INTERNET_MAX_URL_LENGTH, szIdentFile); if ('\0' == pszItemsSchema[0]) { // no Items schema path specified in iuident.txt LOG_Error(_T("No schema path specified in iuident.txt for Items")); goto CleanUp; } hr = StringCchPrintfEx(pszNameSpaceSchema, INTERNET_MAX_URL_LENGTH, NULL, NULL, MISTSAFE_STRING_FLAGS, _T("x-schema:%s"), pszItemsSchema); if (FAILED(hr)) { LOG_ErrorMsg(hr); goto CleanUp; } bstrNameSpaceSchema = T2BSTR(pszNameSpaceSchema); // // create the node with the path of the schema // m_pNodeItems = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_ITEMS, bstrNameSpaceSchema); if (NULL == m_pNodeItems) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocItems, m_pNodeItems)); } } else { SafeReleaseNULL(m_pNodeItems); FindSingleDOMNode(m_pDocItems, KEY_ITEMS, &m_pNodeItems); } if (NULL != m_pNodeItems) { if (NULL != (pNodeItem = pHistoryDownload->GetDOMNodebyHandle(hNodeItem))) { CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeItem, m_pDocItems, &pNodeItemNew)); CleanUpIfFailedAndSetHrMsg(m_pNodeItems->get_firstChild(&pNodeItemRef)); CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeItems, pNodeItemNew, pNodeItemRef)); // SafeReleaseNULL(pNodeItem); SafeReleaseNULL(pNodeItemNew); SafeReleaseNULL(pNodeItemRef); } while (SUCCEEDED(pHistoryDownload->GetNextItem(hNodeListItem, &hNodeItem))) { if (NULL != (pNodeItem = pHistoryDownload->GetDOMNodebyHandle(hNodeItem))) { CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeItem, m_pDocItems, &pNodeItemNew)); CleanUpIfFailedAndSetHrMsg(m_pNodeItems->get_firstChild(&pNodeItemRef)); CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeItems, pNodeItemNew, pNodeItemRef)); // SafeReleaseNULL(pNodeItem); SafeReleaseNULL(pNodeItemNew); SafeReleaseNULL(pNodeItemRef); } } } } CleanUp: pHistoryDownload->CloseItemList(hNodeListItem); // SafeReleaseNULL(pNodeItem); SafeReleaseNULL(pNodeItemNew); SafeReleaseNULL(pNodeItemRef); SafeReleaseNULL(pNodeXML); SysFreeString(bstrNameSpaceSchema); SafeHeapFree(pszItemsSchema); SafeHeapFree(pszNameSpaceSchema); return hr; } ///////////////////////////////////////////////////////////////////////////// // UpdateItemInstalled() // // Update items with installation history in existing history ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::UpdateItemInstalled(CXmlItems *pHistoryInstall) { LOG_Block("UpdateItemInstalled()"); USES_IU_CONVERSION; HRESULT hr = S_OK; IXMLDOMNode* pNodeItem = NULL; IXMLDOMNode* pNodeItemNew = NULL; IXMLDOMNode* pNodeItemRef = NULL; IXMLDOMNode* pNodeItemExist = NULL; IXMLDOMNode* pNodeInstall = NULL; IXMLDOMNode* pNodeInstallExist = NULL; IXMLDOMNode* pNodeInstallNew = NULL; IXMLDOMNode* pNodeInstallOut = NULL; IXMLDOMNode* pNodeXML = NULL; BSTR bstrInstallStatusExist = NULL; BSTR bstrInstallStatusNew = NULL; BSTR bstrTimeStamp = NULL; BSTR bstrNameSpaceSchema = NULL; LPTSTR pszItemsSchema = NULL; LPTSTR pszNameSpaceSchema = NULL; HANDLE_NODE hNodeItem = HANDLE_NODE_INVALID; HANDLE_NODE hNodeItemExist = HANDLE_NODE_INVALID; HANDLE_NODELIST hNodeListItem = HANDLE_NODELIST_INVALID; hNodeListItem = pHistoryInstall->GetFirstItem(&hNodeItem); if (HANDLE_NODELIST_INVALID != hNodeListItem) { // // if this is the first time writing history // (e.g. the log file does not exist yet), do // initialization for m_pDocItems here... // if (NULL == m_pDocItems) { hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void **) &m_pDocItems); if (FAILED(hr)) { LOG_ErrorMsg(hr); } else { // // create the node // pNodeXML = CreateDOMNode(m_pDocItems, NODE_PROCESSING_INSTRUCTION, KEY_XML); if (NULL == pNodeXML) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocItems, pNodeXML)); // // process the iuident.txt to find the Items schema path // TCHAR szIUDir[MAX_PATH]; TCHAR szIdentFile[MAX_PATH]; pszItemsSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR)); if (NULL == pszItemsSchema) { hr = E_OUTOFMEMORY; LOG_ErrorMsg(hr); goto CleanUp; } pszNameSpaceSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR)); if (NULL == pszNameSpaceSchema) { hr = E_OUTOFMEMORY; LOG_ErrorMsg(hr); goto CleanUp; } GetIndustryUpdateDirectory(szIUDir); hr = PathCchCombine(szIdentFile, ARRAYSIZE(szIdentFile), szIUDir, IDENTTXT); if (FAILED(hr)) { LOG_ErrorMsg(hr); goto CleanUp; } GetPrivateProfileString(IDENT_IUSCHEMA, IDENT_IUSCHEMA_ITEMS, _T(""), pszItemsSchema, INTERNET_MAX_URL_LENGTH, szIdentFile); if ('\0' == pszItemsSchema[0]) { // no Items schema path specified in iuident.txt LOG_Error(_T("No schema path specified in iuident.txt for Items")); goto CleanUp; } hr = StringCchPrintfEx(pszNameSpaceSchema, INTERNET_MAX_URL_LENGTH, NULL, NULL, MISTSAFE_STRING_FLAGS, _T("x-schema:%s"), pszItemsSchema); if (FAILED(hr)) { LOG_ErrorMsg(hr); goto CleanUp; } bstrNameSpaceSchema = T2BSTR(pszNameSpaceSchema); // // create the node with the path of the schema // m_pNodeItems = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_ITEMS, bstrNameSpaceSchema); if (NULL == m_pNodeItems) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocItems, m_pNodeItems)); } } else { SafeReleaseNULL(m_pNodeItems); CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_pDocItems, KEY_ITEMS, &m_pNodeItems)); } if (NULL != (pNodeItem = pHistoryInstall->GetDOMNodebyHandle(hNodeItem))) { if (SUCCEEDED(FindItem(pNodeItem, &hNodeItemExist))) { // // successfully found the match // if (NULL != (pNodeItemExist = GetDOMNodebyHandle(hNodeItemExist))) { CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(pNodeItem, KEY_INSTALLSTATUS, &pNodeInstall)); FindSingleDOMNode(pNodeItemExist, KEY_INSTALLSTATUS, &pNodeInstallExist); if (NULL != pNodeInstallExist) { // // found the item already with installStatus; now find out if we want to update // or append the installStatus // CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeInstallExist, KEY_VALUE, &bstrInstallStatusExist)); CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeInstall, KEY_VALUE, &bstrInstallStatusNew)); if (CSTR_EQUAL == WUCompareStringI(OLE2T(bstrInstallStatusExist), _T("IN_PROGRESS")) && CSTR_EQUAL != WUCompareStringI(OLE2T(bstrInstallStatusNew), _T("IN_PROGRESS"))) { // // this entry is an exclusive item with "IN_PROGRESS" installStatus and we found its // updated installStatus, we need to update its installStatus // LOG_Out(_T("Update the exclusive item's installStatus")); CleanUpIfFailedAndSetHrMsg(pNodeItemExist->removeChild(pNodeInstallExist, &pNodeInstallOut)); CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeInstall, m_pDocItems, &pNodeInstallNew)); CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeItemExist, pNodeInstallNew)); CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeItem, KEY_TIMESTAMP, &bstrTimeStamp)); CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeItemExist, KEY_TIMESTAMP, bstrTimeStamp)); SafeSysFreeString(bstrTimeStamp); } else { // // in this case we append a copy of this item with the new installStatus, since // this comes from a separate install operation // LOG_Out(_T("This item was installed again, add an entry of this item into history \ for the new installation status only.")); CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeItem, m_pDocItems, &pNodeItemNew)); CleanUpIfFailedAndSetHrMsg(m_pNodeItems->get_firstChild(&pNodeItemRef)); CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeItems, pNodeItemNew, pNodeItemRef)); } SafeSysFreeString(bstrInstallStatusExist); SafeSysFreeString(bstrInstallStatusNew); } else { // // found the item without installStatus, update the entry with the installStatus // and update the timeStamp with its installation timeStamp // CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeInstall, m_pDocItems, &pNodeInstallNew)); CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeItemExist, pNodeInstallNew)); CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeItem, KEY_TIMESTAMP, &bstrTimeStamp)); CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeItemExist, KEY_TIMESTAMP, bstrTimeStamp)); SafeSysFreeString(bstrTimeStamp); } } } else { // // no match found, this item was not downloaded through IU, // append this item with the install status // LOG_Out(_T("Can't find the downloaded item in existing history. This item was not downloaded \ through IU. Add the item into history for installation status only.")); CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeItem, m_pDocItems, &pNodeItemNew)); CleanUpIfFailedAndSetHrMsg(m_pNodeItems->get_firstChild(&pNodeItemRef)); CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeItems, pNodeItemNew, pNodeItemRef)); } // SafeReleaseNULL(pNodeItem); // SafeReleaseNULL(pNodeItemExist); SafeReleaseNULL(pNodeItemNew); SafeReleaseNULL(pNodeItemRef); SafeReleaseNULL(pNodeInstall); SafeReleaseNULL(pNodeInstallExist); SafeReleaseNULL(pNodeInstallNew); SafeReleaseNULL(pNodeInstallOut); } while (SUCCEEDED(pHistoryInstall->GetNextItem(hNodeListItem, &hNodeItem))) { if (NULL != (pNodeItem = pHistoryInstall->GetDOMNodebyHandle(hNodeItem))) { if (SUCCEEDED(FindItem(pNodeItem, &hNodeItemExist))) { // // successfully found the match // if (NULL != (pNodeItemExist = GetDOMNodebyHandle(hNodeItemExist))) { CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(pNodeItem, KEY_INSTALLSTATUS, &pNodeInstall)); FindSingleDOMNode(pNodeItemExist, KEY_INSTALLSTATUS, &pNodeInstallExist); if (NULL != pNodeInstallExist) { // // found the item already with installStatus; now find out if we want to update // or append the installStatus // CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeInstallExist, KEY_VALUE, &bstrInstallStatusExist)); CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeInstall, KEY_VALUE, &bstrInstallStatusNew)); if (CSTR_EQUAL == WUCompareStringI(OLE2T(bstrInstallStatusExist), _T("IN_PROGRESS")) && CSTR_EQUAL != WUCompareStringI(OLE2T(bstrInstallStatusNew), _T("IN_PROGRESS"))) { // // this entry is an exclusive item with "IN_PROGRESS" installStatus and we found its // updated installStatus, we need to update its installStatus // LOG_Out(_T("Update the exclusive item's installStatus")); CleanUpIfFailedAndSetHrMsg(pNodeItemExist->removeChild(pNodeInstallExist, &pNodeInstallOut)); CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeInstall, m_pDocItems, &pNodeInstallNew)); CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeItemExist, pNodeInstallNew)); CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeItem, KEY_TIMESTAMP, &bstrTimeStamp)); CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeItemExist, KEY_TIMESTAMP, bstrTimeStamp)); SafeSysFreeString(bstrTimeStamp); } else { // // in this case we append a copy of this item with the new installStatus, since // this comes from a separate install operation // LOG_Out(_T("This item was installed again, add an entry of this item into history \ for the new installation status only.")); CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeItem, m_pDocItems, &pNodeItemNew)); CleanUpIfFailedAndSetHrMsg(m_pNodeItems->get_firstChild(&pNodeItemRef)); CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeItems, pNodeItemNew, pNodeItemRef)); } SafeSysFreeString(bstrInstallStatusExist); SafeSysFreeString(bstrInstallStatusNew); } else { // // found the item without installStatus, update the entry with the installStatus // and update the timeStamp with its installation timeStamp // CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeInstall, m_pDocItems, &pNodeInstallNew)); CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeItemExist, pNodeInstallNew)); CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeItem, KEY_TIMESTAMP, &bstrTimeStamp)); CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeItemExist, KEY_TIMESTAMP, bstrTimeStamp)); SafeSysFreeString(bstrTimeStamp); } } } else { // // no match found, this item was not downloaded through IU, // append this item with the install status // LOG_Out(_T("Can't find the downloaded item in existing history. This item was not downloaded \ through IU. Add the item into history for installation status only.")); CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeItem, m_pDocItems, &pNodeItemNew)); CleanUpIfFailedAndSetHrMsg(m_pNodeItems->get_firstChild(&pNodeItemRef)); CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeItems, pNodeItemNew, pNodeItemRef)); } // SafeReleaseNULL(pNodeItem); // SafeReleaseNULL(pNodeItemExist); SafeReleaseNULL(pNodeItemNew); SafeReleaseNULL(pNodeItemRef); SafeReleaseNULL(pNodeInstall); SafeReleaseNULL(pNodeInstallExist); SafeReleaseNULL(pNodeInstallNew); SafeReleaseNULL(pNodeInstallOut); } } } CleanUp: pHistoryInstall->CloseItemList(hNodeListItem); // SafeReleaseNULL(pNodeItem); // SafeReleaseNULL(pNodeItemExist); SafeReleaseNULL(pNodeItemNew); SafeReleaseNULL(pNodeItemRef); SafeReleaseNULL(pNodeInstall); SafeReleaseNULL(pNodeInstallExist); SafeReleaseNULL(pNodeInstallNew); SafeReleaseNULL(pNodeInstallOut); SafeReleaseNULL(pNodeXML); SysFreeString(bstrInstallStatusExist); SysFreeString(bstrInstallStatusNew); SysFreeString(bstrTimeStamp); SysFreeString(bstrNameSpaceSchema); SafeHeapFree(pszItemsSchema); SafeHeapFree(pszNameSpaceSchema); return hr; } ///////////////////////////////////////////////////////////////////////////// // UpdateItemInstallStatus() // // Update the install status of the given item ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::UpdateItemInstallStatus(HANDLE_NODE hNodeItem, BSTR bstrValue, INT iNeedsReboot /*= -1*/, DWORD dwErrorCode /*= 0*/) { LOG_Block("UpdateItemInstallStatus()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeInstallStatus = NULL; // // get the node // CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(m_ppNodeArray[hNodeItem], KEY_INSTALLSTATUS, &pNodeInstallStatus)); // // set the "value" attribute // CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeInstallStatus, KEY_VALUE, bstrValue)); // // set the "needsReboot" attribute // if (-1 != iNeedsReboot) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeInstallStatus, KEY_NEEDSREBOOT, iNeedsReboot)); } // // set the "errorCode" attribute // if (0 != dwErrorCode) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeInstallStatus, KEY_ERRORCODE, dwErrorCode)); } CleanUp: SafeReleaseNULL(pNodeInstallStatus); return hr; } ///////////////////////////////////////////////////////////////////////////// // AddItem() // // Input: // pNodeItem - the node of the catalog xml; we need to read // node, node and nodes // from it and write to the items xml. // Output: // phNodeItem - the handle we pass back to differentiate different // node in items xml ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::AddItem(IXMLDOMNode* pNodeItem, HANDLE_NODE* phNodeItem) { LOG_Block("AddItem()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeIndentity = NULL; IXMLDOMNode* pNodeIndentityNew = NULL; IXMLDOMNode* pNodeDescription = NULL; IXMLDOMNode* pNodeDescriptionNew = NULL; IXMLDOMNode* pNodePlatform = NULL; IXMLDOMNode* pNodePlatformNew = NULL; HANDLE_NODELIST hNodeList = HANDLE_NODELIST_INVALID; *phNodeItem = CreateDOMNodeWithHandle(m_pDocItems, NODE_ELEMENT, KEY_ITEMSTATUS); if (HANDLE_NODE_INVALID == *phNodeItem) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(m_pNodeItems, m_ppNodeArray[*phNodeItem])); hNodeList = FindFirstDOMNode(pNodeItem, KEY_IDENTITY, &pNodeIndentity); if (HANDLE_NODELIST_INVALID != hNodeList) { SafeFindCloseHandle(hNodeList); CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeIndentity, m_pDocItems, &pNodeIndentityNew)); CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[*phNodeItem], pNodeIndentityNew)); } hNodeList = FindFirstDOMNode(pNodeItem, KEY_DESCRIPTION, &pNodeDescription); if (HANDLE_NODELIST_INVALID != hNodeList) { SafeFindCloseHandle(hNodeList); CleanUpIfFailedAndSetHrMsg(CopyNode(pNodeDescription, m_pDocItems, &pNodeDescriptionNew)); CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[*phNodeItem], pNodeDescriptionNew)); } hNodeList = FindFirstDOMNode(pNodeItem, KEY_PLATFORM, &pNodePlatform); if (HANDLE_NODELIST_INVALID != hNodeList) { CleanUpIfFailedAndSetHrMsg(CopyNode(pNodePlatform, m_pDocItems, &pNodePlatformNew)); CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[*phNodeItem], pNodePlatformNew)); SafeReleaseNULL(pNodePlatform); SafeReleaseNULL(pNodePlatformNew); while (SUCCEEDED(FindNextDOMNode(hNodeList, &pNodePlatform))) { CleanUpIfFailedAndSetHrMsg(CopyNode(pNodePlatform, m_pDocItems, &pNodePlatformNew)); CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[*phNodeItem], pNodePlatformNew)); SafeReleaseNULL(pNodePlatform); SafeReleaseNULL(pNodePlatformNew); } } CleanUp: if (HANDLE_NODELIST_INVALID != hNodeList) { SafeFindCloseHandle(hNodeList); } SafeReleaseNULL(pNodeIndentity); SafeReleaseNULL(pNodeIndentityNew); SafeReleaseNULL(pNodeDescription); SafeReleaseNULL(pNodeDescriptionNew); SafeReleaseNULL(pNodePlatform); SafeReleaseNULL(pNodePlatformNew); return hr; } ///////////////////////////////////////////////////////////////////////////// // AddItem() // // Input: // pCatalog - the pointer to the CXmlCatalog object // hNodeItem - the handle of the node of the catalog xml; we need // to read node, node and // nodes from it and write to the items xml. // Output: // phNodeItem - the handle we pass back to differentiate different // node in items xml ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::AddItem(CXmlCatalog* pCatalog, HANDLE_NODE hNodeItem, HANDLE_NODE* phNodeItem) { LOG_Block("AddItem() by handle"); IXMLDOMNode* pNode = NULL; if (NULL != (pNode = pCatalog->GetDOMNodebyHandle(hNodeItem))) { return AddItem(pNode, phNodeItem); } LOG_Error(_T("Can't retrieve valid item node from catalog xml")); return E_FAIL; } ///////////////////////////////////////////////////////////////////////////// // AddTimeStamp() ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::AddTimeStamp(HANDLE_NODE hNodeItem) { LOG_Block("AddTimeStamp()"); USES_IU_CONVERSION; HRESULT hr = E_FAIL; TCHAR szTimestamp[32]; SYSTEMTIME stTimestamp; BSTR bstrTimeStamp = NULL; GetLocalTime(&stTimestamp); hr = StringCchPrintfEx(szTimestamp, ARRAYSIZE(szTimestamp), NULL, NULL, MISTSAFE_STRING_FLAGS, _T("%4d-%02d-%02dT%02d:%02d:%02d"), // "ISO 8601" format for "datatime" datatype in xml stTimestamp.wYear, stTimestamp.wMonth, stTimestamp.wDay, stTimestamp.wHour, stTimestamp.wMinute, stTimestamp.wSecond); CleanUpIfFailedAndSetHrMsg(hr); bstrTimeStamp = SysAllocString(T2OLE(szTimestamp)); // // set the "timestamp" attribute // CleanUpIfFailedAndSetHrMsg(SetAttribute(m_ppNodeArray[hNodeItem], KEY_TIMESTAMP, bstrTimeStamp)); CleanUp: SysFreeString(bstrTimeStamp); return hr; } ///////////////////////////////////////////////////////////////////////////// // AddDetectResult() ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::AddDetectResult(HANDLE_NODE hNodeItem, INT iInstalled /*= -1*/, INT iUpToDate /*= -1*/, INT iNewerVersion /*= -1*/, INT iExcluded /*= -1*/, INT iForce /*= -1*/, INT iComputerSystem /* = -1 */) { LOG_Block("AddDetectResult()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeDetectResult = NULL; // // create the node // pNodeDetectResult = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_DETECTRESULT); if (NULL == pNodeDetectResult) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[hNodeItem], pNodeDetectResult)); // // set the "installed" attribute // if (-1 != iInstalled) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDetectResult, KEY_INSTALLED, iInstalled)); } // // set the "upToDate" attribute // if (-1 != iUpToDate) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDetectResult, KEY_UPTODATE, iUpToDate)); } // // set the "newerVersion" attribute // if (-1 != iNewerVersion) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDetectResult, KEY_NEWERVERSION, iNewerVersion)); } // // set the "excluded" attribute // if (-1 != iExcluded) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDetectResult, KEY_EXCLUDED, iExcluded)); } // // set the "force" attribute // if (-1 != iForce) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDetectResult, KEY_FORCE, iForce)); } // // set computerSystem attribute // if (-1 != iComputerSystem) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDetectResult, KEY_COMPUTERSYSTEM, iComputerSystem)); } CleanUp: SafeReleaseNULL(pNodeDetectResult); return hr; } ///////////////////////////////////////////////////////////////////////////// // AddDownloadStatus() ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::AddDownloadStatus(HANDLE_NODE hNodeItem, BSTR bstrValue, DWORD dwErrorCode /*= 0*/) { LOG_Block("AddDownloadStatus()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeDownloadStatus = NULL; // // create the node // pNodeDownloadStatus = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_DOWNLOADSTATUS); if (NULL == pNodeDownloadStatus) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[hNodeItem], pNodeDownloadStatus)); // // set the "value" attribute // CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDownloadStatus, KEY_VALUE, bstrValue)); // // set the "errorCode" attribute // if (0 != dwErrorCode) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeDownloadStatus, KEY_ERRORCODE, dwErrorCode)); } CleanUp: SafeReleaseNULL(pNodeDownloadStatus); return hr; } ///////////////////////////////////////////////////////////////////////////// // AddDownloadPath() ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::AddDownloadPath(HANDLE_NODE hNodeItem, BSTR bstrDownloadPath) { LOG_Block("AddDownloadPath()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeDownloadPath = NULL; IXMLDOMNode* pNodeDownloadPathText = NULL; pNodeDownloadPath = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_DOWNLOADPATH); if (NULL == pNodeDownloadPath) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[hNodeItem], pNodeDownloadPath)); pNodeDownloadPathText = CreateDOMNode(m_pDocItems, NODE_TEXT, NULL); if (NULL == pNodeDownloadPathText) goto CleanUp; CleanUpIfFailedAndSetHrMsg(SetValue(pNodeDownloadPathText, bstrDownloadPath)); CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeDownloadPath, pNodeDownloadPathText)); CleanUp: SafeReleaseNULL(pNodeDownloadPath); SafeReleaseNULL(pNodeDownloadPathText); return hr; } ///////////////////////////////////////////////////////////////////////////// // AddInstallStatus() ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::AddInstallStatus(HANDLE_NODE hNodeItem, BSTR bstrValue, BOOL fNeedsReboot, DWORD dwErrorCode /*= 0*/) { LOG_Block("AddInstallStatus()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeInstallStatus = NULL; // // create the node // pNodeInstallStatus = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_INSTALLSTATUS); if (NULL == pNodeInstallStatus) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[hNodeItem], pNodeInstallStatus)); // // set the "value" attribute // CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeInstallStatus, KEY_VALUE, bstrValue)); // // set the "needsReboot" attribute // CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeInstallStatus, KEY_NEEDSREBOOT, fNeedsReboot)); // // set the "errorCode" attribute // if (0 != dwErrorCode) { CleanUpIfFailedAndSetHrMsg(SetAttribute(pNodeInstallStatus, KEY_ERRORCODE, dwErrorCode)); } CleanUp: SafeReleaseNULL(pNodeInstallStatus); return hr; } ///////////////////////////////////////////////////////////////////////////// // AddClientInfo() ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::AddClientInfo(HANDLE_NODE hNodeItem, BSTR bstrClient) { LOG_Block("AddClientInfo()"); HRESULT hr = E_FAIL; IXMLDOMNode* pNodeClient = NULL; IXMLDOMNode* pNodeClientText = NULL; pNodeClient = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_CLIENT); if (NULL == pNodeClient) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(m_ppNodeArray[hNodeItem], pNodeClient)); pNodeClientText = CreateDOMNode(m_pDocItems, NODE_TEXT, NULL); if (NULL == pNodeClientText) goto CleanUp; CleanUpIfFailedAndSetHrMsg(SetValue(pNodeClientText, bstrClient)); CleanUpIfFailedAndSetHrMsg(InsertNode(pNodeClient, pNodeClientText)); CleanUp: SafeReleaseNULL(pNodeClient); SafeReleaseNULL(pNodeClientText); return hr; } ///////////////////////////////////////////////////////////////////////////// // MigrateV3History() // // Migrate V3 History: Consumer history only. ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::MigrateV3History(LPCTSTR pszHistoryFilePath) { LOG_Block("MigrateV3History()"); HRESULT hr = S_OK; IXMLDOMNode* pNodeXML = NULL; IXMLDOMNode* pNodeItemStatus = NULL; IXMLDOMNode* pNodeIdentity = NULL; IXMLDOMNode* pNodeDescription = NULL; IXMLDOMNode* pNodeDescriptionText = NULL; IXMLDOMNode* pNodeTitle = NULL; IXMLDOMNode* pNodeTitleText = NULL; IXMLDOMNode* pNodeVersion = NULL; IXMLDOMNode* pNodeVersionText = NULL; IXMLDOMNode* pNodeInstallStatus = NULL; IXMLDOMNode* pNodeClient = NULL; IXMLDOMNode* pNodeClientText = NULL; BSTR bstrNameSpaceSchema = NULL, bstrStatus = NULL, bstrString = NULL; LPTSTR pszItemsSchema = NULL; LPTSTR pszNameSpaceSchema = NULL; CV3AppLog V3History(pszHistoryFilePath); char szLineType[32]; char szTemp[32]; char szDate[32]; char szTime[32]; char szPUID[32]; // puid - migrate to char szTitle[256]; // title - migrate to ->-> char szVersion[40]; // version - migrate to <identity>-><version> char szTimeStamp[32]; // timestamp - migrate to <itemStatus "timestamp"> char szResult[16]; // result - migrate to <installStatus "value"> char szErrCode[16]; // errorcode - migrate to <installStatus "errorCode"> USES_IU_CONVERSION; V3History.StartReading(); while (V3History.ReadLine()) { SafeSysFreeString(bstrString); // get line type (first field) V3History.CopyNextField(szLineType, ARRAYSIZE(szLineType)); if ((_stricmp(szLineType, LOG_V3CAT) == 0) || (_stricmp(szLineType, LOG_V3_2) == 0)) { // get "puid" field V3History.CopyNextField(szPUID, ARRAYSIZE(szPUID)); // get "operation" field: installed/uninstalled // we only migrate installed item V3History.CopyNextField(szTemp, ARRAYSIZE(szTemp)); if (0 != _stricmp(szTemp, LOG_INSTALL)) continue; // // now we start to create <itemStatus> node for this item // if (NULL == m_pDocItems) { // // we don't have IU history file yet // hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void **) &m_pDocItems); if (FAILED(hr)) { LOG_ErrorMsg(hr); } else { // // create the <?xml version="1.0"?> node // pNodeXML = CreateDOMNode(m_pDocItems, NODE_PROCESSING_INSTRUCTION, KEY_XML); if (NULL == pNodeXML) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocItems, pNodeXML)); // // process the iuident.txt to find the Items schema path // TCHAR szIUDir[MAX_PATH]; TCHAR szIdentFile[MAX_PATH]; pszItemsSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR)); if (NULL == pszItemsSchema) { hr = E_OUTOFMEMORY; LOG_ErrorMsg(hr); goto CleanUp; } pszNameSpaceSchema = (LPTSTR) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERNET_MAX_URL_LENGTH * sizeof(TCHAR)); if (NULL == pszNameSpaceSchema) { hr = E_OUTOFMEMORY; LOG_ErrorMsg(hr); goto CleanUp; } GetIndustryUpdateDirectory(szIUDir); hr = PathCchCombine(szIdentFile, ARRAYSIZE(szIdentFile), szIUDir, IDENTTXT); if (FAILED(hr)) { LOG_ErrorMsg(hr); goto CleanUp; } GetPrivateProfileString(IDENT_IUSCHEMA, IDENT_IUSCHEMA_ITEMS, _T(""), pszItemsSchema, INTERNET_MAX_URL_LENGTH, szIdentFile); if ('\0' == pszItemsSchema[0]) { // no Items schema path specified in iuident.txt LOG_Error(_T("No schema path specified in iuident.txt for Items")); goto CleanUp; } hr = StringCchPrintfEx(pszNameSpaceSchema, INTERNET_MAX_URL_LENGTH, NULL, NULL, MISTSAFE_STRING_FLAGS, _T("x-schema:%s"), pszItemsSchema); if (FAILED(hr)) { LOG_ErrorMsg(hr); goto CleanUp; } bstrNameSpaceSchema = T2BSTR(pszNameSpaceSchema); // // create the <items> node with the path of the schema // m_pNodeItems = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_ITEMS, bstrNameSpaceSchema); if (NULL == m_pNodeItems) goto CleanUp; CleanUpIfFailedAndSetHrMsg(InsertNode(m_pDocItems, m_pNodeItems)); } } else { SafeReleaseNULL(m_pNodeItems); FindSingleDOMNode(m_pDocItems, KEY_ITEMS, &m_pNodeItems); } // create <itemStatus> node pNodeItemStatus = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_ITEMSTATUS); if (NULL == pNodeItemStatus) continue; SkipIfFail(InsertNode(m_pNodeItems, pNodeItemStatus)); // create <client> node pNodeClient = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_CLIENT); if (NULL == pNodeClient) continue; pNodeClientText = CreateDOMNode(m_pDocItems, NODE_TEXT, NULL); if (NULL == pNodeClientText) continue; BSTR bstrV3Client = SysAllocString(C_V3_CLIENTINFO); SkipIfFail(SetValue(pNodeClientText, bstrV3Client)); SkipIfFail(InsertNode(pNodeClient, pNodeClientText)); SkipIfFail(InsertNode(pNodeItemStatus, pNodeClient)); SafeSysFreeString(bstrV3Client); // create <identity> node pNodeIdentity = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_IDENTITY); if (NULL == pNodeIdentity) continue; SkipIfFail(InsertNode(pNodeItemStatus, pNodeIdentity)); // set the "name" attribute for <identity> bstrString = SysAllocString(A2OLE(szPUID)); SkipIfFail(SetAttribute(pNodeIdentity, KEY_NAME, bstrString)); // set the "itemID" attribute for <identity> SkipIfFail(SetAttribute(pNodeIdentity, KEY_ITEMID, bstrString)); SafeSysFreeString(bstrString); // get "title" field V3History.CopyNextField(szTitle, ARRAYSIZE(szTitle)); // create <description> node pNodeDescription = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_DESCRIPTION); if (NULL == pNodeDescription) continue; SkipIfFail(SetAttribute(pNodeDescription, KEY_HIDDEN, 0)); SkipIfFail(InsertNode(pNodeItemStatus, pNodeDescription)); // create <descriptionText> node pNodeDescriptionText = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_DESCRIPTIONTEXT); if (NULL == pNodeDescriptionText) continue; SkipIfFail(InsertNode(pNodeDescription, pNodeDescriptionText)); // create <title> node pNodeTitle = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_TITLE); if (NULL == pNodeTitle) continue; pNodeTitleText = CreateDOMNode(m_pDocItems, NODE_TEXT, NULL); if (NULL == pNodeTitleText) continue; bstrString = SysAllocString(A2OLE(szTitle)); SkipIfFail(SetValue(pNodeTitleText, bstrString)); SkipIfFail(InsertNode(pNodeTitle, pNodeTitleText)); SkipIfFail(InsertNode(pNodeDescriptionText, pNodeTitle)); SafeSysFreeString(bstrString); // get "version" field V3History.CopyNextField(szVersion, ARRAYSIZE(szVersion)); // create <version> node pNodeVersion = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_VERSION); if (NULL == pNodeVersion) continue; pNodeVersionText = CreateDOMNode(m_pDocItems, NODE_TEXT, NULL); if (NULL == pNodeVersionText) continue; bstrString = SysAllocString(A2OLE(szVersion)); SkipIfFail(SetValue(pNodeVersionText, bstrString)); SkipIfFail(InsertNode(pNodeVersion, pNodeVersionText)); SkipIfFail(InsertNode(pNodeIdentity, pNodeVersion)); SafeSysFreeString(bstrString); // get timestamp if ((_stricmp(szLineType, LOG_V3_2) == 0)) { // read the timestamp and convert to "ISO 8601" format for "datatime" datatype in xml: // for example, 2001-05-01T18:30:00 // so we only need to replace the space with 'T' // timestamp V3History.CopyNextField(szTimeStamp, ARRAYSIZE(szTimeStamp)); char *p = strchr(szTimeStamp, ' '); if (NULL != p) // if (NULL == p): there's no space then leave it as is to pass into SetAttribute { *p = 'T'; } } else { // V3 Beta had two fields for date and time, we need read both these fields: // date V3History.CopyNextField(szDate, ARRAYSIZE(szDate)); // time V3History.CopyNextField(szTime, ARRAYSIZE(szTime)); hr = StringCchPrintfExA(szTimeStamp, ARRAYSIZE(szTimeStamp), NULL, NULL, MISTSAFE_STRING_FLAGS, "%sT%s", szDate, szTime); SkipIfFail(hr); } // set the "timestamp" attribute for <itemStatus> bstrString = SysAllocString(A2OLE(szTimeStamp)); SkipIfFail(SetAttribute(pNodeItemStatus, KEY_TIMESTAMP, bstrString)); SafeSysFreeString(bstrString); // skip the "record type" field V3History.CopyNextField(szTemp, ARRAYSIZE(szTemp)); // get "result" field V3History.CopyNextField(szResult, ARRAYSIZE(szResult)); // create <InstallStatus> node pNodeInstallStatus = CreateDOMNode(m_pDocItems, NODE_ELEMENT, KEY_INSTALLSTATUS); if (NULL == pNodeInstallStatus) continue; SkipIfFail(InsertNode(pNodeItemStatus, pNodeInstallStatus)); // set the "value" attribute for <installStatus> if (_stricmp(szResult, LOG_SUCCESS) == 0) { bstrStatus = SysAllocString(L"COMPLETE"); } else if (_stricmp(szTemp, LOG_STARTED) == 0) { bstrStatus = SysAllocString(L"IN_PROGRESS"); } else { bstrStatus = SysAllocString(L"FAILED"); } SkipIfFail(SetAttribute(pNodeInstallStatus, KEY_VALUE, bstrStatus)); if (_stricmp(szResult, LOG_SUCCESS) != 0) { // get "error code" field V3History.CopyNextField(szErrCode, ARRAYSIZE(szErrCode)); // set the "errorCode" attribute for <installStatus> SkipIfFail(SetAttribute(pNodeInstallStatus, KEY_ERRORCODE, atoh(szErrCode))); } } } V3History.StopReading(); CleanUp: SafeReleaseNULL(pNodeXML); SafeReleaseNULL(pNodeItemStatus); SafeReleaseNULL(pNodeIdentity); SafeReleaseNULL(pNodeDescriptionText); SafeReleaseNULL(pNodeTitle); SafeReleaseNULL(pNodeTitleText); SafeReleaseNULL(pNodeVersion); SafeReleaseNULL(pNodeVersionText); SafeReleaseNULL(pNodeInstallStatus); SafeReleaseNULL(pNodeClient); SafeReleaseNULL(pNodeClientText); SysFreeString(bstrString); SysFreeString(bstrNameSpaceSchema); SysFreeString(bstrStatus); SafeHeapFree(pszItemsSchema); SafeHeapFree(pszNameSpaceSchema); return hr; } ///////////////////////////////////////////////////////////////////////////// // GetItemsBSTR() ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::GetItemsBSTR(BSTR *pbstrXmlItems) { LOG_Block("GetItemsBSTR()"); if (NULL == m_pDocItems) { *pbstrXmlItems = NULL; return S_OK; } // // convert XML DOC into BSTR // HRESULT hr = m_pDocItems->get_xml(pbstrXmlItems); if (FAILED(hr)) { LOG_ErrorMsg(hr); } return hr; } ///////////////////////////////////////////////////////////////////////////// // GetFilteredHistoryBSTR() ///////////////////////////////////////////////////////////////////////////// HRESULT CXmlItems::GetFilteredHistoryBSTR(BSTR bstrBeginDateTime, BSTR bstrEndDateTime, BSTR bstrClient, BSTR *pbstrXmlHistory) { LOG_Block("GetFilteredHistoryBSTR()"); USES_IU_CONVERSION; HRESULT hr = S_OK; IXMLDOMNode* pNodeItems = NULL; IXMLDOMNode* pNodeItem = NULL; IXMLDOMNode* pNodeItemOut = NULL; IXMLDOMNode* pNodeClient = NULL; BSTR bstrTimeStamp = NULL; BSTR bstrClientInfo = NULL; BOOL fOutOfRange = FALSE; HANDLE_NODELIST hNodeList = HANDLE_NODELIST_INVALID; if (NULL == pbstrXmlHistory) { SetHrMsgAndGotoCleanUp(E_INVALIDARG); } if (NULL != m_pDocItems) { if (SUCCEEDED(FindSingleDOMNode(m_pDocItems, KEY_ITEMS, &pNodeItems))) { hNodeList = FindFirstDOMNode(pNodeItems, KEY_ITEMSTATUS, &pNodeItem); if (HANDLE_NODELIST_INVALID != hNodeList) { CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeItem, KEY_TIMESTAMP, &bstrTimeStamp)); if (NULL != bstrTimeStamp) { if ((NULL != bstrBeginDateTime) && (0 != SysStringLen(bstrBeginDateTime)) && (CompareBSTRs(bstrTimeStamp, bstrBeginDateTime) < 0)) { // // remove the item whose timestamp is out of range; // set the flag to ignore the timestamp comparison for the rest of nodes // CleanUpIfFailedAndSetHrMsg(pNodeItems->removeChild(pNodeItem, &pNodeItemOut)); fOutOfRange = TRUE; } else if ((NULL != bstrEndDateTime) && (0 != SysStringLen(bstrEndDateTime)) && (CompareBSTRs(bstrTimeStamp, bstrEndDateTime) > 0)) { // // remove the item whose timestamp is out of range // CleanUpIfFailedAndSetHrMsg(pNodeItems->removeChild(pNodeItem, &pNodeItemOut)); } else { CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(pNodeItem, KEY_CLIENT, &pNodeClient)); CleanUpIfFailedAndSetHrMsg(GetText(pNodeClient, &bstrClientInfo)); if ((NULL != bstrClient) && (0 != SysStringLen(bstrClient)) && (WUCompareStringI(OLE2T(bstrClientInfo), OLE2T(bstrClient)) != CSTR_EQUAL)) { // // remove the item whose clieninfo does not match what we need // CleanUpIfFailedAndSetHrMsg(pNodeItems->removeChild(pNodeItem, &pNodeItemOut)); } } } SafeReleaseNULL(pNodeItem); SafeReleaseNULL(pNodeItemOut); SafeReleaseNULL(pNodeClient); SafeSysFreeString(bstrTimeStamp); SafeSysFreeString(bstrClientInfo); while (SUCCEEDED(FindNextDOMNode(hNodeList, &pNodeItem))) { if (fOutOfRange) { // // remove the item whose timestamp is out of range // CleanUpIfFailedAndSetHrMsg(pNodeItems->removeChild(pNodeItem, &pNodeItemOut)); } else { CleanUpIfFailedAndSetHrMsg(GetAttribute(pNodeItem, KEY_TIMESTAMP, &bstrTimeStamp)); if (NULL != bstrTimeStamp) { if ((NULL != bstrBeginDateTime) && (0 != SysStringLen(bstrBeginDateTime)) && (CompareBSTRs(bstrTimeStamp, bstrBeginDateTime) < 0)) { // // remove the item whose timestamp is out of range; // set the flag to ignore the timestamp comparison for the rest of nodes // CleanUpIfFailedAndSetHrMsg(pNodeItems->removeChild(pNodeItem, &pNodeItemOut)); fOutOfRange = TRUE; } else if ((NULL != bstrEndDateTime) && (0 != SysStringLen(bstrEndDateTime)) && (CompareBSTRs(bstrTimeStamp, bstrEndDateTime) > 0)) { // // remove the item whose timestamp is out of range // CleanUpIfFailedAndSetHrMsg(pNodeItems->removeChild(pNodeItem, &pNodeItemOut)); } else { CleanUpIfFailedAndSetHrMsg(FindSingleDOMNode(pNodeItem, KEY_CLIENT, &pNodeClient)); CleanUpIfFailedAndSetHrMsg(GetText(pNodeClient, &bstrClientInfo)); if ((NULL != bstrClient) && (0 != SysStringLen(bstrClient)) && (WUCompareStringI(OLE2T(bstrClientInfo), OLE2T(bstrClient)) != CSTR_EQUAL)) { // // remove the item whose clieninfo does not match what we need // CleanUpIfFailedAndSetHrMsg(pNodeItems->removeChild(pNodeItem, &pNodeItemOut)); } } } } SafeReleaseNULL(pNodeItem); SafeReleaseNULL(pNodeItemOut); SafeReleaseNULL(pNodeClient); SafeSysFreeString(bstrTimeStamp); SafeSysFreeString(bstrClientInfo); } } } } CleanUp: CloseItemList(hNodeList); SafeReleaseNULL(pNodeItems); SafeReleaseNULL(pNodeItem); SafeReleaseNULL(pNodeItemOut); SafeReleaseNULL(pNodeClient); SysFreeString(bstrTimeStamp); SysFreeString(bstrClientInfo); if (SUCCEEDED(hr)) { hr = GetItemsBSTR(pbstrXmlHistory); } return hr; } ///////////////////////////////////////////////////////////////////////////// // CXmlClientInfo CXmlClientInfo::CXmlClientInfo() : m_pDocClientInfo(NULL) { } CXmlClientInfo::~CXmlClientInfo() { SafeReleaseNULL(m_pDocClientInfo); } // // load and parse and validate an XML document from string // HRESULT CXmlClientInfo::LoadXMLDocument(BSTR bstrXml, BOOL fOfflineMode) { LOG_Block("CXmlClientInfo::LoadXMLDocument()"); SafeReleaseNULL(m_pDocClientInfo); HRESULT hr = LoadXMLDoc(bstrXml, &m_pDocClientInfo, fOfflineMode); if (FAILED(hr)) { LOG_ErrorMsg(hr); } return hr; } // // retrieve client name attribute // HRESULT CXmlClientInfo::GetClientName(BSTR* pbstrClientName) { HRESULT hr= E_UNEXPECTED; IXMLDOMElement* pElement = NULL; BSTR bstrTagName = NULL; VARIANT vAttr; VariantInit(&vAttr); LOG_Block("GetClientName()"); if (NULL == pbstrClientName) { return E_INVALIDARG; } if (NULL == m_pDocClientInfo) { return hr; } hr = m_pDocClientInfo->get_documentElement(&pElement); CleanUpIfFailedAndMsg(hr); if (NULL == pElement) { // // no root element // hr = E_INVALIDARG; // clientInfo is bad! return this error back to caller LOG_ErrorMsg(hr); goto CleanUp; } hr = pElement->get_tagName(&bstrTagName); CleanUpIfFailedAndMsg(hr); if (!CompareBSTRsEqual(bstrTagName, KEY_CLIENTINFO)) { // // root is not clientInfo // hr = E_INVALIDARG; LOG_ErrorMsg(hr); goto CleanUp; } hr = pElement->getAttribute(KEY_CLIENTNAME, &vAttr); CleanUpIfFailedAndMsg(hr); if (VT_BSTR == vAttr.vt) { *pbstrClientName = SysAllocString(vAttr.bstrVal); } else { hr = E_FAIL; CleanUpIfFailedAndMsg(hr); } CleanUp: SafeReleaseNULL(pElement); if (bstrTagName) { SysFreeString(bstrTagName); bstrTagName = NULL; } VariantClear(&vAttr); return hr; }