/****************************************************************************** Copyright (c) 1999 Microsoft Corporation Module Name: Configuration.cpp Abstract: This file contains the implementation of the ... Revision History: Davide Massarenti (Dmassare) 01/09/2000 created ******************************************************************************/ #include "stdafx.h" //////////////////////////////////////////////////////////////////////////////// const MPC::Config::DefinitionOfTag* MPC::Config::DefinitionOfTag::FindSubTag( /*[in]*/ LPCWSTR szTag ) const { const DefinitionOfTag** ptr = m_tblSubTags; if(ptr) { while(*ptr) { if(!MPC::StrICmp( (*ptr)->m_szTag, szTag )) { return (*ptr); } ptr++; } } return NULL; } const MPC::Config::DefinitionOfAttribute* MPC::Config::DefinitionOfTag::FindAttribute( /*[in]*/ XMLTypes xt, /*[in]*/ LPCWSTR szName ) const { const DefinitionOfAttribute* ptr = m_tblAttributes; if(ptr) { while(ptr->m_xt != XT_invalid) { if(ptr->m_xt == xt) { if(ptr->m_xt == XT_value || !MPC::StrICmp( ptr->m_szName, szName )) return ptr; } ptr++; } } return NULL; } //////////////////////////////////////////////////////////////////////////////// void MPC::Config::ClearValue( /*[in]*/ TypeConstructor* defType , /*[in]*/ const DefinitionOfAttribute* defAttrib ) { { void* data = defType->GetOffset( defAttrib->m_offset ); VARTYPE dest; switch(defAttrib->m_mtType) { case MT_bool : *(bool *)data = false ; break; case MT_BOOL : *(BOOL *)data = FALSE ; break; case MT_VARIANT_BOOL: *(VARIANT_BOOL*)data = VARIANT_FALSE; break; case MT_int : *(int *)data = 0 ; break; case MT_long : *(long *)data = 0 ; break; case MT_DWORD : *(DWORD *)data = 0 ; break; case MT_float : *(float *)data = 0 ; break; case MT_double : *(double *)data = 0 ; break; case MT_DATE : *(DATE *)data = 0 ; break; case MT_DATE_US : *(DATE *)data = 0 ; break; case MT_DATE_CIM : *(DATE *)data = 0 ; break; case MT_CHAR : *(CHAR *)data = 0 ; break; case MT_WCHAR : *(WCHAR *)data = 0 ; break; case MT_BSTR : *(CComBSTR *)data = (LPCWSTR)NULL; break; case MT_string : *(MPC::string *)data = "" ; break; case MT_wstring : *(MPC::wstring*)data = L"" ; break; case MT_bitfield : *(DWORD *)data = 0 ; break; } } if(defAttrib->m_fPresenceFlag) { bool* data = (bool*)defType->GetOffset( defAttrib->m_offsetPresence ); *data = false; } } HRESULT MPC::Config::LoadValue( /*[in]*/ TypeConstructor* defType , /*[in]*/ const DefinitionOfAttribute* defAttrib , /*[in/out]*/ CComVariant& value , /*[in]*/ bool fFound ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::LoadValue" ); USES_CONVERSION; HRESULT hr; if(fFound) { void* data = defType->GetOffset( defAttrib->m_offset ); VARTYPE dest; switch(defAttrib->m_mtType) { case MT_bool : dest = VT_BOOL ; break; case MT_BOOL : dest = VT_BOOL ; break; case MT_VARIANT_BOOL: dest = VT_BOOL ; break; case MT_int : dest = VT_I4 ; break; case MT_long : dest = VT_I4 ; break; case MT_DWORD : dest = VT_I4 ; break; case MT_float : dest = VT_R4 ; break; case MT_double : dest = VT_R8 ; break; case MT_DATE : dest = VT_ILLEGAL; break; case MT_DATE_US : dest = VT_ILLEGAL; break; case MT_DATE_CIM : dest = VT_ILLEGAL; break; case MT_CHAR : dest = VT_BSTR ; break; case MT_WCHAR : dest = VT_BSTR ; break; case MT_BSTR : dest = VT_BSTR ; break; case MT_string : dest = VT_BSTR ; break; case MT_wstring : dest = VT_BSTR ; break; case MT_bitfield : dest = VT_BSTR ; break; default : __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG); } if(dest == VT_ILLEGAL) { LPCWSTR szDate; bool fCIM = false; LCID lcid = 0; __MPC_EXIT_IF_METHOD_FAILS(hr, value.ChangeType( VT_BSTR )); szDate = value.bstrVal; SANITIZEWSTR(szDate); switch(defAttrib->m_mtType) { case MT_DATE : fCIM = false; lcid = 0; break; case MT_DATE_US : fCIM = false; lcid = -1; break; case MT_DATE_CIM: fCIM = true ; lcid = 0; break; } // // We try as much as we can to parse the date. First the expected format, then the US one, finally the user default. // if(FAILED(MPC::ConvertStringToDate( szDate, *(DATE*)data, /*fGMT*/false, fCIM, lcid ))) { if(FAILED(MPC::ConvertStringToDate( szDate, *(DATE*)data, /*fGMT*/false, /*fCIM*/false, -1 ))) { __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertStringToDate( szDate, *(DATE*)data, /*fGMT*/false, /*fCIM*/false, 0 )); } } } else { __MPC_EXIT_IF_METHOD_FAILS(hr, value.ChangeType( dest )); switch(defAttrib->m_mtType) { case MT_bool : *(bool *)data = (value.boolVal == VARIANT_TRUE) ? true : false; break; case MT_BOOL : *(BOOL *)data = (value.boolVal == VARIANT_TRUE) ? TRUE : FALSE; break; case MT_VARIANT_BOOL: *(VARIANT_BOOL*)data = value.boolVal ; break; case MT_int : *(int *)data = value.lVal ; break; case MT_long : *(long *)data = value.lVal ; break; case MT_DWORD : *(DWORD *)data = value.lVal ; break; case MT_float : *(float *)data = value.fltVal ; break; case MT_double : *(double *)data = value.dblVal ; break; case MT_CHAR : *(CHAR *)data = value.bstrVal ? ( CHAR)value.bstrVal[0] : 0 ; break; case MT_WCHAR : *(WCHAR *)data = value.bstrVal ? (WCHAR)value.bstrVal[0] : 0 ; break; case MT_BSTR : *(CComBSTR *)data = value.bstrVal ; break; case MT_string : *(MPC::string *)data = OLE2A(SAFEBSTR(value.bstrVal)) ; break; case MT_wstring : *(MPC::wstring*)data = SAFEBSTR(value.bstrVal) ; break; case MT_bitfield: __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertStringToBitField( value.bstrVal, *(DWORD*)data, defAttrib->m_Lookup, /*fUseTilde*/false )); break; } } } if(defAttrib->m_fPresenceFlag) { bool* data = (bool*)defType->GetOffset( defAttrib->m_offsetPresence ); *data = fFound; } hr = S_OK; __MPC_FUNC_CLEANUP; __MPC_FUNC_EXIT(hr); } HRESULT MPC::Config::SaveValue( /*[in]*/ const TypeConstructor* defType , /*[in]*/ const DefinitionOfAttribute* defAttrib , /*[out]*/ CComVariant& value , /*[out]*/ bool& fFound ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::SaveValue" ); HRESULT hr; if(defAttrib->m_fPresenceFlag) { bool* data = (bool*)defType->GetOffset( defAttrib->m_offsetPresence ); fFound = *data; } else { fFound = true; } value.Clear(); if(fFound) { const void* data = defType->GetOffset( defAttrib->m_offset ); VARTYPE src; WCHAR rgBuf[2]; switch(defAttrib->m_mtType) { case MT_bool : value.boolVal = *(bool *)data ? VARIANT_TRUE : VARIANT_FALSE; src = VT_BOOL ; break; case MT_BOOL : value.boolVal = *(BOOL *)data ? VARIANT_TRUE : VARIANT_FALSE; src = VT_BOOL ; break; case MT_VARIANT_BOOL: value.boolVal = *(VARIANT_BOOL*)data ; src = VT_BOOL ; break; case MT_int : value.lVal = *(int *)data ; src = VT_I4 ; break; case MT_long : value.lVal = *(long *)data ; src = VT_I4 ; break; case MT_DWORD : value.lVal = *(DWORD *)data ; src = VT_I4 ; break; case MT_float : value.fltVal = *(float *)data ; src = VT_R4 ; break; case MT_double : value.dblVal = *(double *)data ; src = VT_R8 ; break; case MT_DATE : ; src = VT_ILLEGAL; break; case MT_DATE_US : ; src = VT_ILLEGAL; break; case MT_DATE_CIM : ; src = VT_ILLEGAL; break; case MT_CHAR : rgBuf[0] = *(CHAR *)data; rgBuf[1] = 0; value = rgBuf ; src = VT_BSTR ; break; case MT_WCHAR : rgBuf[0] = *(WCHAR *)data; rgBuf[1] = 0; value = rgBuf ; src = VT_BSTR ; break; case MT_BSTR : value = *(CComBSTR *)data ; src = VT_BSTR ; break; case MT_string : value = ((MPC::string *)data)->c_str() ; src = VT_BSTR ; break; case MT_wstring : value = ((MPC::wstring*)data)->c_str() ; src = VT_BSTR ; break; case MT_bitfield: { MPC::wstring strText; __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertBitFieldToString( *(DWORD*)data, strText, defAttrib->m_Lookup )); value = strText.c_str(); src = VT_BSTR; } break; default: __MPC_SET_ERROR_AND_EXIT(hr, E_INVALIDARG); } if(src == VT_ILLEGAL) { MPC::wstring strDate; bool fCIM = false; LCID lcid = 0; switch(defAttrib->m_mtType) { case MT_DATE : fCIM = false; lcid = 0; break; case MT_DATE_US : fCIM = false; lcid = -1; break; case MT_DATE_CIM: fCIM = true ; lcid = 0; break; } __MPC_EXIT_IF_METHOD_FAILS(hr, MPC::ConvertDateToString( *(DATE*)data, strDate, /*fGMT*/false, fCIM, lcid )); value = strDate.c_str(); } else if(src != VT_BSTR) { value.vt = src; __MPC_EXIT_IF_METHOD_FAILS(hr, value.ChangeType( VT_BSTR )); } } hr = S_OK; __MPC_FUNC_CLEANUP; __MPC_FUNC_EXIT(hr); } //////////////////////////////////////////////////////////////////////////////// HRESULT MPC::Config::LoadNode( /*[in]*/ TypeConstructor* defType , /*[in]*/ const DefinitionOfTag* defTag , /*[in]*/ IXMLDOMNode* xdn ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::LoadNode" ); HRESULT hr; const DefinitionOfTag* defSubTag; const DefinitionOfAttribute* defAttrib; // // First of all, clean all the variables. // defAttrib = defTag->m_tblAttributes; if(defAttrib) { while(defAttrib->m_xt != XT_invalid) { ClearValue( defType, defAttrib ); defAttrib++; } } // // Load all the attributes. // { CComPtr xdnnmAttribs; __MPC_EXIT_IF_METHOD_FAILS(hr, xdn->get_attributes( &xdnnmAttribs )); if(xdnnmAttribs) { while(1) { CComPtr xdnNode; CComQIPtr xdaAttrib; __MPC_EXIT_IF_METHOD_FAILS(hr, xdnnmAttribs->nextNode( &xdnNode )); if(xdnNode == NULL) break; if((xdaAttrib = xdnNode)) { CComBSTR bstrName; __MPC_EXIT_IF_METHOD_FAILS(hr, xdaAttrib->get_name( &bstrName )); defAttrib = defTag->FindAttribute( XT_attribute, SAFEBSTR( bstrName ) ); if(defAttrib) { CComVariant value; __MPC_EXIT_IF_METHOD_FAILS(hr, xdaAttrib->get_value( &value )); __MPC_EXIT_IF_METHOD_FAILS(hr, LoadValue( defType, defAttrib, value, true )); } } } } } // // Load the node as value. // defAttrib = defTag->FindAttribute( XT_value, NULL ); if(defAttrib) { MPC::XmlUtil xml( xdn ); CComVariant value; bool fFound; __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetValue( NULL, value, fFound )); __MPC_EXIT_IF_METHOD_FAILS(hr, LoadValue( defType, defAttrib, value, fFound )); } // // Load all subnodes. // if(defTag->m_tblSubTags) { CComPtr xdnChild; __MPC_EXIT_IF_METHOD_FAILS(hr, xdn->get_firstChild( &xdnChild )); while(xdnChild) { CComPtr xdnSibling; CComBSTR bstrName; __MPC_EXIT_IF_METHOD_FAILS(hr, xdnChild->get_nodeName( &bstrName )); defAttrib = defTag->FindAttribute( XT_element, SAFEBSTR( bstrName ) ); if(defAttrib) { MPC::XmlUtil xml( xdnChild ); CComVariant value; bool fFound; __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetValue( NULL, value, fFound )); __MPC_EXIT_IF_METHOD_FAILS(hr, LoadValue( defType, defAttrib, value, fFound )); } defSubTag = defTag->FindSubTag( SAFEBSTR( bstrName ) ); if(defSubTag) { TypeConstructor* defSubType; __MPC_EXIT_IF_METHOD_FAILS(hr, defType->CreateInstance( defSubTag, defSubType )); __MPC_EXIT_IF_METHOD_FAILS(hr, defSubType->LoadNode( xdnChild )); } __MPC_EXIT_IF_METHOD_FAILS(hr, xdnChild->get_nextSibling( &xdnSibling )); xdnChild = xdnSibling; } } hr = S_OK; __MPC_FUNC_CLEANUP; __MPC_FUNC_EXIT(hr); } HRESULT MPC::Config::LoadXmlUtil( /*[in]*/ TypeConstructor* defType , /*[in]*/ MPC::XmlUtil& xml ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::LoadXmlUtil" ); HRESULT hr; CComPtr xdnRoot; __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetRoot( &xdnRoot )); __MPC_EXIT_IF_METHOD_FAILS(hr, defType->LoadNode( xdnRoot )); hr = S_OK; __MPC_FUNC_CLEANUP; __MPC_FUNC_EXIT(hr); } HRESULT MPC::Config::LoadStream( /*[in]*/ TypeConstructor* defType , /*[in]*/ IStream* pStream ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::LoadStream" ); HRESULT hr; MPC::XmlUtil xml; bool fFound; bool fLoaded; __MPC_EXIT_IF_METHOD_FAILS(hr, xml.LoadAsStream( pStream, defType->GetTag(), fLoaded, &fFound )); if(fFound) { __MPC_EXIT_IF_METHOD_FAILS(hr, LoadXmlUtil( defType, xml )); } hr = S_OK; __MPC_FUNC_CLEANUP; __MPC_FUNC_EXIT(hr); } HRESULT MPC::Config::LoadFile( /*[in]*/ TypeConstructor* defType , /*[in]*/ LPCWSTR szFile ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::LoadFile" ); HRESULT hr; MPC::XmlUtil xml; MPC::wstring strFileOrig( szFile ); strFileOrig += L".orig"; bool fFound; bool fLoaded; __MPC_EXIT_IF_METHOD_FAILS(hr, xml.Load( szFile, defType->GetTag(), fLoaded, &fFound )); if(fFound == false) { // // If fails, try to load ".orig" // __MPC_EXIT_IF_METHOD_FAILS(hr, xml.Load( strFileOrig.c_str(), defType->GetTag(), fLoaded, &fFound )); } if(fFound && fLoaded) { __MPC_EXIT_IF_METHOD_FAILS(hr, LoadXmlUtil( defType, xml )); } hr = S_OK; __MPC_FUNC_CLEANUP; __MPC_FUNC_EXIT(hr); } //////////////////////////////////////////////////////////////////////////////// HRESULT MPC::Config::SaveNode( /*[in]*/ const TypeConstructor* defType , /*[in]*/ const DefinitionOfTag* defTag , /*[in]*/ IXMLDOMNode* xdn ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::SaveNode" ); HRESULT hr; const DefinitionOfAttribute* defAttrib; defAttrib = defTag->m_tblAttributes; if(defAttrib) { MPC::XmlUtil xml( xdn ); while(defAttrib->m_xt != XT_invalid) { CComVariant value; bool fFound; __MPC_EXIT_IF_METHOD_FAILS(hr, SaveValue( defType, defAttrib, value, fFound )); if(fFound) { if(defAttrib->m_xt == XT_attribute) { CComPtr xdaAttrib; __MPC_EXIT_IF_METHOD_FAILS(hr, xml.PutAttribute( NULL, defAttrib->m_szName, &xdaAttrib, fFound )); if(fFound) { __MPC_EXIT_IF_METHOD_FAILS(hr, xdaAttrib->put_value( value )); } } else if(defAttrib->m_xt == XT_value) { __MPC_EXIT_IF_METHOD_FAILS(hr, xml.PutValue( NULL, value, fFound )); } else if(defAttrib->m_xt == XT_element) { __MPC_EXIT_IF_METHOD_FAILS(hr, xml.PutValue( defAttrib->m_szName, value, fFound )); } } defAttrib++; } } hr = S_OK; __MPC_FUNC_CLEANUP; __MPC_FUNC_EXIT(hr); } HRESULT MPC::Config::SaveSubNode( /*[in]*/ const TypeConstructor* defType , /*[in]*/ IXMLDOMNode* xdn ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::SaveSubNode" ); HRESULT hr; CComPtr xdnChild; MPC::XmlUtil xml( xdn ); __MPC_EXIT_IF_METHOD_FAILS(hr, xml.CreateNode( defType->GetTag(), &xdnChild )); __MPC_EXIT_IF_METHOD_FAILS(hr, defType->SaveNode( xdnChild )); hr = S_OK; __MPC_FUNC_CLEANUP; __MPC_FUNC_EXIT(hr); } HRESULT MPC::Config::SaveXmlUtil( /*[in ]*/ const TypeConstructor* defType , /*[out]*/ MPC::XmlUtil& xml ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::SaveXmlUtil" ); HRESULT hr; CComPtr xdnRoot; __MPC_EXIT_IF_METHOD_FAILS(hr, xml.New( defType->GetTag() )); __MPC_EXIT_IF_METHOD_FAILS(hr, xml.GetRoot( &xdnRoot )); __MPC_EXIT_IF_METHOD_FAILS(hr, defType->SaveNode( xdnRoot )); hr = S_OK; __MPC_FUNC_CLEANUP; __MPC_FUNC_EXIT(hr); } HRESULT MPC::Config::SaveStream( /*[in]*/ const TypeConstructor* defType , /*[in]*/ IStream* *ppStream ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::SaveStream" ); HRESULT hr; MPC::XmlUtil xml; __MPC_EXIT_IF_METHOD_FAILS(hr, SaveXmlUtil( defType, xml )); __MPC_EXIT_IF_METHOD_FAILS(hr, xml.SaveAsStream( (IUnknown**)ppStream )); hr = S_OK; __MPC_FUNC_CLEANUP; __MPC_FUNC_EXIT(hr); } HRESULT MPC::Config::SaveFile( /*[in]*/ const TypeConstructor* defType , /*[in]*/ LPCWSTR szFile ) { __MPC_FUNC_ENTRY( COMMONID, "MPC::Config::SaveFile" ); HRESULT hr; MPC::XmlUtil xml; MPC::wstring strFileNew ( szFile ); strFileNew += L".new"; MPC::wstring strFileOrig( szFile ); strFileOrig += L".orig"; __MPC_EXIT_IF_METHOD_FAILS(hr, SaveXmlUtil( defType, xml )); // // First of all, delete ".new" and recreate it. // ::SetFileAttributesW( strFileNew.c_str(), FILE_ATTRIBUTE_NORMAL ); ::DeleteFileW ( strFileNew.c_str() ); __MPC_EXIT_IF_METHOD_FAILS(hr, xml.Save( strFileNew.c_str() )); // // Then move "" to ".orig" // ::SetFileAttributesW( szFile , FILE_ATTRIBUTE_NORMAL ); ::SetFileAttributesW( strFileOrig.c_str(), FILE_ATTRIBUTE_NORMAL ); ::DeleteFileW ( strFileOrig.c_str() ); if(::MoveFileW( szFile, strFileOrig.c_str() ) == FALSE) { DWORD dwRes = ::GetLastError(); if(dwRes != ERROR_FILE_NOT_FOUND) { __MPC_SET_WIN32_ERROR_AND_EXIT(hr, dwRes); } } // // Then rename ".new" to "" // __MPC_EXIT_IF_CALL_RETURNS_FALSE(hr, ::MoveFileW( strFileNew.c_str(), szFile )); // // Finally delete ".orig" // (void)::DeleteFileW( strFileOrig.c_str() ); hr = S_OK; __MPC_FUNC_CLEANUP; __MPC_FUNC_EXIT(hr); }