/*++ Copyright (C) 1997-2001 Microsoft Corporation Module Name: CBMOFOUT.CPP Abstract: Declares the CBMOFOut class. History: a-davj 06-April-97 Created. --*/ #include "precomp.h" #include "wstring.h" #include "mofout.h" #include "mofdata.h" #include "bmof.h" #include "cbmofout.h" #include "trace.h" #include "strings.h" #include //*************************************************************************** // // CBMOFOut::CBMOFOut // // DESCRIPTION: // // Constructor. Save the eventual destination name and writes the initial // structure out to the buffer. NOTE THAT TYPICALLY THE BMOFFileName will // be NULL and this object will not do anything. That deals with the 99% // of mofs that are not WMI! // // PARAMETERS: // // BMOFFileName Name of file to eventually write to. // //*************************************************************************** CBMOFOut::CBMOFOut( IN LPTSTR BMOFFileName, PDBG pDbg) : m_OutBuff(pDbg) { m_pDbg = pDbg; m_BinMof.dwSignature = BMOF_SIG; // spells BMOF m_BinMof.dwLength = sizeof(WBEM_Binary_MOF); // updated at end m_BinMof.dwVersion = 1; // 0x1 m_BinMof.dwEncoding = 1; // 0x1 = little endian, DWORD-aligned, no compression m_BinMof.dwNumberOfObjects = 0; // Total classes and instances in MOF if(BMOFFileName && lstrlen(BMOFFileName) > 0) { DWORD dwLen = lstrlen(BMOFFileName) + 1; m_pFile = new TCHAR[dwLen]; if(m_pFile) { StringCchCopyW(m_pFile, dwLen, BMOFFileName); m_OutBuff.AppendBytes((BYTE *)&m_BinMof, sizeof(WBEM_Binary_MOF)); } } else m_pFile = NULL; } //*************************************************************************** // // CBMOFOut::~CBMOFOut // // DESCRIPTION: // // Destructor. // //*************************************************************************** CBMOFOut::~CBMOFOut() { if(m_pFile) delete m_pFile; } //*************************************************************************** // // DWORD CBMOFOut::AddClass // // DESCRIPTION: // // Adds a class to the BMOF buffer. // // PARAMETERS: // // pObject pointer to class object. // bEmbedded TRUE if object is embedded. // // RETURN VALUE: // // Number of bytes written. // //*************************************************************************** DWORD CBMOFOut::AddClass( IN CMObject * pObject, IN BOOL bEmbedded) { DWORD dwStartingOffset = m_OutBuff.GetOffset(); CMoQualifierArray * pQualifierSet = NULL; if(!m_pFile) return 0; WBEM_Object wo; wo.dwLength = sizeof(WBEM_Object); // updated later wo.dwOffsetQualifierList = 0xffffffff; wo.dwOffsetPropertyList = 0xffffffff; wo.dwOffsetMethodList = 0xffffffff; wo.dwType = (pObject->IsInstance()) ? 1 : 0; // 0 = class, 1 = instance m_OutBuff.AppendBytes((BYTE *)&wo, sizeof(WBEM_Object)); DWORD dwStartInfoOffset = m_OutBuff.GetOffset(); // Write class qualifier pQualifierSet = pObject->GetQualifiers(); if(pQualifierSet) { wo.dwOffsetQualifierList = m_OutBuff.GetOffset() - dwStartInfoOffset; AddQualSet(pQualifierSet); } wo.dwOffsetPropertyList = m_OutBuff.GetOffset() - dwStartInfoOffset; AddPropSet(pObject); wo.dwOffsetMethodList = m_OutBuff.GetOffset() - dwStartInfoOffset; AddMethSet(pObject); wo.dwLength = m_OutBuff.GetOffset() - dwStartingOffset; m_OutBuff.WriteBytes(dwStartingOffset, (BYTE *)&wo, sizeof(WBEM_Object)); // If the object is not embedded, update the structure that keeps track // of top level objects. if(!bEmbedded) { m_BinMof.dwNumberOfObjects++; m_BinMof.dwLength = m_OutBuff.GetOffset(); m_OutBuff.WriteBytes(0, (BYTE *)&m_BinMof, sizeof(WBEM_Binary_MOF)); } return wo.dwLength; } //*************************************************************************** // // DWORD CBMOFOut::AddQualSet // // DESCRIPTION: // // Adds a qualifier set to the BMOF buffer. // // PARAMETERS: // // pQualifierSet pointer to qualifier object. // // RETURN VALUE: // // Number of bytes written. // //*************************************************************************** DWORD CBMOFOut::AddQualSet( IN CMoQualifierArray * pQualifierSet) { DWORD dwStartingOffset = m_OutBuff.GetOffset(); WBEM_QualifierList ql; ql.dwLength = sizeof(WBEM_QualifierList); ql.dwNumQualifiers = 0; m_OutBuff.AppendBytes((BYTE *)&ql, sizeof(WBEM_QualifierList)); BSTR bstr = NULL; VARIANT var; VariantInit(&var); int i; for(i = 0; i < pQualifierSet->GetSize(); i++) { CMoQualifier * pQual = pQualifierSet->GetAt(i); if(pQual) { ql.dwNumQualifiers++; AddQualifier(pQual->GetName(), pQual->GetpVar(), pQual); } } ql.dwLength = m_OutBuff.GetOffset() - dwStartingOffset; m_OutBuff.WriteBytes(dwStartingOffset, (BYTE *)&ql, sizeof(WBEM_QualifierList)); return ql.dwLength; } //*************************************************************************** // // DWORD CBMOFOut::AddPropSet // // DESCRIPTION: // // Adds the property set to the BMOF buffer. // // PARAMETERS: // // pObject pointer to class object. // // RETURN VALUE: // // Number of bytess written // //*************************************************************************** DWORD CBMOFOut::AddPropSet( IN CMObject * pObject) { DWORD dwStartingOffset = m_OutBuff.GetOffset(); WBEM_PropertyList pl; BSTR bstr = NULL; VARIANT var; VariantInit(&var); IWbemQualifierSet* pQual = NULL; pl.dwLength = sizeof(WBEM_PropertyList); // updated later pl.dwNumberOfProperties = 0; m_OutBuff.AppendBytes((BYTE *)&pl, sizeof(WBEM_PropertyList)); // Loop through the properties int i; for(i = 0; i < pObject->GetNumProperties(); i++) { CMoProperty * pProp = pObject->GetProperty(i); if(pProp && pProp->IsValueProperty()) { pl.dwNumberOfProperties++; CMoQualifierArray * pQual = pProp->GetQualifiers(); AddProp(pProp->GetName(), pProp->GetpVar(), pQual,pProp->GetType(),pProp); } } // Store the class name and possibly the parent name as properties. VariantInit(&var); var.vt = VT_BSTR; var.bstrVal = SysAllocString(pObject->GetClassName()); AddProp(L"__CLASS", &var, NULL,VT_BSTR,NULL); pl.dwNumberOfProperties++; VariantClear(&var); if(pObject->GetNamespace() && wcslen(pObject->GetNamespace()) > 0) { VariantInit(&var); var.vt = VT_BSTR; var.bstrVal = SysAllocString(pObject->GetNamespace()); AddProp(L"__NAMESPACE", &var, NULL,VT_BSTR,NULL); pl.dwNumberOfProperties++; VariantClear(&var); } if(pObject->GetClassFlags() != 0) { VariantInit(&var); var.vt = VT_I4; var.lVal = pObject->GetClassFlags(); AddProp(L"__CLASSFLAGS", &var, NULL,VT_I4,NULL); pl.dwNumberOfProperties++; VariantClear(&var); } if(pObject->GetInstanceFlags() != 0) { VariantInit(&var); var.vt = VT_I4; var.lVal = pObject->GetInstanceFlags(); AddProp(L"__INSTANCEFLAGS", &var, NULL,VT_I4,NULL); pl.dwNumberOfProperties++; VariantClear(&var); } if(pObject->GetAlias() && wcslen(pObject->GetAlias()) > 0) { VariantInit(&var); var.vt = VT_BSTR; var.bstrVal = SysAllocString(pObject->GetAlias()); AddProp(L"__ALIAS", &var, NULL,VT_BSTR,NULL); pl.dwNumberOfProperties++; VariantClear(&var); } if(!pObject->IsInstance()) { CMoClass * pClass = (CMoClass * )pObject; var.vt = VT_BSTR; if(pClass->GetParentName() && wcslen(pClass->GetParentName()) > 0) { var.bstrVal = SysAllocString(pClass->GetParentName()); AddProp(L"__SUPERCLASS", &var, NULL,VT_BSTR,NULL); pl.dwNumberOfProperties++; VariantClear(&var); } }; pl.dwLength = m_OutBuff.GetOffset() - dwStartingOffset; m_OutBuff.WriteBytes(dwStartingOffset, (BYTE *)&pl, sizeof(WBEM_PropertyList)); return pl.dwLength; } //*************************************************************************** // // DWORD CBMOFOut::AddMethSet // // DESCRIPTION: // // Adds the method set to the BMOF buffer. // // PARAMETERS: // // pObject pointer to class object. // // RETURN VALUE: // // Number of bytess written // //*************************************************************************** DWORD CBMOFOut::AddMethSet( IN CMObject * pObject) { DWORD dwStartingOffset = m_OutBuff.GetOffset(); WBEM_PropertyList ml; SCODE sc; IWbemQualifierSet* pQual = NULL; ml.dwLength = sizeof(WBEM_PropertyList); // updated later ml.dwNumberOfProperties = 0; m_OutBuff.AppendBytes((BYTE *)&ml, sizeof(WBEM_PropertyList)); // Loop through the properties int i; for(i = 0; i < pObject->GetNumProperties(); i++) { CMoProperty * pProp = pObject->GetProperty(i); if(pProp && !pProp->IsValueProperty()) { ml.dwNumberOfProperties++; CMoQualifierArray * pQual = pProp->GetQualifiers(); // Create a variant that has an array of embedded object for each of out // input and output arg sets CMethodProperty * pMeth = (CMethodProperty *)pProp; VARIANT vSet; if(pMeth->GetInObj() || pMeth->GetOutObj()) { vSet.vt = VT_ARRAY | VT_EMBEDDED_OBJECT; SAFEARRAYBOUND aBounds[1]; // Note the you might have either inputs, or ouputs, or both if(pMeth->GetInObj() && pMeth->GetOutObj()) aBounds[0].cElements = 2; else aBounds[0].cElements = 1; aBounds[0].lLbound = 0; #ifdef _WIN64 vSet.parray = SafeArrayCreate(VT_R8, 1, aBounds); #else vSet.parray = SafeArrayCreate(VT_I4, 1, aBounds); #endif if(vSet.parray == NULL) return FALSE; long lIndex = 0; VARIANT var; if(pMeth->GetInObj()) { var.punkVal = (IUnknown *)pMeth->GetInObj(); sc = SafeArrayPutElement(vSet.parray, &lIndex, &var.punkVal); lIndex = 1; } if(pMeth->GetOutObj()) { var.punkVal = (IUnknown *)pMeth->GetOutObj(); sc = SafeArrayPutElement(vSet.parray, &lIndex, &var.punkVal); } } else vSet.vt = VT_NULL; AddProp(pProp->GetName(), &vSet, pQual,pProp->GetType(),pProp); } } ml.dwLength = m_OutBuff.GetOffset() - dwStartingOffset; m_OutBuff.WriteBytes(dwStartingOffset, (BYTE *)&ml, sizeof(WBEM_PropertyList)); return ml.dwLength; } //*************************************************************************** // // DWORD CBMOFOut::AddProp // // DESCRIPTION: // // Adds a single property to the BMOF buffer. // // PARAMETERS: // // bstr property name // pvar variant containing value // pQual pointer to qualifier set if any. Caller will release. // dwType data type. Note that the variant might have type // VT_NULL if the property doesnt have a value. // RETURN VALUE: // // Number of bytes written // //*************************************************************************** DWORD CBMOFOut::AddProp( IN BSTR bstr, IN VARIANT * pvar, IN CMoQualifierArray * pQual, IN DWORD dwType, IN CMoProperty * pProp) { DWORD dwStartingOffset = m_OutBuff.GetOffset(); WBEM_Property prop; prop.dwLength = sizeof(WBEM_Property); if(pvar->vt == VT_NULL || pvar->vt == VT_EMPTY) prop.dwType = dwType; else prop.dwType = pvar->vt; prop.dwOffsetName = 0xffffffff; prop.dwOffsetValue = 0xffffffff; prop.dwOffsetQualifierSet = 0xffffffff; m_OutBuff.AppendBytes((BYTE *)&prop, sizeof(WBEM_Property)); DWORD dwStartInfoOffset = m_OutBuff.GetOffset(); if(bstr) { prop.dwOffsetName = m_OutBuff.GetOffset() - dwStartInfoOffset; m_OutBuff.WriteBSTR(bstr); } if(pvar->vt != VT_EMPTY && pvar->vt != VT_NULL) { prop.dwOffsetValue = m_OutBuff.GetOffset() - dwStartInfoOffset; if(pProp) { CMoValue& Value = pProp->AccessValue(); AddVariant(pvar, &Value); prop.dwType = pvar->vt; } else AddVariant(pvar, NULL); } if(pQual) { prop.dwOffsetQualifierSet = m_OutBuff.GetOffset() - dwStartInfoOffset; AddQualSet(pQual); } prop.dwLength = m_OutBuff.GetOffset() - dwStartingOffset; m_OutBuff.WriteBytes(dwStartingOffset, (BYTE *)&prop, sizeof(WBEM_Property)); return 1; } //*************************************************************************** // // DWORD CBMOFOut::AddQualifier // // DESCRIPTION: // // Adds a qualifier to the BMOF buffer. // // PARAMETERS: // // bstr qualifer name // pvar qualifier value // // RETURN VALUE: // // Number of bytes written. // //*************************************************************************** DWORD CBMOFOut::AddQualifier( IN BSTR bstr, IN VARIANT * pvar, CMoQualifier * pQual) { WBEM_Qualifier qu; DWORD dwStartingOffset = m_OutBuff.GetOffset(); long lFlavor = pQual->GetFlavor(); if(pQual->IsAmended()) lFlavor |= WBEM_FLAVOR_AMENDED; if(lFlavor) m_OutBuff.AddFlavor(lFlavor); qu.dwLength = sizeof(WBEM_Qualifier); // filled in later qu.dwType = pvar->vt; qu.dwOffsetName = 0xffffffff; qu.dwOffsetValue = 0xffffffff; m_OutBuff.AppendBytes((BYTE *)&qu, sizeof(WBEM_Qualifier)); DWORD dwStartInfoOffset = m_OutBuff.GetOffset(); // Write the qualifier name and data if(bstr) { qu.dwOffsetName = m_OutBuff.GetOffset() - dwStartInfoOffset; m_OutBuff.WriteBSTR(bstr); } if(pvar->vt != VT_EMPTY && pvar->vt != VT_NULL) { CMoValue& Value = pQual->AccessValue(); qu.dwOffsetValue = m_OutBuff.GetOffset() - dwStartInfoOffset; AddVariant(pvar, &Value); qu.dwType = pvar->vt; } qu.dwLength = m_OutBuff.GetOffset() - dwStartingOffset; m_OutBuff.WriteBytes(dwStartingOffset, (BYTE *)&qu, sizeof(WBEM_Qualifier)); return 0; } //*************************************************************************** // // DWORD CBMOFOut::AddVariant // // DESCRIPTION: // // Adds a value to the BMOF buffer. // // PARAMETERS: // // pvar value to add. // // RETURN VALUE: // // Total bytes written // //*************************************************************************** DWORD CBMOFOut::AddVariant(VARIANT * pvar, CMoValue * pValue) { if(pValue && pValue->GetNumAliases() > 0) pvar->vt |= VT_BYREF; VARTYPE vtSimple = pvar->vt & ~VT_ARRAY & ~VT_BYREF; if(pvar->vt & VT_ARRAY) { DWORD dwStartingOffset = m_OutBuff.GetOffset(); DWORD dwSize = 0; m_OutBuff.AppendBytes((BYTE *)&dwSize, sizeof(DWORD)); DWORD dwTotal = 0; SCODE sc; SAFEARRAY * psa; long ix[2] = {0,0}; long uLower, uUpper; psa = pvar->parray; sc = SafeArrayGetLBound(psa,1,&uLower); sc |= SafeArrayGetUBound(psa,1,&uUpper); if(sc != S_OK) return 0; // write the number of dimensions and the size of each DWORD dwNumDim = 1; // for now!!! m_OutBuff.AppendBytes((BYTE *)&dwNumDim, sizeof(long)); // Number of dimensions DWORD dwNumElem = uUpper - uLower + 1; m_OutBuff.AppendBytes((BYTE *)&dwNumElem, sizeof(long)); // Write out the row size DWORD dwStartingRowOffset = m_OutBuff.GetOffset(); DWORD dwRowSize = 0; m_OutBuff.AppendBytes((BYTE *)&dwRowSize, sizeof(DWORD)); // Get each element and write it for(ix[0] = uLower; ix[0] <= uUpper && sc == S_OK; ix[0]++) { VARIANT var; VariantInit(&var); var.vt = vtSimple; sc = SafeArrayGetElement(psa,ix,&var.bstrVal); if(sc != S_OK) { Trace(true, m_pDbg, SAFE_ARRAY_ERROR); } if(ix[0] < uUpper) m_OutBuff.SetPadMode(FALSE); else m_OutBuff.SetPadMode(TRUE); dwTotal += AddSimpleVariant(&var, ix[0], pValue); if(var.vt != VT_EMBEDDED_OBJECT) // Our dispatch is actual a CMObject * VariantClear(&var); } // Update the size of the property and the row. Note that having a separate size // is for possible future support of multi dimensional arrays. dwRowSize = m_OutBuff.GetOffset() - dwStartingRowOffset; m_OutBuff.WriteBytes(dwStartingRowOffset, (BYTE *)&dwRowSize, sizeof(DWORD)); dwSize = m_OutBuff.GetOffset() - dwStartingOffset; m_OutBuff.WriteBytes(dwStartingOffset, (BYTE *)&dwSize, sizeof(DWORD)); return dwTotal; } else return AddSimpleVariant(pvar, -1, pValue); } //*************************************************************************** // // DWORD CBMOFOut::AddSimpleVariant // // DESCRIPTION: // // Adds a non array variant to the BMOF buffer. // // PARAMETERS: // // pvar value to add. // iIndex set to -1 if property in scalar, or if array, has // the index of this element. Note that arrays are // broken up into simple variants. // // // RETURN VALUE: // // Bytes written //*************************************************************************** DWORD CBMOFOut::AddSimpleVariant(VARIANT * pvar, int iIndex, CMoValue * pValue) { DWORD dwSize = iTypeSize(pvar->vt & ~VT_BYREF); VARTYPE vtSimple = pvar->vt & ~VT_BYREF; if(pValue && pValue->GetNumAliases() && (vtSimple == VT_BSTR)) { WCHAR * wszAlias = NULL; int iTry, iAlIndex = -1; if(iIndex == -1) pValue->GetAlias(0, wszAlias, iAlIndex); else { for(iTry = 0; iTry < pValue->GetNumAliases(); iTry++) { pValue->GetAlias(iTry, wszAlias, iAlIndex); if(iIndex == iAlIndex) break; } if(iTry == pValue->GetNumAliases()) wszAlias = NULL; } if(wszAlias && iIndex == -1) pvar->bstrVal = SysAllocString(wszAlias); else if(wszAlias && iIndex != -1) { DWORD dwLen = wcslen(wszAlias)+2; WCHAR * pTemp = new WCHAR[dwLen]; if(pTemp == NULL) return 0; pTemp[0]= L'$'; StringCchCopyW(pTemp+1, dwLen-1, wszAlias); pvar->bstrVal = SysAllocString(pTemp); delete pTemp; } else if(wszAlias == NULL && iIndex != -1) { DWORD dwLen = wcslen(pvar->bstrVal)+2; WCHAR * pTemp = new WCHAR[dwLen]; if(pTemp == NULL) return 0; pTemp[0]= L' '; StringCchCopyW(pTemp+1, dwLen-1, pvar->bstrVal); pvar->bstrVal = SysAllocString(pTemp); delete pTemp; } } if(vtSimple == VT_BSTR) return m_OutBuff.WriteBSTR(pvar->bstrVal); else if(vtSimple == VT_EMBEDDED_OBJECT) { CMObject * pObj = (CMObject *)pvar->punkVal; return AddClass(pObj, TRUE); } else return m_OutBuff.AppendBytes((BYTE *)&pvar->bstrVal, dwSize); } //*************************************************************************** // // BOOL CBMOFOut::WriteFile // // DESCRIPTION: // // Writes the buffer out to the file. // //*************************************************************************** BOOL CBMOFOut::WriteFile() { BOOL bRet = FALSE; if(m_pFile) { m_BinMof.dwLength = m_OutBuff.GetOffset(); m_OutBuff.WriteBytes(0, (BYTE *)&m_BinMof, sizeof(WBEM_Binary_MOF)); #ifdef UNICODE char cFile[MAX_PATH]; wcstombs(cFile, m_pFile, MAX_PATH); bRet = m_OutBuff.WriteToFile(cFile); #else bRet = m_OutBuff.WriteToFile(m_pFile); #endif } return bRet; }