560 lines
15 KiB
C++
560 lines
15 KiB
C++
//***************************************************************************/
|
|
//
|
|
// Copyright (c) 2000-2001 Microsoft Corporation
|
|
//
|
|
// utils.cpp
|
|
//
|
|
// ramrao Created 13 Nov 2000.
|
|
//
|
|
// Utility classes and function
|
|
//
|
|
//***************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#include "wmitoxml.h"
|
|
|
|
|
|
#define WMI2XSD_REGISTRYPATH _T("Software\\Microsoft\\Wbem\\XML")
|
|
|
|
#define WINNT_VER_UTF_SUPPORTED 4
|
|
|
|
extern DWORD g_dwNTMajorVersion;
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//**********************************************************************************************
|
|
// Utility Classes: CStringConversion
|
|
//**********************************************************************************************
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Function to convert ANSI to UNICODE string
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CStringConversion::AllocateAndConvertAnsiToUnicode(char * pstr, WCHAR *& pszW)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
pszW = NULL;
|
|
|
|
if(pstr)
|
|
{
|
|
int nSize = strlen(pstr);
|
|
if (nSize != 0 )
|
|
{
|
|
|
|
// Determine number of wide characters to be allocated for the
|
|
// Unicode string.
|
|
nSize++;
|
|
pszW = new WCHAR[nSize + 1];
|
|
if (pszW)
|
|
{
|
|
// Covert to Unicode.
|
|
if(MultiByteToWideChar(CP_ACP, 0, pstr, nSize,pszW,nSize))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
SAFE_DELETE_ARRAY(pszW);
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Function to convert UNICODE to ANSI string
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CStringConversion::UnicodeToAnsi(WCHAR * pszW, char *& pAnsi)
|
|
{
|
|
ULONG cbAnsi, cCharacters;
|
|
HRESULT hr = S_OK;
|
|
|
|
pAnsi = NULL;
|
|
if (pszW != NULL)
|
|
{
|
|
|
|
cCharacters = wcslen(pszW)+1;
|
|
// Determine number of bytes to be allocated for ANSI string. An
|
|
// ANSI string can have at most 2 bytes per character (for Double
|
|
// Byte Character Strings.)
|
|
cbAnsi = cCharacters;
|
|
pAnsi = new char[cbAnsi];
|
|
if ( pAnsi)
|
|
{
|
|
// Convert to ANSI.
|
|
if (0 != WideCharToMultiByte(CP_ACP, 0, pszW, cCharacters, pAnsi, cbAnsi, NULL, NULL))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
SAFE_DELETE_ARRAY(pAnsi);
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Converts LPWSTR to its UTF-8 encoding
|
|
// Returns -1 if it fails
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
DWORD CStringConversion::ConvertLPWSTRToUTF8(LPCWSTR theWcharString, ULONG lNumberOfWideChars, LPSTR * lppszRetValue)
|
|
{
|
|
|
|
DWORD dwRet = -1;
|
|
// Find the length of the Ansi string required
|
|
DWORD dwBytesToWrite = WideCharToMultiByte( g_dwNTMajorVersion >= WINNT_VER_UTF_SUPPORTED ? CP_UTF8 : CP_ACP, // UTF-8 code page
|
|
0, // performance and mapping flags
|
|
theWcharString, // address of wide-character string
|
|
lNumberOfWideChars, // number of characters in string
|
|
NULL, // address of buffer for new string
|
|
0, // size of buffer
|
|
NULL, // address of default for unmappable characters
|
|
NULL); // address of flag set when default char. used
|
|
|
|
if(dwBytesToWrite)
|
|
{
|
|
|
|
// Allocate the required length for the Ansi string
|
|
*lppszRetValue = NULL;
|
|
if(*lppszRetValue = new char[dwBytesToWrite])
|
|
{
|
|
|
|
// Convert BSTR to ANSI
|
|
dwRet = WideCharToMultiByte( g_dwNTMajorVersion >= WINNT_VER_UTF_SUPPORTED ? CP_UTF8 : CP_ACP, // use UTF8 page if available
|
|
0, // performance and mapping flags // else use AnsiCode page
|
|
theWcharString, // address of wide-character string
|
|
lNumberOfWideChars, // number of characters in string
|
|
*lppszRetValue, // address of buffer for new string
|
|
dwBytesToWrite, // size of buffer
|
|
NULL, // address of default for unmappable characters
|
|
NULL); // address of flag set when default
|
|
// char. used
|
|
}
|
|
}
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//**********************************************************************************************
|
|
// End of Utility Class CStringConversion
|
|
//**********************************************************************************************
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// TranslateAndLog
|
|
// Logs message to a log file
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void TranslateAndLog( WCHAR * wcsMsg )
|
|
{
|
|
char * pStr = NULL;
|
|
|
|
if( SUCCEEDED(CStringConversion::UnicodeToAnsi(wcsMsg,pStr)))
|
|
{
|
|
// ERRORTRACE((THICOMPONENT,pStr));
|
|
//ERRORTRACE((THICOMPONENT,"\n"));
|
|
SAFE_DELETE_ARRAY(pStr);
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// LoadAndAllocateStringW
|
|
// Loads a string from string table. ALlocates memory for the string
|
|
// calling funcition should releas the memory
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT LoadAndAllocateStringW(LONG strID , WCHAR *& pwcsOut)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
TCHAR * pStrTemp = NULL;
|
|
|
|
if(SUCCEEDED(hr = LoadAndAllocateString(strID , pStrTemp)))
|
|
{
|
|
|
|
#ifndef UNICODE
|
|
hr = CStringConversion::AllocateAndConvertAnsiToUnicode(pStrTemp,pwcsOut);
|
|
SAFE_DELETE_ARRAY(pStrTemp);
|
|
#else
|
|
pwcsOut = pStrTemp;
|
|
#endif
|
|
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// LoadAndAllocateStringA
|
|
// Loads a string from string table. ALlocates memory for the string
|
|
// calling funcition should releas the memory
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT LoadAndAllocateStringA(LONG strID , char *& pszOut)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
TCHAR * pStrTemp = NULL;
|
|
|
|
if(SUCCEEDED(hr = LoadAndAllocateString(strID , pStrTemp)))
|
|
{
|
|
|
|
#ifdef UNICODE
|
|
hr = CStringConversion::UnicodeToAnsi(pStrTemp,pszOut);
|
|
SAFE_DELETE_ARRAY(pStrTemp);
|
|
#else
|
|
pszOut = pStrTemp;
|
|
#endif
|
|
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
|
#define INITBUFSIZE 100
|
|
#define INCRBUFFSIZE 50
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// LoadAndAllocateString
|
|
// Loads a string from the string table. Allocates memory
|
|
// and caller has to free the memory
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT LoadAndAllocateString(LONG strID , TCHAR *& pstrOut)
|
|
{
|
|
int nLen = 0;
|
|
int nAllocSize = 0;
|
|
HRESULT hr = S_OK;
|
|
|
|
do
|
|
{
|
|
SAFE_DELETE_ARRAY(pstrOut);
|
|
nAllocSize = nAllocSize ? (nAllocSize + INCRBUFFSIZE) : INITBUFSIZE ;
|
|
|
|
pstrOut = new TCHAR[nAllocSize];
|
|
if(pstrOut)
|
|
{
|
|
nLen = ::LoadString(g_hModule, strID, pstrOut, nAllocSize);
|
|
}
|
|
else
|
|
{
|
|
SAFE_DELETE_ARRAY(pstrOut);
|
|
hr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
}
|
|
while((nLen + 1) >= nAllocSize);
|
|
|
|
return hr; // excluding terminator
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// WriteToFile
|
|
// Writes data to a file.
|
|
// If file name is not given then data is written to %SYSTEMDIR%\wbem\logs\xmlencoder.log file
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT WriteToFile(char * strData ,TCHAR *pFileName)
|
|
{
|
|
HANDLE hFile;
|
|
TCHAR strFileName[512];
|
|
|
|
if(GetSystemDirectory(strFileName,512))
|
|
{
|
|
_tcscat(strFileName,_T("\\wbem\\"));
|
|
if(pFileName)
|
|
{
|
|
_tcscat(strFileName,pFileName);
|
|
}
|
|
else
|
|
{
|
|
_tcscat(strFileName,_T("wmi2xsd.xml"));
|
|
}
|
|
}
|
|
|
|
DWORD nLen = (strlen(strData) + 1) * sizeof(char);
|
|
|
|
if(INVALID_HANDLE_VALUE !=
|
|
(hFile = CreateFile(strFileName,GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL)))
|
|
{
|
|
char * pData = NULL;
|
|
nLen = strlen(strData);
|
|
BOOL bWrite = WriteFile(hFile,(VOID *)strData,nLen,&nLen,NULL);
|
|
|
|
CloseHandle(hFile);
|
|
}
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Function to compare data of same types and check if both are same
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
BOOL CompareData(VARIANT * pvData1 , VARIANT *pvData2)
|
|
{
|
|
|
|
BOOL bRet = FALSE;
|
|
|
|
if(!((pvData2->vt & VT_ARRAY) || (pvData1->vt & VT_ARRAY) ))
|
|
{
|
|
|
|
if(VT_NULL == pvData1->vt || pvData2->vt == VT_NULL)
|
|
{
|
|
// if both the property is NULL then return TRUE
|
|
if(VT_NULL == pvData1->vt && pvData2->vt == VT_NULL)
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
HRESULT hr = VarCmp(pvData1,pvData2 ,LOCALE_USER_DEFAULT, NORM_IGNORECASE ); // FIX get LCID
|
|
bRet = hr == VARCMP_EQ ? TRUE: FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// FIXX compare arrays
|
|
}
|
|
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// checks if the given property is an embedded object
|
|
// and returns the number
|
|
// Return Values: the logging level
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
BOOL IsEmbededType(LONG cimtype)
|
|
{
|
|
return (cimtype == CIM_OBJECT) || (cimtype == (CIM_OBJECT | CIM_FLAG_ARRAY));
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Reads registry "LoggingLevel" keyvalue at HKEY_LOCAL_MACHINE\software\microsoft\wbem\xml
|
|
// and returns the number
|
|
// Return Values: the logging level
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
ULONG GetLoggingLevel()
|
|
{
|
|
ULONG nLoggingLevel = 0;
|
|
HKEY hKey;
|
|
|
|
// Get the Logging level
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
WMI2XSD_REGISTRYPATH, 0, KEY_QUERY_VALUE, &hKey))
|
|
{
|
|
DWORD dwlen = 0;
|
|
|
|
dwlen = sizeof (nLoggingLevel);
|
|
|
|
if (ERROR_SUCCESS != RegQueryValueEx (hKey, _T("LoggingLevel"),
|
|
NULL, NULL, (BYTE *) &nLoggingLevel, &dwlen))
|
|
{
|
|
nLoggingLevel = 0;
|
|
}
|
|
RegCloseKey (hKey);
|
|
}
|
|
|
|
return nLoggingLevel;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// copies data from source stream to destination stream.
|
|
//
|
|
// Parameters:
|
|
// pStreamIn - Source stream pointer
|
|
// pOutStream - Destination stream pointer
|
|
// bConvertToUTF8 - Flag which determines if data has to be converted to UTF8
|
|
// before writing to destination stream
|
|
// Return Values: S_OK -
|
|
// E_FAIL -
|
|
// E_OUTOFMEMORY
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CopyStream(IStream *pStreamIn , IStream *pOutStream,BOOL bConvertToUTF8)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
STATSTG stat;
|
|
LARGE_INTEGER lSeek;
|
|
LARGE_INTEGER lCur;
|
|
|
|
|
|
memset(&lCur,0,sizeof(LARGE_INTEGER));
|
|
memset(&lSeek , 0, sizeof(LARGE_INTEGER));
|
|
|
|
// Store the current seek pointer
|
|
pOutStream->Seek(lSeek,STREAM_SEEK_CUR,(ULARGE_INTEGER *)&lCur);
|
|
|
|
if(SUCCEEDED(hr = pStreamIn->Stat(&stat,STATFLAG_NONAME )) && stat.cbSize.LowPart && // get the lenght
|
|
SUCCEEDED(hr =pStreamIn->Seek(lSeek,STREAM_SEEK_SET,(ULARGE_INTEGER *)&lSeek)) ) // move to the begining of stream
|
|
{
|
|
void * pStrOut = NULL;
|
|
LPWSTR pstrTemp = NULL;
|
|
ULONG lSizeWritten = 0;
|
|
ULONG lSizeRead = 0;
|
|
ULONG lSizeinWchars = stat.cbSize.LowPart /sizeof(WCHAR);
|
|
|
|
pstrTemp = new WCHAR[lSizeinWchars + 2];
|
|
|
|
if(pstrTemp)
|
|
{
|
|
pstrTemp[lSizeinWchars] = 0;
|
|
while (lSizeRead <= lSizeinWchars)
|
|
{
|
|
if(SUCCEEDED(hr = pStreamIn->Read(pstrTemp,lSizeinWchars * sizeof(WCHAR),&lSizeRead)))
|
|
{
|
|
if(!lSizeRead)
|
|
{
|
|
break;
|
|
}
|
|
// NULL terminate the string
|
|
pstrTemp[lSizeinWchars] = 0;
|
|
|
|
if(bConvertToUTF8)
|
|
{
|
|
// call this function to convert WCHAR to UTF8 format
|
|
lSizeWritten = (ULONG)CStringConversion::ConvertLPWSTRToUTF8( pstrTemp,
|
|
lSizeinWchars * sizeof(WCHAR) > lSizeRead ? lSizeRead/sizeof(WCHAR) : lSizeinWchars ,
|
|
(LPSTR *)&pStrOut);
|
|
}
|
|
else
|
|
{
|
|
pStrOut = pstrTemp;
|
|
lSizeWritten = wcslen(pstrTemp) * sizeof(WCHAR);
|
|
}
|
|
|
|
if(lSizeWritten >0)
|
|
{
|
|
ULONG lTest;
|
|
hr = pOutStream->Write(pStrOut,(ULONG)lSizeWritten ,&lTest);
|
|
}
|
|
}
|
|
if(FAILED(hr))
|
|
{
|
|
break;
|
|
}
|
|
|
|
}
|
|
if(bConvertToUTF8)
|
|
{
|
|
SAFE_DELETE_ARRAY(pStrOut);
|
|
}
|
|
|
|
SAFE_DELETE_ARRAY(pstrTemp);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
SAFE_DELETE_ARRAY(pstrTemp);
|
|
}
|
|
// Reset the position to the previous one
|
|
pOutStream->Seek(lCur,STREAM_SEEK_SET,NULL);
|
|
return hr;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Checks if the given property is NULL of not
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
BOOL IsPropNull(VARIANT *pVar)
|
|
{
|
|
return ((pVar->vt == VT_NULL) || (pVar->vt == VT_EMPTY));
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Checks if the given property value is given as strings
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
BOOL IsStringType(CIMTYPE cimtype)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
switch(cimtype)
|
|
{
|
|
case VT_BSTR:
|
|
case CIM_UINT64:
|
|
case CIM_SINT64:
|
|
case CIM_DATETIME:
|
|
bRet = TRUE;
|
|
break;
|
|
|
|
default:
|
|
bRet = FALSE;
|
|
};
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Checks if the given property/qualifier name is valid
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT IsValidName(WCHAR *pstrName)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
if(pstrName)
|
|
{
|
|
if(wcslen(pstrName) > 0)
|
|
{
|
|
if(iswalpha(*pstrName))
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
} |