コード例 #1
0
ファイル: DBHistory.cpp プロジェクト: Hpark11/FIES
HRESULT CDBHistory::UpdateHistory(HDBCONNECTION hDBConnection,
									int nIndex,
									LPCWSTR lpszComment,
									BSTR* pbstrResult)
{
	HRESULT hr = E_FAIL;

	IMT::CDBConnection* pDBConnection = reinterpret_cast<IMT::CDBConnection*>(hDBConnection);
	if (pDBConnection != NULL)
	{
		ATL::CCommand<ATL::CDynamicAccessor> Command;

		ATL::CDBPropSet _DBPropSet(DBPROPSET_ROWSET);
		pDBConnection->GetRowsetProperties(&_DBPropSet);

		CAtlStringW strCommand;

		strCommand.Format(QUERY_HISTORY_UPDATE, lpszComment, nIndex);

		hr = Command.Open(ATL::CSession(*pDBConnection), strCommand, &_DBPropSet);
		if (hr != S_OK)
		{
			if (pbstrResult != NULL)
				IMT::GetDBErrorString(hr, pbstrResult);
		}
		else
		{
			TRACE(_T(":::[CDBHistory]-[UPDATE] SUCCEEDED :::\n"));
		}
	}

	return hr;
}
コード例 #2
0
ファイル: DBConnection.cpp プロジェクト: Hpark11/FIES
HRESULT CDBConnection::OpenDataSource(LPCWSTR lpszPathFileName, LPCWSTR lpszUserName, LPCWSTR lpszPassword)
{
	_ASSERTE(lpszPathFileName != NULL);
	_ASSERTE(lpszUserName != NULL);
	_ASSERTE(lpszPassword != NULL);

	USES_CONVERSION;

	HRESULT hr = E_FAIL;

	if (lpszPathFileName != NULL && lpszUserName != NULL && lpszPassword != NULL)
	{
		if (::PathFileExists(lpszPathFileName))
		{
			CAtlStringW strConnection;

			strConnection.Format(
#if defined(USES_JET_OLEDB_DRIVER)
				L"Provider=Microsoft.Jet.OLEDB.4.0;"
#else
				L"Provider=Microsoft.ACE.OLEDB.12.0;"
#endif
				L"Data Source=%s;"
				L"User ID=%s;"
				L"Mode=Share Deny None;"
				L"Extended Properties=\"\";"
				L"Jet OLEDB:System database=\"\";"
				L"Jet OLEDB:Registry Path=\"\";"
				L"Jet OLEDB:Database Password=\"%s\";"
				L"Jet OLEDB:Engine Type=5;"
				L"Jet OLEDB:Database Locking Mode=1;"
				L"Jet OLEDB:Global Partial Bulk Ops=2;"
				L"Jet OLEDB:Global Bulk Transactions=1;"
				L"Jet OLEDB:New Database Password=\"\";"
				L"Jet OLEDB:Create System Database=False;"
				L"Jet OLEDB:Encrypt Database=False;"
				L"Jet OLEDB:Don't Copy Locale on Compact=False;"
				L"Jet OLEDB:Compact Without Replica Repair=False;"
				L"Jet OLEDB:SFP=False"
				, lpszPathFileName, lpszUserName, lpszPassword);

			hr = Open(LPCWSTR(strConnection));

			if (FAILED(hr))
			{
#ifdef _DEBUG
				ATL::AtlTraceErrorRecords(hr);
#endif
			}
		}
		else
			hr = HRESULT_FROM_WIN32(::GetLastError());
	}
	else
		hr = E_POINTER;


	return hr;
}
コード例 #3
0
ファイル: DBHistory.cpp プロジェクト: Hpark11/FIES
HRESULT CDBHistory::QueryHistory(HDBCONNECTION hDBConnection, 
						LPCWSTR lpszSerialNum,
						LPDB_HISTORY_COMMON pRecord,
						BSTR* pbstrResult)

{
	HRESULT hr = E_FAIL;

	IMT::CDBConnection* pDBConnection = reinterpret_cast<IMT::CDBConnection*>(hDBConnection);
	if (pDBConnection != NULL)
	{
		ATL::CCommand<ATL::CAccessor<IMT::CDBHistory>> Command;

		ATL::CDBPropSet _DBPropSet(DBPROPSET_ROWSET);
		pDBConnection->GetRowsetProperties(&_DBPropSet);

		CAtlStringW strCommand;
		CAtlStringW strTemp;
		strCommand.Format(QUERY_HISTORY_SELECT L" WHERE ");

		BOOL isExist = FALSE;

		strTemp.Format(L"SerialNum = '%s'", lpszSerialNum);//L"SerialNum = '%s'", lpszSerial);//
		strCommand += strTemp;

		hr = Command.Open(ATL::CSession(*pDBConnection), strCommand, &_DBPropSet);
		if (hr != S_OK)
		{
			if (pbstrResult != NULL)
				IMT::GetDBErrorString(hr, pbstrResult);
		}
		else
		{
			TRACE(_T(":::[CDBUser]-[QUERY] SUCCEEDED :::\n"));

			hr = Command.MoveNext();
			if (hr == S_OK)
				::CopyMemory(pRecord, LPDB_HISTORY_COMMON(Command), sizeof(DB_HISTORY_COMMON));
		}
	}

	return hr;
}
コード例 #4
0
ファイル: DBHistory.cpp プロジェクト: Hpark11/FIES
HRESULT CDBHistory::AddHistory(HDBCONNECTION hDBConnection, 
								DB_HISTORY_COMMON dbHistory,
								BSTR* pbstrResult)
{
	HRESULT hr = E_FAIL;

	IMT::CDBConnection* pDBConnection = reinterpret_cast<IMT::CDBConnection*>(hDBConnection);
	if (pDBConnection != NULL)
	{
		ATL::CCommand<ATL::CDynamicAccessor> Command;

		ATL::CDBPropSet _DBPropSet(DBPROPSET_ROWSET);
		pDBConnection->GetRowsetProperties(&_DBPropSet);

		CAtlStringW strCommand;

		strCommand.Format(QUERY_HISTORY_INSERT,
							dbHistory.dateTime.year,
							dbHistory.dateTime.month,
							dbHistory.dateTime.day,
							dbHistory.dateTime.hour,
							dbHistory.dateTime.minute,
							dbHistory.dateTime.second,
							dbHistory.nLRUIdx,
							dbHistory.wszSerialNum,
							dbHistory.wszSRUName,
							dbHistory.nInspectType,
							dbHistory.wszItem,
							dbHistory.nBIT,
							dbHistory.lPresentedResult,
							dbHistory.wszID,
							dbHistory.wszComment,
							dbHistory.l_Index);

		hr = Command.Open(ATL::CSession(*pDBConnection), strCommand, &_DBPropSet);
		if (hr != S_OK)
		{
			if (pbstrResult != NULL)
				IMT::GetDBErrorString(hr, pbstrResult);
		}
		else
		{
			TRACE(_T(":::[CDBHistory]-[INSERT] SUCCEEDED :::\n"));
		}
	}

	return hr;
}
コード例 #5
0
ファイル: DBHistory_External.cpp プロジェクト: Hpark11/FIES
HRESULT CDBHistroy_External::AddHistoryExternal(HDBCONNECTION hDBConnection, 
									DB_EXTERNAL dbExternal,
									BSTR* pbstrResult)
{
	HRESULT hr = E_FAIL;

	IMT::CDBConnection* pDBConnection = reinterpret_cast<IMT::CDBConnection*>(hDBConnection);
	if (pDBConnection != NULL)
	{
		ATL::CCommand<ATL::CDynamicAccessor> Command;

		ATL::CDBPropSet _DBPropSet(DBPROPSET_ROWSET);
		pDBConnection->GetRowsetProperties(&_DBPropSet);

		CAtlStringW strCommand;

		strCommand.Format(QUERY_H_EXTERNAL_INSERT,
						dbExternal.dbHistory.dateTime.year,
						dbExternal.dbHistory.dateTime.month,
						dbExternal.dbHistory.dateTime.day,
						dbExternal.dbHistory.dateTime.hour,
						dbExternal.dbHistory.dateTime.minute,
						dbExternal.dbHistory.dateTime.second,
						dbExternal.wszInspectionItem,
						dbExternal.wszLRUPort,
						dbExternal.wszCable,
						dbExternal.wszInspectionSignal,
						dbExternal.wszInterlockPort,
						dbExternal.dbHistory.bResult,
						dbExternal.dbHistory.wszID,
						dbExternal.dbHistory.wszComment);

		hr = Command.Open(ATL::CSession(*pDBConnection), strCommand, &_DBPropSet);
		if (hr != S_OK)
		{
			if (pbstrResult != NULL)
				IMT::GetDBErrorString(hr, pbstrResult);
		}
		else
		{
			TRACE(_T(":::[CDBHistroy_External]-[INSERT] SUCCEEDED :::\n"));
		}
	}

	return hr;
}
コード例 #6
0
ファイル: DBHistory_BIT.cpp プロジェクト: Hpark11/FIES
HRESULT CDBHistroy_BIT::AddHistoryBIT(HDBCONNECTION hDBConnection, 
									DB_BIT dbBIT,
									BSTR* pbstrResult)
{
	HRESULT hr = E_FAIL;

	IMT::CDBConnection* pDBConnection = reinterpret_cast<IMT::CDBConnection*>(hDBConnection);
	if (pDBConnection != NULL)
	{
		ATL::CCommand<ATL::CDynamicAccessor> Command;

		ATL::CDBPropSet _DBPropSet(DBPROPSET_ROWSET);
		pDBConnection->GetRowsetProperties(&_DBPropSet);

		CAtlStringW strCommand;

		strCommand.Format(QUERY_H_BIT_INSERT,
							dbBIT.dbHistory.dateTime.year,
							dbBIT.dbHistory.dateTime.month,
							dbBIT.dbHistory.dateTime.day,
							dbBIT.dbHistory.dateTime.hour,
							dbBIT.dbHistory.dateTime.minute,
							dbBIT.dbHistory.dateTime.second,
							dbBIT.wszInstrumentName,
							dbBIT.dbHistory.nBIT,
							dbBIT.wszInspectionItem,
							dbBIT.dbHistory.lPresentedResult,
							dbBIT.dbHistory.wszComment,
							dbBIT.bMainSection);

		hr = Command.Open(ATL::CSession(*pDBConnection), strCommand, &_DBPropSet);
		if (hr != S_OK)
		{
			if (pbstrResult != NULL)
				IMT::GetDBErrorString(hr, pbstrResult);
		}
		else
		{
			TRACE(_T(":::[CDBHistroy_BIT]-[INSERT] SUCCEEDED :::\n"));
		}
	}

	/*SELECT MAX(rowId) FROM property */

	return hr;
}
コード例 #7
0
HRESULT CIIS7XMLConfigHelper::RemoveModuleNodes(IXMLDOMDocument* pDoc, LPCSTR pszModuleName)
{
	if (pDoc == NULL || pszModuleName == NULL)
		return E_POINTER;

	CAtlStringW sQuery;
	sQuery.Format(L"//add[@name='%hs']", pszModuleName);	

	CComBSTR bsQuery(sQuery);

	CComPtr<IXMLDOMNodeList> pModuleNodes;
	HRESULT hr = pDoc->selectNodes(bsQuery, &pModuleNodes);

	if (hr == S_OK)
	{
		LONG nModules = 0;
		hr = pModuleNodes->get_length(&nModules);

		for (LONG i = 0; i < nModules; i++)
		{
			CComPtr<IXMLDOMNode> pModuleNode;
			hr = pModuleNodes->get_item(i, &pModuleNode);
			if (hr != S_OK || pModuleNode == NULL)
				continue;

			CComPtr<IXMLDOMNode> pParentNode;
			hr = pModuleNode->get_parentNode(&pParentNode);
			if (hr != S_OK || pParentNode == NULL)
				continue;

			CComPtr<IXMLDOMNode> pTemp;
			hr = pParentNode->removeChild(pModuleNode, &pTemp);
			if (hr != S_OK)
				break;
		}
	}

	return hr;
}
コード例 #8
0
ファイル: DBHistory_BIT.cpp プロジェクト: Hpark11/FIES
HRESULT CDBHistroy_BIT::QueryHistoryBIT_InspRecord(HDBCONNECTION hDBConnection,
													long l_Index,
													LPDB_BIT pRecord,
													BSTR* pbstrResult)
{
	HRESULT hr = E_FAIL;

	IMT::CDBConnection* pDBConnection = reinterpret_cast<IMT::CDBConnection*>(hDBConnection);
	if (pDBConnection != NULL)
	{
		ATL::CCommand<ATL::CAccessor<IMT::CDBHistroy_BIT>> Command;

		ATL::CDBPropSet _DBPropSet(DBPROPSET_ROWSET);
		pDBConnection->GetRowsetProperties(&_DBPropSet);

		CAtlStringW strCommand;
		CAtlStringW strTemp;

		strCommand.Format(QUERY_H_BIT_SELECT L" WHERE Index = %d", l_Index);
		
		hr = Command.Open(ATL::CSession(*pDBConnection), strCommand, &_DBPropSet);
		if (hr != S_OK)
		{
			if (pbstrResult != NULL)
				IMT::GetDBErrorString(hr, pbstrResult);
		}
		else
		{
			TRACE(_T(":::[CDBHistroy_BIT]-[QUERY] SUCCEEDED :::\n"));
			hr = Command.MoveNext();
			if (hr == S_OK)
				::CopyMemory(pRecord, LPDB_BIT(Command), sizeof(DB_BIT));
		}
	}

	return hr;
}
コード例 #9
0
ファイル: DBHistory.cpp プロジェクト: Hpark11/FIES
HRESULT CDBHistory::QueryHistory_InspectionRecord(HDBCONNECTION hDBConnection, 
													SYSTEMTIME sysTimeFrom,
													SYSTEMTIME sysTimeTo,
													long l_LRUIndex,
													LPCWSTR lpszSerial,
													long	lResult,
													LPCWSTR lpszUserID,
													long	l_Index,
													LPDB_HISTORY_COMMON pRecord,
													BSTR* pbstrResult)
{
	HRESULT hr = E_FAIL;

	IMT::CDBConnection* pDBConnection = reinterpret_cast<IMT::CDBConnection*>(hDBConnection);
	if (pDBConnection != NULL)
	{
		ATL::CCommand<ATL::CAccessor<IMT::CDBHistory>> Command;

		ATL::CDBPropSet _DBPropSet(DBPROPSET_ROWSET);
		pDBConnection->GetRowsetProperties(&_DBPropSet);

		CAtlStringW strCommand;
		CAtlStringW strTemp;
		strCommand.Format(QUERY_USER_BY_VALID_CONDITIONS, sysTimeFrom.wYear,
														  sysTimeFrom.wMonth,
														  sysTimeFrom.wDay,
														  sysTimeTo.wYear,
														  sysTimeTo.wMonth,
														  sysTimeTo.wDay);

		BOOL isExist = FALSE;

		strTemp = strCommand;
		strCommand += L"AND ";

		if(l_LRUIndex != 0)
		{
			strTemp.Format(L"(LRU_Index = %d) ", l_LRUIndex);
			strCommand += strTemp;
			strTemp = strCommand;
			strCommand += L"AND ";
		}
		else
			TRACE(L"");

		if(::lstrcmpi(lpszSerial, L"Àüü") != 0)
		{
			strTemp.Format(L"(SerialNum = '%s') ", lpszSerial);
			strCommand += strTemp;
			strTemp = strCommand;
			strCommand += L"AND ";
		}
		else
			TRACE(L"");

		if(lResult != dfRESULT_ALL)
		{
			strTemp.Format(L"(State = %d) ", lResult);
			strCommand += strTemp;
			strTemp = strCommand;
			strCommand += L"AND ";
		}
		else
			TRACE(L"");

		if(::lstrcmpi(lpszUserID, L"Àüü") != 0)
		{
			strTemp.Format(L"(User = '******') ", lpszUserID);
			strCommand += strTemp;
			strTemp = strCommand;
			strCommand += L"AND ";
		}
		else
			TRACE(L"");

		if(::lstrcmpi(strCommand.Right(4), L"AND ") == 0)
		{
			strCommand = strTemp;
		}
		else
			TRACE(L"");


		hr = Command.Open(ATL::CSession(*pDBConnection), strCommand, &_DBPropSet);
		if (hr != S_OK)
		{
			if (pbstrResult != NULL)
				IMT::GetDBErrorString(hr, pbstrResult);
		}
		else
		{
			TRACE(_T(":::[CDBHistory]-[QUERY] SUCCEEDED :::\n"));
			for(long i = 0; i < l_Index; i++)
			{
				hr = Command.MoveNext();
			}
			if (hr == S_OK)
				::CopyMemory(pRecord, LPDB_HISTORY_COMMON(Command), sizeof(DB_HISTORY_COMMON));
		}
	}

	return hr;
}
コード例 #10
0
CAtlStringW ToString(int n)
{
    CAtlStringW result;
    result.Format(L"%i", n);
    return result;
}
コード例 #11
0
// Writes a set of properties for all objects.
void WriteContentPropertiesBulk(
    IPortableDevice*    pDevice)
{
    if (pDevice == NULL)
    {
        printf("! A NULL IPortableDevice interface pointer was received\n");
        return;
    }

    HRESULT                                       hr                = S_OK;
    GUID                                          guidContext       = GUID_NULL;
    CSetBulkValuesCallback*                       pCallback         = NULL;
    CComPtr<IPortableDeviceProperties>            pProperties;
    CComPtr<IPortableDevicePropertiesBulk>        pPropertiesBulk;
    CComPtr<IPortableDeviceValues>                pObjectProperties;
    CComPtr<IPortableDeviceContent>               pContent;
    CComPtr<IPortableDeviceValuesCollection>      pPropertiesToWrite;
    CComPtr<IPortableDevicePropVariantCollection> pObjectIDs;
    DWORD                                         cObjectIDs        = 0;


    // 1) Get an IPortableDeviceContent interface from the IPortableDevice interface to
    // access the content-specific methods.
    hr = pDevice->Content(&pContent);
    if (FAILED(hr))
    {
        printf("! Failed to get IPortableDeviceContent from IPortableDevice, hr = 0x%lx\n",hr);
    }

    // 2) Get an IPortableDeviceProperties interface from the IPortableDeviceContent interface
    // to access the property-specific methods.
    if (SUCCEEDED(hr))
    {
        hr = pContent->Properties(&pProperties);
        if (FAILED(hr))
        {
            printf("! Failed to get IPortableDeviceProperties from IPortableDevice, hr = 0x%lx\n",hr);
        }
    }

    // 3) Check to see if the driver supports BULK property operations by call QueryInterface
    // on the IPortableDeviceProperties interface for IPortableDevicePropertiesBulk
    if (SUCCEEDED(hr))
    {
        hr = pProperties->QueryInterface(IID_PPV_ARGS(&pPropertiesBulk));
        if (FAILED(hr))
        {
            printf("This driver does not support BULK property operations.\n");
        }
    }

    // 4) CoCreate an IPortableDeviceValuesCollection interface to hold the the properties
    // we wish to write.
    if (SUCCEEDED(hr))
    {
        hr = CoCreateInstance(CLSID_PortableDeviceValuesCollection,
                              NULL,
                              CLSCTX_INPROC_SERVER,
                              IID_PPV_ARGS(&pPropertiesToWrite));
        if (FAILED(hr))
        {
            printf("! Failed to CoCreate IPortableDeviceValuesCollection for bulk property values, hr = 0x%lx\n", hr);
        }
    }

    // 6) Create an instance of the IPortableDevicePropertiesBulkCallback object.
    if (SUCCEEDED(hr))
    {
        pCallback = new (std::nothrow) CSetBulkValuesCallback();
        if (pCallback == NULL)
        {
            hr = E_OUTOFMEMORY;
            printf("! Failed to allocate CSetBulkValuesCallback, hr = 0x%lx\n", hr);
        }
    }

    // 7) Call our helper function CreateIPortableDevicePropVariantCollectionWithAllObjectIDs
    // to enumerate and create an IPortableDevicePropVariantCollection with the object
    // identifiers needed to perform the bulk operation on.
    if (SUCCEEDED(hr))
    {
        hr = CreateIPortableDevicePropVariantCollectionWithAllObjectIDs(pContent,
                                                                        &pObjectIDs);
    }

    if (SUCCEEDED(hr))
    {
        hr = pObjectIDs->GetCount(&cObjectIDs);
        if (FAILED(hr))
        {
            printf("! Failed to get number of objectIDs from IPortableDevicePropVariantCollection, hr = 0x%lx\n", hr);
        }
    }

    // 8) Iterate through object list and add appropriate IPortableDeviceValues to collection
    if (SUCCEEDED(hr))
    {
        for(DWORD dwIndex = 0; (dwIndex < cObjectIDs) && (hr == S_OK); dwIndex++)
        {
            CComPtr<IPortableDeviceValues>  pValues;
            PROPVARIANT                     pv = {0};

            PropVariantInit(&pv);
            hr = CoCreateInstance(CLSID_PortableDeviceValues,
                                  NULL,
                                  CLSCTX_INPROC_SERVER,
                                  IID_PPV_ARGS(&pValues));
            if (FAILED(hr))
            {
                printf("! Failed to CoCreate CLSID_PortableDeviceValues, hr = 0x%lx\n", hr);
            }

            // Get the Object ID whose properties we will set
            if (hr == S_OK)
            {
                hr = pObjectIDs->GetAt(dwIndex, &pv);
                if (FAILED(hr))
                {
                    printf("! Failed to get next Object ID from list, hr = 0x%lx\n", hr);
                }
            }

            // Save them into the IPortableDeviceValues so the driver knows which object this proeprty set belongs to
            if (hr == S_OK)
            {
                hr = pValues->SetStringValue(WPD_OBJECT_ID, pv.pwszVal);
                if (FAILED(hr))
                {
                    printf("! Failed to set WPD_OBJECT_ID, hr = 0x%lx\n", hr);
                }
            }

            // Set the new values.  In this sample, we attempt to set the name property.
            if (hr == S_OK)
            {
                CAtlStringW strValue;
                strValue.Format(L"NewName%d", dwIndex);

                hr = pValues->SetStringValue(WPD_OBJECT_NAME, strValue.GetString());
                if (FAILED(hr))
                {
                    printf("! Failed to set WPD_OBJECT_NAME, hr = 0x%lx\n", hr);
                }
            }

            // Add this property set to the collection
            if (hr == S_OK)
            {
                hr = pPropertiesToWrite->Add(pValues);
                if (FAILED(hr))
                {
                    printf("! Failed to add values to collection, hr = 0x%lx\n", hr);
                }
            }
            PropVariantClear(&pv);
        }
    }

    // 9) Call QueueSetValuesByObjectList to initialize the Asynchronous
    // property operation.
    if (SUCCEEDED(hr))
    {
        hr = pPropertiesBulk->QueueSetValuesByObjectList(pPropertiesToWrite,
                                                         pCallback,
                                                         &guidContext);
        // 10) Call Start() to actually being the property operation
        if(SUCCEEDED(hr))
        {
            // Cleanup any previously created global event handles.
            if (g_hBulkPropertyOperationEvent != NULL)
            {
                CloseHandle(g_hBulkPropertyOperationEvent);
                g_hBulkPropertyOperationEvent = NULL;
            }

            // In order to create a simpler to follow example we create and wait infinitly
            // for the bulk property operation to complete and ignore any errors.
            // Production code should be written in a more robust manner.
            // Create the global event handle to wait on for the bulk operation
            // to complete.
            g_hBulkPropertyOperationEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
            if (g_hBulkPropertyOperationEvent != NULL)
            {
                // Call Start() to actually being the Asynchronous bulk operation.
                hr = pPropertiesBulk->Start(guidContext);
                if(FAILED(hr))
                {
                    printf("! Failed to start property operation, hr = 0x%lx\n", hr);
                }
            }
            else
            {
                printf("! Failed to create the global event handle to wait on for the bulk operation. Aborting operation.\n");
            }
        }
        else
        {
            printf("! QueueSetValuesByObjectList Failed, hr = 0x%lx\n", hr);
        }
    }

    // In order to create a simpler to follow example we will wait infinitly for the operation
    // to complete and ignore any errors.  Production code should be written in a more
    // robust manner.
    if (SUCCEEDED(hr))
    {
        if (g_hBulkPropertyOperationEvent != NULL)
        {
            WaitForSingleObject(g_hBulkPropertyOperationEvent, INFINITE);
        }
    }

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

    // Cleanup any created global event handles before exiting..
    if (g_hBulkPropertyOperationEvent != NULL)
    {
        CloseHandle(g_hBulkPropertyOperationEvent);
        g_hBulkPropertyOperationEvent = NULL;
    }
}
コード例 #12
0
HRESULT CIIS7XMLConfigHelper::AddNativeModuleNode(IXMLDOMDocument* pDoc, 
												  IXMLDOMNode* pModulesNode, 
												  LPCSTR pszModuleName,
												  LPCSTR pszModulePath,
												  int bitness)
{
	if (pDoc == NULL || pModulesNode == NULL || pszModuleName == NULL)
		return E_POINTER;

	CAtlStringW sQuery;
	sQuery.Format(L"add[@name='%hs']", pszModuleName);	

	CComBSTR bsQuery(sQuery);

	// find the module node, if it doesn't exist then add it
	CComPtr<IXMLDOMNode> pModuleNode;
	HRESULT hr = pModulesNode->selectSingleNode(bsQuery, &pModuleNode);
	if (hr != S_OK || pModuleNode == NULL)
	{		
		hr = pDoc->createNode(CComVariant(NODE_ELEMENT), L"add", L"", &pModuleNode);
		if (hr != S_OK || pModuleNode == NULL)
			return hr;

		CComPtr<IXMLDOMNamedNodeMap> pAttrs;
		hr = pModuleNode->get_attributes(&pAttrs);
		if (hr != S_OK || pAttrs == NULL)
			return hr;

		CComPtr<IXMLDOMAttribute> pNameAttr;
		hr = pDoc->createAttribute(L"name", &pNameAttr);
		if (hr != S_OK || pNameAttr == NULL)
			return hr;

		hr = pNameAttr->put_text(CComBSTR(pszModuleName));
		hr = pAttrs->setNamedItem(pNameAttr, NULL);

		if (pszModulePath != NULL)
		{
			CComPtr<IXMLDOMAttribute> pImageAttr;
			hr = pDoc->createAttribute(L"image", &pImageAttr);
			if (hr != S_OK || pNameAttr == NULL)
				return hr;

			hr = pImageAttr->put_text(CComBSTR(pszModulePath));
			hr = pAttrs->setNamedItem(pImageAttr, NULL);
		}

		// set the bitness precondition
		if (bitness > 0)
		{
			CComPtr<IXMLDOMAttribute> pPreconditionAttr;
			hr = pDoc->createAttribute(L"preCondition", &pPreconditionAttr);
			if (hr != S_OK || pPreconditionAttr == NULL)
				return hr;
			
			CAtlString sBitness;
			sBitness.Format(_T("bitness%d"), bitness);

			hr = pPreconditionAttr->put_text(CComBSTR(sBitness));
			hr = pAttrs->setNamedItem(pPreconditionAttr, NULL);
		}

		hr = pModulesNode->appendChild(pModuleNode, NULL);
	}

	return hr;
}