/*++ // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved Module Name: BMOF.C Abstract: Structures and helper functions for naviagating a BMOF file. History: a-davj 14-April-97 Created. --*/ #include #include #include #include "bmof.h" #include wchar_t ToLower(wchar_t c) { wchar_t wideChar ; if (LCMapStringW(LOCALE_INVARIANT, LCMAP_LOWERCASE, &c, 1, &wideChar, 1) ==0) { return c; } return wideChar; } wchar_t wbem_towlower(wchar_t c) { if(c >= 0 && c <= 127) { if(c >= 'A' && c <= 'Z') return c + ('a' - 'A'); else return c; } else return ToLower(c); } int wbem_wcsicmp( const wchar_t* wsz1, const wchar_t* wsz2) { while(*wsz1 || *wsz2) { int diff = wbem_towlower(*wsz1) - wbem_towlower(*wsz2); if(diff) return diff; wsz1++; wsz2++; } return 0; } int wmi_unaligned_wcslen( LPCWSTR wszString ) { BYTE* pbData = (BYTE*) wszString; int i; // Walk the string looking for two 0 bytes next to each other. for( i =0; !(!*(pbData) && !*(pbData+1) ); pbData+=2, i++ ); return i; } WCHAR* wmi_unaligned_wcscpy( WCHAR* wszDest, LPCWSTR wszSource ) { int nLen = wmi_unaligned_wcslen( wszSource ); // Account for the NULL terminator when copying CopyMemory( (BYTE*) wszDest, (BYTE*) wszSource, (nLen+1) * 2 ); return wszDest; } //*************************************************************************** // // BOOL LookupFlavor // // DESCRIPTION: // // Looks in the flavor table to see if a qualifier has a flavor. // // PARAMETERS: // // pQual Pointer to the qualifier. // pdwFlavor Pointer to where the return value is put // pBuff Pointer to the main buffer. I.e. "BMOF...." // pToFar Pointer to 1 past the last byte in the buffer // // // RETURN VALUE: // // TRUE if there is a flavor. Note that failure is normal // //*************************************************************************** BOOL LookupFlavor(BYTE * pQual, DWORD * pdwFlavor, BYTE * pBuff, BYTE * pToFar) { UNALIGNED DWORD * pTemp; BYTE * pFlavorBlob; DWORD dwNumPairs; UNALIGNED DWORD * pOffset; UNALIGNED DWORD * pFlavor; DWORD dwMyOffset; DWORD dwCnt; *pdwFlavor = 0; // Calculate the pointer of the start of the flavor data pTemp = (DWORD * )pBuff; pTemp++; // point to the original blob size pFlavorBlob = pBuff + *pTemp; // Dont even try past the end of memory if(pToFar == NULL) return FALSE; if(pFlavorBlob + 16 >= pToFar) return FALSE; // Check if the flavor blob is valid, it should start off with the // characters "BMOFQUALFLAVOR11" if(memcmp(pFlavorBlob, "BMOFQUALFLAVOR11", 16)) return FALSE; // Not really a problem since it may be old file // The flavor part of the file has the format // DWORD dwNumPair, followed by pairs of dwords; // offset, flavor // Determine the number of pairs pFlavorBlob+= 16; pTemp = (DWORD *)pFlavorBlob; dwNumPairs = *pTemp; // Number of offset/value pairs if(dwNumPairs < 1) return FALSE; // point to the first offset/flavor pair pOffset = pTemp+1; pFlavor = pOffset+1; // Determine the offset we are looking for. That is the pointer to the qualifier minus // the pointer to the start of the block; dwMyOffset = (DWORD)(pQual - pBuff); for(dwCnt = 0; dwCnt < dwNumPairs; dwCnt++) { if(dwMyOffset == *pOffset) { *pdwFlavor = *pFlavor; } if(dwMyOffset < *pOffset) return FALSE; pOffset += 2; pFlavor += 2; } return FALSE; } //*************************************************************************** // // int ITypeSize // // DESCRIPTION: // // Gets the number of bytes acutally used to store // a variant type. 0 if the type is unknown // // PARAMETERS: // // vtTest Type in question. // // // RETURN VALUE: // // see description // //*************************************************************************** int iTypeSize( IN DWORD vtTest) { int iRet; vtTest &= ~ VT_ARRAY; // get rid of possible array bit vtTest &= ~ VT_BYREF; // get rid of possible byref bit switch (vtTest) { case VT_UI1: case VT_LPSTR: iRet = 1; break; case VT_LPWSTR: case VT_BSTR: case VT_I2: iRet = 2; break; case VT_I4: case VT_R4: iRet = 4; break; case VT_R8: iRet = 8; break; case VT_BOOL: iRet = sizeof(VARIANT_BOOL); break; case VT_ERROR: iRet = sizeof(SCODE); break; case VT_CY: iRet = sizeof(CY); break; case VT_DATE: iRet = sizeof(DATE); break; default: iRet = 0; } return iRet; } //*************************************************************************** // // CBMOFQualList * CreateQualList // // DESCRIPTION: // // Create a CBMOFQualList object which serves as a wrapper. // // PARAMETERS: // // pwql pointer to the WBEM_Qualifier structure in the binary // MOF. // // RETURN VALUE: // // Pointer to CBMOFQualList structure that servers as a wrapper. NULL // if error. This must be freed via BMOFFree() when no longer needed. // // //*************************************************************************** CBMOFQualList * CreateQualList(UNALIGNED WBEM_QualifierList *pwql) { CBMOFQualList * pRet = NULL; if(pwql == NULL) return NULL; pRet = (CBMOFQualList *)BMOFAlloc(sizeof (CBMOFQualList)); if(pRet != NULL) { pRet->m_pql = pwql; pRet->m_pInfo = (UNALIGNED WBEM_Qualifier *) ((BYTE *)pRet->m_pql + sizeof(WBEM_QualifierList));; ResetQualList(pRet); } return pRet; } //*************************************************************************** // // void ResetQualList // // DESCRIPTION: // // Resets CBMOFQualList stucture to point to the first entry. // // PARAMETERS: // // pql structure to be reset // //*************************************************************************** void ResetQualList(CBMOFQualList * pql) { if(pql) { pql->m_CurrQual = 0; pql->m_pCurr = pql->m_pInfo; } } //*************************************************************************** // // BOOL NextQual // // DESCRIPTION: // // Gets the name and value of the next qualifier in the list. // // PARAMETERS: // // pql Input, points to CBMOFQualList object with data // ppName Output, if functions succeeds, this points to a // WCHAR string that the caller must free. May be // NULL if caller doesnt want name. // pItem Input/Output, if set, points to a data item structure // which will be updated to point to the qualifier data. // // RETURN VALUE: // // TRUE if OK. // // //*************************************************************************** BOOL NextQual(CBMOFQualList * pql,WCHAR ** ppName, CBMOFDataItem * pItem) { return NextQualEx(pql, ppName, pItem, NULL, NULL, NULL); } //*************************************************************************** // // BOOL NextQualEx // // DESCRIPTION: // // Gets the name and value of the next qualifier in the list. // // PARAMETERS: // // pql Input, points to CBMOFQualList object with data // ppName Output, if functions succeeds, this points to a // WCHAR string that the caller must free. May be // NULL if caller doesnt want name. // pItem Input/Output, if set, points to a data item structure // which will be updated to point to the qualifier data. // pdwFlavor optional, pointer to where the flavor value is to be copied // if not null, then pBuff must be set! // pBuff Pointer to the starting byte of the whole blob. Same as // whats copied to CreateObjList. // pToFar Pointer to one past the end of the memory buffer // // RETURN VALUE: // // TRUE if OK. // // //*************************************************************************** BOOL NextQualEx(CBMOFQualList * pql,WCHAR ** ppName, CBMOFDataItem * pItem, DWORD * pdwFlavor, BYTE * pBuff, BYTE * pToFar) { BYTE * pInfo; BOOL bRet = TRUE; if(pql == NULL || pql->m_CurrQual++ >= pql->m_pql->dwNumQualifiers) return FALSE; if(pdwFlavor && pBuff) LookupFlavor((BYTE *)pql->m_pCurr, pdwFlavor, pBuff, pToFar); pInfo = (BYTE *)pql->m_pCurr + sizeof(WBEM_Qualifier); if(ppName) SetName(ppName, pInfo, pql->m_pCurr->dwOffsetName); if(pInfo) bRet = SetValue(pItem, pInfo, pql->m_pCurr->dwOffsetValue, pql->m_pCurr->dwType); // advance to next pql->m_pCurr = (UNALIGNED WBEM_Qualifier *)((BYTE *)pql->m_pCurr + pql->m_pCurr->dwLength); return bRet; } //*************************************************************************** // // BOOL FindQual // // DESCRIPTION: // // Searches for a qualifier with a given name. The search is case // insensitive // // PARAMETERS: // // pql Input, pointer to qualifier list // pName Input, Name to be searched for. // pItem Input/Output, if successful set to point to the data. // // RETURN VALUE: // // True if OK. // //*************************************************************************** BOOL FindQual(CBMOFQualList * pql,WCHAR * pName, CBMOFDataItem * pItem) { return FindQualEx(pql, pName, pItem, NULL, NULL, NULL); } //*************************************************************************** // // BOOL FindQualEx // // DESCRIPTION: // // Searches for a qualifier with a given name. The search is case // insensitive // // PARAMETERS: // // pql Input, pointer to qualifier list // pName Input, Name to be searched for. // pItem Input/Output, if successful set to point to the data. // pdwFlavor optional, pointer to where the flavor value is to be copied // if not null, then pBuff must be set! // pBuff Pointer to the starting byte of the whole blob. Same as // whats copied to CreateObjList. // // RETURN VALUE: // // True if OK. // //*************************************************************************** BOOL FindQualEx(CBMOFQualList * pql,WCHAR * pName, CBMOFDataItem * pItem, DWORD * pdwFlavor, BYTE * pBuff, BYTE * pToFar) { DWORD dwCnt; UNALIGNED WBEM_Qualifier * pQual = pql->m_pInfo; for(dwCnt = 0; dwCnt < pql->m_pql->dwNumQualifiers; dwCnt++) { WCHAR * pTest; BOOL bMatch; BYTE * pInfo = (BYTE *)pQual + sizeof(WBEM_Qualifier); if(!SetName(&pTest, pInfo, pQual->dwOffsetName)) return FALSE; bMatch = !wbem_wcsicmp(pTest, pName); BMOFFree(pTest); if(bMatch) { if(pdwFlavor && pBuff) LookupFlavor((BYTE *)pQual, pdwFlavor, pBuff, pToFar); return SetValue(pItem, pInfo, pQual->dwOffsetValue, pQual->dwType); } pQual = (UNALIGNED WBEM_Qualifier *)((BYTE *)pQual + pQual->dwLength); } return FALSE; } //*************************************************************************** // // BOOL SetValue // // DESCRIPTION: // // Sets up a CBMOFDataItem structure to point to a value in the BMOF. // // PARAMETERS: // // pItem Input/Output, item to be set // pInfo Input, start of information block // dwOffset Input, offset to actual data. // dwType Input data type. // // RETURN VALUE: // // TRUE if OK. // //*************************************************************************** BOOL SetValue(CBMOFDataItem * pItem, BYTE * pInfo, DWORD dwOffset, DWORD dwType) { if(pItem == NULL || pInfo == NULL) return FALSE; pItem->m_dwType = dwType; // Check for NULL case. This is how uninitialized data is stored. if(dwOffset == 0xffffffff) pItem->m_pData = NULL; else pItem->m_pData = pInfo + dwOffset; return TRUE; } //*************************************************************************** // // BOOL SetName // // DESCRIPTION: // // Gets a name out of an information block. // // PARAMETERS: // // ppName Input/Output. On successful return, will point to a // WCHAR string containing the name. This MUST be freed // by the caller via BMOFFree()! // pInfo Input, start of information block // dwOffset Input, offset to actual data. // // RETURN VALUE: // // TRUE if OK. //*************************************************************************** BOOL SetName(WCHAR ** ppName, BYTE * pInfo, DWORD dwOffset) { UNALIGNED WCHAR * pName; if(ppName == NULL || pInfo == NULL || dwOffset == 0xffffffff) return FALSE; pName = (UNALIGNED WCHAR *)(pInfo + dwOffset); // point to string in info block *ppName = (WCHAR *)BMOFAlloc(2*(wmi_unaligned_wcslen((LPWSTR)pName) + 1)); if(*ppName == NULL) return FALSE; wmi_unaligned_wcscpy(*ppName, (LPWSTR)pName); return TRUE; } //*************************************************************************** // // CBMOFObj * CreateObj // // DESCRIPTION: // // Create a CBMOFObj structure which wraps a WBEM_Object // // PARAMETERS: // // pwob Input, structure to be wrapped // // RETURN VALUE: // // pointer to wrapper structure. NULL if error. This must be freed via // BMOFFree() when no longer needed. // //*************************************************************************** CBMOFObj * CreateObj(UNALIGNED WBEM_Object * pwob) { CBMOFObj * pRet = (CBMOFObj *)BMOFAlloc(sizeof(CBMOFObj)); if(pRet) { pRet->m_pob = pwob; pRet->m_pInfo = ((BYTE *)pwob) + sizeof(WBEM_Object); pRet->m_ppl = (WBEM_PropertyList*)(pRet->m_pInfo + pwob->dwOffsetPropertyList); pRet->m_pml = (WBEM_PropertyList*)(pRet->m_pInfo + pwob->dwOffsetMethodList); ResetObj(pRet); } return pRet; } //*************************************************************************** // // void ResetObj // // DESCRIPTION: // // Resets a CBMOFObj structure so that it points to its first property. // // PARAMETERS: // // pob Input/Output, stucture to be reset. // //*************************************************************************** void ResetObj(CBMOFObj * pob) { if(pob) { pob->m_CurrProp = 0; pob->m_pCurrProp = (UNALIGNED WBEM_Property *) ((BYTE *)pob->m_ppl + sizeof(WBEM_PropertyList)); pob->m_CurrMeth = 0; pob->m_pCurrMeth = (UNALIGNED WBEM_Property *) ((BYTE *)pob->m_pml + sizeof(WBEM_PropertyList)); } } //*************************************************************************** // // CBMOFQualList * GetQualList // // DESCRIPTION: // // Returns a CBMOFQualList structure which wraps the objects qualifier list. // // PARAMETERS: // // pob Input. Structure which wraps the object. // // RETURN VALUE: // // Pointer to CBMOFQualList stucture. NULL if error. Note that this must // be freed by the caller via BMOFFree() // //*************************************************************************** CBMOFQualList * GetQualList(CBMOFObj * pob) { UNALIGNED WBEM_QualifierList *pql; if(pob->m_pob->dwOffsetQualifierList == 0xffffffff) return NULL; pql = (UNALIGNED WBEM_QualifierList *)((BYTE *)pob->m_pInfo+ pob->m_pob->dwOffsetQualifierList); return CreateQualList(pql); } //*************************************************************************** // // CBMOFQualList * GetPropQualList // CBMOFQualList * GetMethQualList // // DESCRIPTION: // // Returns a CBMOFQualList structure which wraps a property or // methods qualifier list. // // PARAMETERS: // // pob Input. Structure which wraps the object. // pName Input. Property name. Note that this is case // insensitive. // // RETURN VALUE: // // Pointer to CBMOFQualList stucture. NULL if error. Note that this must // be freed by the caller via BMOFFree() // //*************************************************************************** CBMOFQualList * GetPropOrMethQualList(UNALIGNED WBEM_Property * pProp) { if(pProp == NULL) return NULL; if(pProp->dwOffsetQualifierSet == 0xffffffff) return NULL; return CreateQualList((UNALIGNED WBEM_QualifierList *)( (BYTE *)pProp + sizeof(WBEM_Property)+ pProp->dwOffsetQualifierSet)); } CBMOFQualList * GetPropQualList(CBMOFObj * pob, WCHAR * pName) { UNALIGNED WBEM_Property * pProp = FindPropPtr(pob, pName); return GetPropOrMethQualList(pProp); } CBMOFQualList * GetMethQualList(CBMOFObj * pob, WCHAR * pName) { UNALIGNED WBEM_Property * pProp = FindMethPtr(pob, pName); return GetPropOrMethQualList(pProp); } //*************************************************************************** // // BOOL NextProp // BOOL NextMet // // DESCRIPTION: // // // PARAMETERS: // // pob Input. Structure which wraps the object. // ppName Output, if functions succeeds, this points to a // WCHAR string that the caller must free. May be // NULL if caller doesnt want name. // pItem Input/Output, if set, points to a data item structure // which will be updated to point to the qualifier data. /// // RETURN VALUE: // // TRUE if OK. //*************************************************************************** BOOL Info(UNALIGNED WBEM_Property * pPropOrMeth, WCHAR ** ppName, CBMOFDataItem * pItem) { BYTE * pInfo; BOOL bRet = TRUE; if(pPropOrMeth == NULL) return FALSE; pInfo = (BYTE *)pPropOrMeth + sizeof(WBEM_Property); if(ppName) { bRet = SetName(ppName, pInfo, pPropOrMeth->dwOffsetName); if(!bRet) return FALSE; } if(pItem) bRet = SetValue(pItem, pInfo, pPropOrMeth->dwOffsetValue, pPropOrMeth->dwType); return bRet; } BOOL NextProp(CBMOFObj * pob, WCHAR ** ppName, CBMOFDataItem * pItem) { BOOL bRet = TRUE; if(pob == FALSE || pob->m_CurrProp++ >= pob->m_ppl->dwNumberOfProperties) return FALSE; if(!Info(pob->m_pCurrProp, ppName, pItem)) return FALSE; // advance pointer to next property. pob->m_pCurrProp = (UNALIGNED WBEM_Property *) ((BYTE *)pob->m_pCurrProp + pob->m_pCurrProp->dwLength); return bRet; } BOOL NextMeth(CBMOFObj * pob, WCHAR ** ppName, CBMOFDataItem * pItem) { BOOL bRet = TRUE; if(pob == FALSE || pob->m_CurrMeth++ >= pob->m_pml->dwNumberOfProperties) return FALSE; if(!Info(pob->m_pCurrMeth, ppName, pItem)) return FALSE; // advance pointer to next method. pob->m_pCurrMeth = (UNALIGNED WBEM_Property *) ((BYTE *)pob->m_pCurrMeth + pob->m_pCurrMeth->dwLength); return bRet; } //*************************************************************************** // // BOOL FindProp // BOOL FindMeth // // DESCRIPTION: // // Sets a CBMOFDataItem structure to point to a properties data. // // PARAMETERS: // // pob Input. Structure which wraps the object. // pName Input. Name to be use for case insensitve search. // pItem Input/Output. Data item stucture to be updated. // // RETURN VALUE: // // True if found. // //*************************************************************************** BOOL FindProp(CBMOFObj * pob, WCHAR * pName, CBMOFDataItem * pItem) { UNALIGNED WBEM_Property * pProp = FindPropPtr(pob, pName); return Info(pProp, NULL, pItem); } BOOL FindMeth(CBMOFObj * pob, WCHAR * pName, CBMOFDataItem * pItem) { UNALIGNED WBEM_Property * pProp = FindMethPtr(pob, pName); return Info(pProp, NULL, pItem); } //*************************************************************************** // // BOOL GetName // // DESCRIPTION: // // Gets the name of an object. This is works be returning the "__Class" // property. // // PARAMETERS: // // pob Input. Structure which wraps the object. // ppName Input/Output. Points to a WCHAR string which // has the name. The caller MUST free this via // BMOFFree() // // RETURN VALUE: // // TRUE if OK. // //*************************************************************************** BOOL GetName(CBMOFObj * pob, WCHAR ** ppName) { CBMOFDataItem Item; BOOL bRet = FALSE, bFound; if(pob == NULL || ppName == NULL) return FALSE; bFound = FindProp(pob, L"__Class", &Item); if(!bFound) return FALSE; if(Item.m_dwType == VT_BSTR && ppName) { bRet = GetData(&Item, (BYTE *)ppName, NULL); } return bRet; } //*************************************************************************** // // DWORD GetType // // DESCRIPTION: // // Returns an objects type. A 0 indicates a class while a 1 indicates an // instance. A 0xffffffff if passed a null pointer. // // PARAMETERS: // // pob Input. Structure which wraps the object. // // // RETURN VALUE: // // See description. // //*************************************************************************** DWORD GetType(CBMOFObj * pob) { if(pob) return pob->m_pob->dwType; else return 0xFFFFFFFF; } //*************************************************************************** // // WBEM_Property * FindPropPtr // WBEM_Property * FindMethPtr // // DESCRIPTION: // // Returns a WBEM_Property stucture pointer for a particular property or // method given its name. // // PARAMETERS: // // pob Input. Structure which wraps the object. // pName Input. Name of property. Comparison is case // insensitive. // // RETURN VALUE: // // pointer to WBEM_Property, NULL if it cant be found. // //*************************************************************************** UNALIGNED WBEM_Property * Search(BYTE * pList, DWORD dwListSize, WCHAR * pName) { DWORD dwCnt; UNALIGNED WBEM_Property * pProp = NULL; // point to first property structure pProp = (UNALIGNED WBEM_Property *)(pList + sizeof(WBEM_PropertyList)); for(dwCnt = 0; dwCnt < dwListSize; dwCnt++) { WCHAR * pTest; BOOL bMatch; // point to the property's name and retrieve it BYTE * pInfo = (BYTE *)pProp + sizeof(WBEM_Property); if(!SetName(&pTest, pInfo, pProp->dwOffsetName)) return NULL; bMatch = !wbem_wcsicmp(pTest, pName); BMOFFree(pTest); // If we have a match, return if(bMatch) return pProp; pProp = (UNALIGNED WBEM_Property *)((BYTE *)pProp + pProp->dwLength); } return NULL; } UNALIGNED WBEM_Property * FindPropPtr(CBMOFObj * pob, WCHAR * pName) { if(pob == NULL || pName == NULL) return NULL; // point to first property structure return Search((BYTE *)pob->m_ppl, pob->m_ppl->dwNumberOfProperties, pName); } UNALIGNED WBEM_Property * FindMethPtr(CBMOFObj * pob, WCHAR * pName) { if(pob == NULL || pName == NULL) return NULL; // point to first property structure return Search((BYTE *)pob->m_pml, pob->m_pml->dwNumberOfProperties, pName); } //*************************************************************************** // // CBMOFObjList * CreateObjList // // DESCRIPTION: // // Create a CBMOFObjList structure which wraps a BMOF file. // // PARAMETERS: // // pBuff Input, points to start of BMOF file. // // RETURN VALUE: // // pointer to wrapper structure. NULL if error. This must be freed via // BMOFFree() when no longer needed. // //*************************************************************************** CBMOFObjList * CreateObjList(BYTE * pBuff) { CBMOFObjList * pRet = (CBMOFObjList * )BMOFAlloc(sizeof(CBMOFObjList)); if(pRet) { pRet->m_pol = (WBEM_Binary_MOF *)pBuff; pRet->m_pInfo = (WBEM_Object *) ((BYTE *)pBuff + sizeof(WBEM_Binary_MOF)); ResetObjList(pRet); } return pRet; } //*************************************************************************** // // void ResetObjList // // DESCRIPTION: // // Resets a CBMOFObjList structure so that it points to its first object. // // PARAMETERS: // // pol Input/Output, stucture to be reset. // //*************************************************************************** void ResetObjList(CBMOFObjList * pol) { if(pol) { pol->m_pCurrObj = pol->m_pInfo; pol->m_CurrObj = 0; } } //*************************************************************************** // // CBMOFObj * NextObj // // DESCRIPTION: // // Gets the next object in the list. // // PARAMETERS: // // pol Input. Pointer to CBMOFObjList object // // RETURN VALUE: // // Pointer to a CBMOFObj stucture which can be use to access the object // information. NULL if error. Note that the caller MUST Free this via // BMOFFree(). // //*************************************************************************** CBMOFObj * NextObj(CBMOFObjList *pol) { CBMOFObj * pRet; if(pol == NULL || pol->m_CurrObj++ >= pol->m_pol->dwNumberOfObjects) return NULL; pRet = CreateObj(pol->m_pCurrObj); pol->m_pCurrObj = (UNALIGNED WBEM_Object *)((BYTE *)pol->m_pCurrObj + pol->m_pCurrObj->dwLength); return pRet; } //*************************************************************************** // // CBMOFObj * FindObj // // DESCRIPTION: // // Searches the object list for the first object which has a "__className" // property. The search is case insensitive. // // PARAMETERS: // // pol Input. Pointer to CBMOFObjList object // pName Input. Name of object being searched for // // RETURN VALUE: // // Pointer to a CBMOFObj stucture which can be use to access the object // information. NULL if error. Note that the caller MUST Free this via // BMOFFree(). // //*************************************************************************** CBMOFObj * FindObj(CBMOFObjList *pol, WCHAR * pName) { DWORD dwCnt; UNALIGNED WBEM_Object * pob; if(pol->m_pol == NULL || pName == NULL) return NULL; pob = pol->m_pInfo; for(dwCnt = 0; dwCnt < pol->m_pol->dwNumberOfObjects; dwCnt) { WCHAR * pwcName = NULL; BOOL bMatch = FALSE; CBMOFObj * pRet = CreateObj(pob); if(pRet == NULL) return NULL; if(GetName(pRet,&pwcName)) bMatch = TRUE; if(pwcName) BMOFFree(pwcName); // If we found it, return it, otherwise free object and advance if(bMatch) return pRet; BMOFFree(pRet); pob = (UNALIGNED WBEM_Object *)((BYTE *)pob + pob->dwLength); } return NULL; } //*************************************************************************** // // int GetNumDimensions // // DESCRIPTION: // // Returns the number of dimensions for a data item. // // PARAMETERS: // // pItem Input. Item in question. // // RETURN VALUE: // -1 if bogus argument, or if the data item doesnt hold data which would // be the case for uninitialized properties. // 0 if non array argument // n Number of dimensions. Currently only single dimension arrays are // supported. // //*************************************************************************** int GetNumDimensions(CBMOFDataItem * pItem) { UNALIGNED unsigned long * pdwTemp; if(pItem == NULL) return -1; if(!(pItem->m_dwType & VT_ARRAY)) return 0; if(pItem->m_pData == NULL) return -1; pdwTemp = (unsigned long *)pItem->m_pData; pdwTemp++; // skip past total size return *pdwTemp; } //*************************************************************************** // // int GetNumElements // // DESCRIPTION: // // Gets the number of elements for an array dimension. Note that 1 is the // first dimenstion. Currently, only scalars and 1 dimensional arrays are // supported. // // PARAMETERS: // // pItem Input. Data item in question. // lDim Input. Dimension in question. The most significent // (and for now only) dimension is 0. // // RETURN VALUE: // // Number of array elements. Note that scalars will return -1. // //*************************************************************************** int GetNumElements(CBMOFDataItem * pItem, long lDim) { int iCnt; UNALIGNED DWORD * pdwTemp; int lNumDim = GetNumDimensions(pItem); if(lNumDim == -1 || lDim > lNumDim) return -1; pdwTemp = (UNALIGNED unsigned long *)pItem->m_pData; pdwTemp++; // skip total size pdwTemp++; // skip number of dimensions for(iCnt = 0; iCnt < lDim; iCnt++) pdwTemp++; return *pdwTemp; } //*************************************************************************** // // BYTE * GetDataElemPtr // // DESCRIPTION: // // Used to get the pointer to a particular data element. Note that this is // usually used internally. // // PARAMETERS: // // pItem Input. Data item to use. // plDims Input. Pointer to array of dimension values. Note // that currenly only a single dimension is supported. // vtSimple Input. Variant type of the data with the VT_ARRAY // and VT_BYREF bits cleared. // // RETURN VALUE: // // pointer to the data. //*************************************************************************** BYTE * GetDataElemPtr(CBMOFDataItem * pItem, long * plDims, DWORD vtSimple) { int iNumDim; DWORD dwTotalDataSize; BYTE * pEndOfData; UNALIGNED DWORD * pdwCurr; UNALIGNED DWORD * pdwCurrObj; BYTE * pRow; int iCnt; // first check the number of dimensions. iNumDim = GetNumDimensions(pItem); if(iNumDim == -1) return NULL; if(iNumDim == 0) // simple case of scalar argument return pItem->m_pData; // for arrays, the data block starts off with this form, // dwtotalsize, dwNumDimenstions, dwMostSigDimension... dwLeastSigDimension // Since currently only 1 dimensional arrays are supported, a 5 element // array would start with // dwSize, 1, 5 pdwCurr = (UNALIGNED DWORD *)pItem->m_pData; dwTotalDataSize = *pdwCurr; pEndOfData = pItem->m_pData + dwTotalDataSize; pdwCurr+= 2; // skip to dimension list pdwCurr += iNumDim; // skip of dimension sizes. while((BYTE *)pdwCurr < pEndOfData) { // Each row has the format // dwSizeOfRow, MostSigDimension ... dwLeastSignificentDimension+1,data // For a one dimensional array, it would just be // dwSizeOfRow, data DWORD dwRowSize = *pdwCurr; // test if this row is ok. Each row of data will have // a set of Indicies for each higher dimension. for(iCnt = 0; iCnt < iNumDim-1; iCnt++) { UNALIGNED DWORD * pRowInd = pdwCurr +1 + iCnt; if((long)*pRowInd != plDims[iCnt]) break; } if(iCnt >= iNumDim -1) { break; // found the row. } // go to the next row pdwCurr = (UNALIGNED DWORD *)((BYTE *)pdwCurr + dwRowSize); } if((BYTE *)pdwCurr >= pEndOfData) return NULL; pRow = (BYTE *)(pdwCurr + 1 + iNumDim -1); for(iCnt = 0; iCnt < plDims[iNumDim-1]; iCnt++) { if(vtSimple == VT_BSTR) pRow += 2*(wmi_unaligned_wcslen((WCHAR *)pRow)+1); else if(vtSimple == VT_EMBEDDED_OBJECT) { // Each embedded object starts off with its own size pdwCurrObj = (DWORD *)pRow; pRow += *pdwCurrObj; } else pRow += iTypeSize(vtSimple); } return pRow; } //*************************************************************************** // // int GetData // // DESCRIPTION: // // // PARAMETERS: // // pItem Input. Data item to use. // pRet Input/Output. Pointer to where the data is to be // copied. For simple data, such as ints, this can just // be a pointer to an int. For BSTRs, or embedded // objects, this is treated as a pointer to a pointer // and it is the responsibility of the caller to free // the strings via BMOFFree(). // plDims Input. Pointer to array of dimension values. Note // that currenly only a single dimension is supported. // The first element in any dimension is 0. // RETURN VALUE: // // Number of bytes of data. //*************************************************************************** int GetData(CBMOFDataItem * pItem, BYTE * pRet, long * plDims) { DWORD dwSimple; BYTE * pData; CBMOFObj * pObjRet = NULL; dwSimple = pItem->m_dwType &~ VT_ARRAY &~VT_BYREF; pData = GetDataElemPtr(pItem, plDims, dwSimple); if(pData == NULL) return 0; if(dwSimple == VT_BSTR) { // For strings, a new WCHAR buffer is returned. Note that // SysAllocString isnt used so as to avoid any Ole dependencies. BYTE * pStr; DWORD dwSize = 2*(wmi_unaligned_wcslen((WCHAR *)pData)+1); pStr = BMOFAlloc(dwSize); if(pStr == NULL) return 0; memcpy((void *)pRet, &pStr, sizeof(void *)); wmi_unaligned_wcscpy((WCHAR *)pStr, (WCHAR *)pData); return dwSize; } else if(dwSimple == VT_EMBEDDED_OBJECT) { // This is the embedded object case. pObjRet = CreateObj((UNALIGNED WBEM_Object *)pData); memcpy((void *)pRet, &pObjRet, sizeof(void *)); return sizeof(void *); } else { memcpy((void *)pRet, (void *)pData, iTypeSize(dwSimple)); return iTypeSize(dwSimple); } }