示例#1
0
/*
	 Function name		: CXML::Delete
	 Description	    : This helper function delete the node supplied node
	 Return type		: bool 
	 Argument			: IXMLDOMNode **ppRemoveNode
	 Tested				: Ok
 */	
bool CXML::Delete(IXMLDOMNode **ppRemoveNode)
{
	if(!(*ppRemoveNode)) return false;

	IXMLDOMNode * pParentNode = NULL;
	IXMLDOMNode * pRemovedNode = NULL;

	m_hr = (*ppRemoveNode)->get_parentNode(&pParentNode );
	if(!SUCCEEDED(m_hr) || !pParentNode)
		return false;


	m_hr = pParentNode->removeChild(*ppRemoveNode,&pRemovedNode);
	pParentNode->Release();
	if(!SUCCEEDED(m_hr) || !pRemovedNode)
		return false;

	pRemovedNode->Release();
	return true;
}
示例#2
0
// New
bool COpcXmlDocument::New(IXMLDOMElement* ipElement)
{
    HRESULT hResult = S_OK;

    IXMLDOMElement* ipClone  = NULL;
    IXMLDOMNode*    ipParent = NULL;
    IXMLDOMNode*    ipResult = NULL;

    TRY
    {
        // create new document instance.
        if (!New())
        {
            THROW_(hResult, E_FAIL);
        }

        // clone the element.
        hResult = ipElement->cloneNode(VARIANT_TRUE, (IXMLDOMNode**)&ipClone);

        if (FAILED(hResult))
        {
            THROW();
        }

        // remove clone from parent.
        hResult = ipClone->get_parentNode(&ipParent);

        if (FAILED(hResult))
        {
            THROW();
        }

        if (ipParent != NULL)
        {
            hResult = ipParent->removeChild(ipClone, &ipResult);

            if (FAILED(hResult))
            {
                THROW();
            }

            if (ipResult != NULL)
            {
                ipResult->Release();
                ipResult = NULL;
            }
        }

        // add root element to document.
        hResult = m_ipDocument->appendChild(ipClone, &ipResult);

        if (FAILED(hResult))
        {
            THROW();
        }

        if (ipResult != NULL)
        {
            ipResult->Release();
            ipResult = NULL;
        }

        // declare element as the document element.
        hResult = m_ipDocument->putref_documentElement(ipClone);

        if (FAILED(hResult))
        {
            THROW();
        }

        // add predefined namespaces
        AddNamespace(TAG_XSD, OPCXML_NS_SCHEMA);
        AddNamespace(TAG_XSI, OPCXML_NS_SCHEMA_INSTANCE);
    }

    CATCH
    {
        Clear();
    }

    FINALLY
    {
        // release memory.
        if (ipClone != NULL)  ipClone->Release();
        if (ipParent != NULL) ipParent->Release();
        if (ipResult != NULL) ipResult->Release();
    }

    return SUCCEEDED(hResult);
}
示例#3
0
文件: XmlConfig.cpp 项目: BMurri/wix3
/******************************************************************
 ExecXmlConfig - entry point for XmlConfig Custom Action

*******************************************************************/
extern "C" UINT __stdcall ExecXmlConfig(
    __in MSIHANDLE hInstall
    )
{
    //AssertSz(FALSE, "debug ExecXmlConfig");
    HRESULT hr = S_OK;
    HRESULT hrOpenFailure = S_OK;
    UINT er = ERROR_SUCCESS;

    BOOL fIsWow64Process = FALSE;
    BOOL fIsFSRedirectDisabled = FALSE;
    BOOL fPreserveDate = FALSE;

    LPWSTR pwzCustomActionData = NULL;
    LPWSTR pwzData = NULL;
    LPWSTR pwzFile = NULL;
    LPWSTR pwzElementPath = NULL;
    LPWSTR pwzVerifyPath = NULL;
    LPWSTR pwzName = NULL;
    LPWSTR pwzValue = NULL;
    LPWSTR pwz = NULL;
    int cAdditionalChanges = 0;

    IXMLDOMDocument* pixd = NULL;
    IXMLDOMNode* pixn = NULL;
    IXMLDOMNode* pixnVerify = NULL;
    IXMLDOMNode* pixnNewNode = NULL;
    IXMLDOMNode* pixnRemovedChild = NULL;

    IXMLDOMDocument* pixdNew = NULL;
    IXMLDOMElement* pixeNew = NULL;

    FILETIME ft;

    int id = IDRETRY;

    eXmlAction xa;
    eXmlPreserveDate xd;

    // initialize
    hr = WcaInitialize(hInstall, "ExecXmlConfig");
    ExitOnFailure(hr, "failed to initialize");

    hr = XmlInitialize();
    ExitOnFailure(hr, "failed to initialize xml utilities");

    hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData);
    ExitOnFailure(hr, "failed to get CustomActionData");

    WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData);

    pwz = pwzCustomActionData;

    hr = WcaReadIntegerFromCaData(&pwz, (int*) &xa);
    ExitOnFailure(hr, "failed to process CustomActionData");

    // Initialize the Wow64 API - store the result in fWow64APIPresent
    // If it fails, this doesn't warrant an error yet, because we only need the Wow64 API in some cases
    WcaInitializeWow64();
    fIsWow64Process = WcaIsWow64Process();

    if (xaOpenFile != xa && xaOpenFilex64 != xa)
    {
        ExitOnFailure(hr = E_INVALIDARG, "invalid custom action data");
    }

    // loop through all the passed in data
    while (pwz && *pwz)
    {
        hr = WcaReadStringFromCaData(&pwz, &pwzFile);
        ExitOnFailure(hr, "failed to read file name from custom action data");

        // Default to not preserve date, preserve it if any modifications require us to
        fPreserveDate = FALSE;

        // Open the file
        ReleaseNullObject(pixd);

        if (xaOpenFilex64 == xa)
        {
            if (!fIsWow64Process)
            {
                hr = E_NOTIMPL;
                ExitOnFailure(hr, "Custom action was told to act on a 64-bit component, but the custom action process is not running in WOW.");
            }

            hr = WcaDisableWow64FSRedirection();
            ExitOnFailure(hr, "Custom action was told to act on a 64-bit component, but was unable to disable filesystem redirection through the Wow64 API.");

            fIsFSRedirectDisabled = TRUE;
        }

        hr = XmlLoadDocumentFromFileEx(pwzFile, XML_LOAD_PRESERVE_WHITESPACE, &pixd);
        if (FAILED(hr))
        {
            // Ignore the return code for now.  If they try to add something, we'll fail the install.  If all they do is remove stuff then it doesn't matter.
            hrOpenFailure = hr;
            hr = S_OK;
        }
        else
        {
            hrOpenFailure = S_OK;
        }

        WcaLog(LOGMSG_VERBOSE, "Configuring Xml File: %ls", pwzFile);

        while (pwz && *pwz)
        {
            // If we skip past an element that has additional changes we need to strip them off the stream before
            // moving on to the next element. Do that now and then restart the outer loop.
            if (cAdditionalChanges > 0)
            {
                while (cAdditionalChanges > 0)
                {
                    hr = WcaReadStringFromCaData(&pwz, &pwzName);
                    ExitOnFailure(hr, "failed to process CustomActionData");
                    hr = WcaReadStringFromCaData(&pwz, &pwzValue);
                    ExitOnFailure(hr, "failed to process CustomActionData");

                    cAdditionalChanges--;
                }
                continue;
            }

            hr = WcaReadIntegerFromCaData(&pwz, (int*) &xa);
            ExitOnFailure(hr, "failed to process CustomActionData");

            // Break if we need to move on to a different file
            if (xaOpenFile == xa || xaOpenFilex64 == xa)
            {
                break;
            }

            hr = WcaReadIntegerFromCaData(&pwz, (int*) &xd);
            ExitOnFailure(hr, "failed to process CustomActionData");

            if (xdPreserve == xd)
            {
                fPreserveDate = TRUE;
            }

            // Get path, name, and value to be written
            hr = WcaReadStringFromCaData(&pwz, &pwzElementPath);
            ExitOnFailure(hr, "failed to process CustomActionData");
            hr = WcaReadStringFromCaData(&pwz, &pwzVerifyPath);
            ExitOnFailure(hr, "failed to process CustomActionData");
            hr = WcaReadStringFromCaData(&pwz, &pwzName);
            ExitOnFailure(hr, "failed to process CustomActionData");
            hr = WcaReadStringFromCaData(&pwz, &pwzValue);
            ExitOnFailure(hr, "failed to process CustomActionData");
            hr = WcaReadIntegerFromCaData(&pwz, &cAdditionalChanges);
            ExitOnFailure(hr, "failed to process CustomActionData");

            // If we failed to open the file and we're adding something to the file, we've got a problem.  Otherwise, just continue on since the file's already gone.
            if (FAILED(hrOpenFailure))
            {
                if (xaCreateElement == xa || xaWriteValue == xa || xaWriteDocument == xa)
                {
                    MessageExitOnFailure1(hr = hrOpenFailure, msierrXmlConfigFailedOpen, "failed to load XML file: %ls", pwzFile);
                }
                else
                {
                    continue;
                }
            }

            // Select the node we're about to modify
            ReleaseNullObject(pixn);

            hr = XmlSelectSingleNode(pixd, pwzElementPath, &pixn);

            // If we failed to find the node that we are going to add to, we've got a problem. Otherwise, just continue since the node's already gone.
            if (S_FALSE == hr)
            {
                if (xaCreateElement == xa || xaWriteValue == xa || xaWriteDocument == xa)
                {
                    hr = HRESULT_FROM_WIN32(ERROR_OBJECT_NOT_FOUND);
                }
                else
                {
                    hr = S_OK;
                    continue;
                }
            }

            MessageExitOnFailure2(hr, msierrXmlConfigFailedSelect, "failed to find node: %ls in XML file: %ls", pwzElementPath, pwzFile);

            // Make the modification
            switch (xa)
            {
            case xaWriteValue:
                if (pwzName && *pwzName)
                {
                    // We're setting an attribute
                    hr = XmlSetAttribute(pixn, pwzName, pwzValue);
                    ExitOnFailure2(hr, "failed to set attribute: %ls to value %ls", pwzName, pwzValue);
                }
                else
                {
                    // We're setting the text of the node
                    hr = XmlSetText(pixn, pwzValue);
                    ExitOnFailure2(hr, "failed to set text to: %ls for element %ls.  Make sure that XPath points to an element.", pwzValue, pwzElementPath);
                }
                break;
            case xaWriteDocument:
                if (NULL != pwzVerifyPath && 0 != pwzVerifyPath[0])
                {
                    hr = XmlSelectSingleNode(pixn, pwzVerifyPath, &pixnVerify);
                    if (S_OK == hr)
                    {
                        // We found the verify path which means we have no further work to do
                        continue;
                    }
                    ExitOnFailure1(hr, "failed to query verify path: %ls", pwzVerifyPath);
                }

                hr = XmlLoadDocumentEx(pwzValue, XML_LOAD_PRESERVE_WHITESPACE, &pixdNew);
                ExitOnFailure(hr, "Failed to load value as document.");

                hr = pixdNew->get_documentElement(&pixeNew);
                ExitOnFailure(hr, "Failed to get document element.");

                hr = pixn->appendChild(pixeNew, NULL);
                ExitOnFailure(hr, "Failed to append document element on to parent element.");

                ReleaseNullObject(pixeNew);
                ReleaseNullObject(pixdNew);
                break;

            case xaCreateElement:
                if (NULL != pwzVerifyPath && 0 != pwzVerifyPath[0])
                {
                    hr = XmlSelectSingleNode(pixn, pwzVerifyPath, &pixnVerify);
                    if (S_OK == hr)
                    {
                        // We found the verify path which means we have no further work to do
                        continue;
                    }
                    ExitOnFailure1(hr, "failed to query verify path: %ls", pwzVerifyPath);
                }

                hr = XmlCreateChild(pixn, pwzName, &pixnNewNode);
                ExitOnFailure1(hr, "failed to create child element: %ls", pwzName);

                if (pwzValue && *pwzValue)
                {
                    hr = XmlSetText(pixnNewNode, pwzValue);
                    ExitOnFailure2(hr, "failed to set text to: %ls for node: %ls", pwzValue, pwzName);
                }

                while (cAdditionalChanges > 0)
                {
                    hr = WcaReadStringFromCaData(&pwz, &pwzName);
                    ExitOnFailure(hr, "failed to process CustomActionData");
                    hr = WcaReadStringFromCaData(&pwz, &pwzValue);
                    ExitOnFailure(hr, "failed to process CustomActionData");

                    // Set the additional attribute
                    hr = XmlSetAttribute(pixnNewNode, pwzName, pwzValue);
                    ExitOnFailure2(hr, "failed to set attribute: %ls to value %ls", pwzName, pwzValue);

                    cAdditionalChanges--;
                }

                ReleaseNullObject(pixnNewNode);
                break;
            case xaDeleteValue:
                if (pwzName && *pwzName)
                {
                    // Delete the attribute
                    hr = XmlRemoveAttribute(pixn, pwzName);
                    ExitOnFailure1(hr, "failed to remove attribute: %ls", pwzName);
                }
                else
                {
                    // Clear the text value for the node
                    hr = XmlSetText(pixn, L"");
                    ExitOnFailure(hr, "failed to clear text value");
                }
                break;
            case xaDeleteElement:
                if (NULL != pwzVerifyPath && 0 != pwzVerifyPath[0])
                {
                    hr = XmlSelectSingleNode(pixn, pwzVerifyPath, &pixnVerify);
                    if (S_OK == hr)
                    {
                        hr = pixn->removeChild(pixnVerify, &pixnRemovedChild);
                        ExitOnFailure(hr, "failed to remove created child element");

                        ReleaseNullObject(pixnRemovedChild);
                    }
                    else
                    {
                        WcaLog(LOGMSG_VERBOSE, "Failed to select path %ls for deleting.  Skipping...", pwzVerifyPath);
                        hr = S_OK;
                    }
                }
                else
                {
                    // TODO: This requires a VerifyPath to delete an element.  Should we support not having one?
                    WcaLog(LOGMSG_VERBOSE, "No VerifyPath specified for delete element of ID: %ls", pwzElementPath);
                }
                break;
            default:
                ExitOnFailure(hr = E_UNEXPECTED, "Invalid modification specified in custom action data");
                break;
            }
        }


        // Now that we've made all of the changes to this file, save it and move on to the next
        if (S_OK == hrOpenFailure)
        {
            if (fPreserveDate)
            {
                hr = FileGetTime(pwzFile, NULL, NULL, &ft);
                ExitOnFailure1(hr, "failed to get modified time of file : %ls", pwzFile);
            }

            int iSaveAttempt = 0;

            do
            {
                hr = XmlSaveDocument(pixd, pwzFile);
                if (FAILED(hr))
                {
                    id = WcaErrorMessage(msierrXmlConfigFailedSave, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 1, pwzFile);
                    switch (id)
                    {
                    case IDABORT:
                        ExitOnFailure1(hr, "Failed to save changes to XML file: %ls", pwzFile);
                    case IDRETRY:
                        hr = S_FALSE;   // hit me, baby, one more time
                        break;
                    case IDIGNORE:
                        hr = S_OK;  // pretend everything is okay and bail
                        break;
                    case 0: // No UI case, MsiProcessMessage returns 0
                        if (STIERR_SHARING_VIOLATION == hr)
                        {
                            // Only in case of sharing violation do we retry 30 times, once a second.
                            if (iSaveAttempt < 30)
                            {
                                hr = S_FALSE;
                                ++iSaveAttempt;
                                WcaLog(LOGMSG_VERBOSE, "Unable to save changes to XML file: %ls, retry attempt: %x", pwzFile, iSaveAttempt);
                                Sleep(1000);
                            }
                            else
                            {
                                ExitOnFailure1(hr, "Failed to save changes to XML file: %ls", pwzFile);
                            }
                        }
                        break;
                    default: // Unknown error
                        ExitOnFailure1(hr, "Failed to save changes to XML file: %ls", pwzFile);
                    }
                }
            } while (S_FALSE == hr);

            if (fPreserveDate)
            {
                hr = FileSetTime(pwzFile, NULL, NULL, &ft);
                ExitOnFailure1(hr, "failed to set modified time of file : %ls", pwzFile);
            }

            if (fIsFSRedirectDisabled)
            {
                fIsFSRedirectDisabled = FALSE;
                WcaRevertWow64FSRedirection();
            }
        }
    }

LExit:
    // Make sure we revert FS Redirection if necessary before exiting
    if (fIsFSRedirectDisabled)
    {
        fIsFSRedirectDisabled = FALSE;
        WcaRevertWow64FSRedirection();
    }
    WcaFinalizeWow64();

    ReleaseStr(pwzCustomActionData);
    ReleaseStr(pwzData);
    ReleaseStr(pwzFile);
    ReleaseStr(pwzElementPath);
    ReleaseStr(pwzVerifyPath);
    ReleaseStr(pwzName);
    ReleaseStr(pwzValue);

    ReleaseObject(pixeNew);
    ReleaseObject(pixdNew);

    ReleaseObject(pixn);
    ReleaseObject(pixd);
    ReleaseObject(pixnNewNode);
    ReleaseObject(pixnRemovedChild);

    XmlUninitialize();

    if (FAILED(hr))
    {
        er = ERROR_INSTALL_FAILURE;
    }
    return WcaFinalize(er);
}
示例#4
0
//void SettingsXML::Save(const wchar_t *regName, const wchar_t *value)
//{
//	if (!value) value = L"";  // сюда мог придти и NULL
//
//	Save(regName, (LPCBYTE)value, REG_SZ, (_tcslen(value)+1)*sizeof(wchar_t));
//}
void SettingsXML::Save(const wchar_t *regName, LPCBYTE value, DWORD nType, DWORD nSize)
{
	HRESULT hr = S_OK;
	IXMLDOMNamedNodeMap* pAttrs = NULL;
	IXMLDOMNodeList* pList = NULL;
	IXMLDOMAttribute *pIXMLDOMAttribute = NULL;
	IXMLDOMNode *pNode = NULL;
	IXMLDOMNode* pChild = NULL;
	IXMLDOMNode *pNodeRmv = NULL;
	BSTR bsValue = NULL;
	BSTR bsType = NULL;
	bool bNeedSetType = false;
	// nType:
	// REG_DWORD:    сохранение числа в 16-ричном или 10-чном формате, в зависимости от того, что сейчас указано в xml ("dword"/"ulong"/"long")
	// REG_BINARY:   строго в hex (FF,FF,...)
	// REG_SZ:       ASCIIZ строка, можно проконтролировать, чтобы nSize/2 не был меньше длины строки
	// REG_MULTI_SZ: ASCIIZZ. При формировании <list...> нужно убедиться, что мы не вылезли за пределы nSize
	pChild = FindItem(mp_Key, L"value", regName, true); // создать, если его еще нету

	if (!pChild)
		goto wrap;

	hr = pChild->get_attributes(&pAttrs);

	if (FAILED(hr) || !pAttrs)
		goto wrap;

	bsType = GetAttr(pChild, pAttrs, L"type");

	switch (nType)
	{
		case REG_DWORD:
		{
			wchar_t szValue[32];

			if (bsType && (bsType[0] == L'u' || bsType[0] == L'U'))
			{
				_wsprintf(szValue, SKIPLEN(countof(szValue)) L"%u", *(LPDWORD)value);
			}
			else if (bsType && (bsType[0] == L'l' || bsType[0] == L'L'))
			{
				_wsprintf(szValue, SKIPLEN(countof(szValue)) L"%i", *(int*)value);
			}
			else
			{
				_wsprintf(szValue, SKIPLEN(countof(szValue)) L"%08x", *(LPDWORD)value);

				if (bsType) ::SysFreeString(bsType);

				// нужно добавить/установить тип
				bsType = ::SysAllocString(L"dword"); bNeedSetType = true;
			}

			bsValue = ::SysAllocString(szValue);
		} break;
		case REG_BINARY:
		{
			if (nSize == 1 && bsType && (bsType[0] == L'u' || bsType[0] == L'U'))
			{
				wchar_t szValue[4];
				BYTE bt = *value;
				_wsprintf(szValue, SKIPLEN(countof(szValue)) L"%u", (DWORD)bt);
				bsValue = ::SysAllocString(szValue);
			}
			else if (nSize == 1 && bsType && (bsType[0] == L'l' || bsType[0] == L'L'))
			{
				wchar_t szValue[4];
				char bt = *value;
				_wsprintf(szValue, SKIPLEN(countof(szValue)) L"%i", (int)bt);
				bsValue = ::SysAllocString(szValue);
			}
			else
			{
				DWORD nLen = nSize*2 + (nSize-1); // по 2 символа на байт + ',' между ними
				bsValue = ::SysAllocStringLen(NULL, nLen);
				nLen ++; // Чтобы далее не добавлять WCHAR на '\0'
				wchar_t* psz = (wchar_t*)bsValue;
				LPCBYTE  ptr = value;

				while (nSize)
				{
					_wsprintf(psz, SKIPLEN(nLen-(psz-bsValue)) L"%02x", (DWORD)*ptr);
					ptr++; nSize--; psz+=2;

					if (nSize)
						*(psz++) = L',';
				}

				if (bsType && lstrcmp(bsType, L"hex"))
				{
					// Допустим только "hex"
					::SysFreeString(bsType); bsType = NULL;
				}

				if (!bsType)
				{
					// нужно добавить/установить тип
					bsType = ::SysAllocString(L"hex"); bNeedSetType = true;
				}
			}
		} break;
		case REG_SZ:
		{
			wchar_t* psz = (wchar_t*)value;
			bsValue = ::SysAllocString(psz);

			if (bsType && lstrcmp(bsType, L"string"))
			{
				// Допустим только "string"
				::SysFreeString(bsType); bsType = NULL;
			}

			if (!bsType)
			{
				// нужно добавить/установить тип
				bsType = ::SysAllocString(L"string"); bNeedSetType = true;
			}
		} break;
		case REG_MULTI_SZ:
		{
			if (bsType && lstrcmp(bsType, L"multi"))
			{
				// Допустим только "multi"
				::SysFreeString(bsType); bsType = NULL;
			}

			if (!bsType)
			{
				// нужно добавить/установить тип
				bsType = ::SysAllocString(L"multi"); bNeedSetType = true;
			}
		} break;
		default:
			goto wrap; // не поддерживается
	}

	if (bNeedSetType)
	{
		_ASSERTE(bsType!=NULL);
		SetAttr(pChild, pAttrs, L"type", bsType);
		::SysFreeString(bsType); bsType = NULL;
	}

	// Теперь собственно значение
	if (nType != REG_MULTI_SZ)
	{
		_ASSERTE(bsValue != NULL);
		SetAttr(pChild, pAttrs, L"data", bsValue);
		::SysFreeString(bsValue); bsValue = NULL;
	}
	else     // Тут нужно формировать список элементов <list>
	{
		// Если ранее был параметр "data" - удалить его из списка атрибутов
		hr = pAttrs->getNamedItem(L"data", &pNode);
		if (SUCCEEDED(hr) && pNode)
		{
			hr = pChild->removeChild(pNode, &pNodeRmv);
			pNode->Release(); pNode = NULL;
			SetDataChanged();

			if (pNodeRmv) { pNodeRmv->Release(); pNodeRmv = NULL; }
		}

		long nAllLen = nSize/2; // длина в wchar_t
		wchar_t* psz = (wchar_t*)value;
		SetMultiLine(pChild, psz, nAllLen);
	}

	mb_Modified = true;
wrap:

	if (pIXMLDOMAttribute) { pIXMLDOMAttribute->Release(); pIXMLDOMAttribute = NULL; }

	if (pNode) { pNode->Release(); pNode = NULL; }

	if (pNodeRmv) { pNodeRmv->Release(); pNodeRmv = NULL; }

	if (pChild) { pChild->Release(); pChild = NULL; }

	if (pAttrs) { pAttrs->Release(); pAttrs = NULL; }

	if (bsValue) { ::SysFreeString(bsValue); bsValue = NULL; }

	if (bsType) { ::SysFreeString(bsType); bsType = NULL; }
}