windows-nt/Source/XPSP1/NT/admin/wmi/wbem/sdk/framedyn/npath.cpp
2020-09-26 16:20:57 +08:00

1041 lines
23 KiB
C++

// unparse singleton
// check parser return codes
/*++
Copyright (c) 1999-2001 Microsoft Corporation, All Rights Reserved
Module Name:
OBJPATH.CPP
Abstract:
Object path parser.
--*/
#include <windows.h>
#include <stdio.h>
#include <wmiutils.h>
#include <wbemcli.h>
#include "npath.h"
DWORD CalcCimType(VARTYPE vt)
{
DWORD dwRet = CIM_EMPTY;
switch (vt)
{
case VT_BSTR:
{
dwRet = CIM_STRING;
break;
}
case VT_UI1:
{
dwRet = CIM_UINT8;
break;
}
case VT_I2:
{
dwRet = CIM_CHAR16;
break;
}
case VT_I4:
{
dwRet = CIM_UINT32;
break;
}
case VT_BOOL:
{
dwRet = CIM_BOOLEAN;
break;
}
}
return dwRet;
}
ParsedObjectPath::ParsedObjectPath() :
m_pServer(NULL),
m_dwNumNamespaces(0),
m_dwAllocNamespaces(0),
m_paNamespaces(NULL),
m_pClass(NULL),
m_dwNumKeys(0),
m_dwAllocKeys(0),
m_paKeys(NULL)
{
m_paNamespaces = new LPWSTR[2];
// Note: We don't HAVE to throw here. We're trying to
// pre-allocate space. However, m_dwAllocNamespaces
// will correctly show how many pre-alloocated spaces we have
// available. During the add, we will new again
if(m_paNamespaces)
{
m_dwAllocNamespaces = 2;
for (unsigned i = 0; i < m_dwAllocNamespaces; i++)
{
m_paNamespaces[i] = NULL;
}
}
m_bSingletonObj = FALSE;
m_paKeys = new KeyRef *[2];
// Note: We don't HAVE to throw here. We're trying to
// pre-allocate space. However, m_dwAllocNamespaces
// will correctly show how many pre-alloocated spaces we have
// available. During the add, we will new again
if (m_paKeys)
{
m_dwAllocKeys = 2;
for (unsigned i = 0; i < m_dwAllocKeys; i++)
{
m_paKeys[i] = NULL;
}
}
}
ParsedObjectPath::~ParsedObjectPath()
{
if (m_pServer)
{
delete [] m_pServer;
}
if (m_paNamespaces)
{
for (DWORD dwIx = 0; dwIx < m_dwNumNamespaces; dwIx++)
{
delete m_paNamespaces[dwIx];
}
delete [] m_paNamespaces;
}
if (m_pClass)
{
delete [] m_pClass;
}
if (m_paKeys)
{
for (DWORD dwIx = 0; dwIx < m_dwNumKeys; dwIx++)
{
delete m_paKeys[dwIx];
}
delete [] m_paKeys;
}
}
void* __cdecl ParsedObjectPath::operator new( size_t n)
{
void *ptr = ::new BYTE[n];
return ptr;
}
void __cdecl ParsedObjectPath::operator delete( void *ptr )
{
::delete ptr;
}
void* __cdecl ParsedObjectPath::operator new[]( size_t n)
{
void *ptr = ::new BYTE[n];
return ptr;
}
void __cdecl ParsedObjectPath::operator delete[]( void *ptr )
{
::delete [] ptr;
}
BOOL ParsedObjectPath::SetClassName(LPCWSTR wszClassName)
{
BOOL bRet = TRUE;
if (m_pClass)
{
delete [] m_pClass;
}
if(wszClassName == NULL)
{
m_pClass = NULL;
}
else
{
DWORD dwLen = wcslen(wszClassName) + 1;
m_pClass = new WCHAR[dwLen];
if (m_pClass)
{
memcpy(m_pClass, wszClassName, dwLen * sizeof(WCHAR));
}
else
{
bRet = FALSE;
}
}
return bRet;
}
BOOL ParsedObjectPath::SetServerName(LPCWSTR wszServerName)
{
BOOL bRet = TRUE;
if (wszServerName)
{
delete [] m_pServer;
}
if(wszServerName == NULL)
{
m_pServer = NULL;
}
else
{
DWORD dwLen = wcslen(wszServerName) + 1;
m_pServer = new WCHAR[dwLen];
if (m_pServer)
{
memcpy(m_pServer, wszServerName, dwLen * sizeof(WCHAR));
}
else
{
bRet = FALSE;
}
}
return bRet;
}
BOOL ParsedObjectPath::IsClass()
{
BOOL bRet = FALSE;
if(IsObject())
{
bRet = TRUE;
}
else
{
bRet = (m_dwNumKeys == 0 && !m_bSingletonObj);
}
return bRet;
}
BOOL ParsedObjectPath::IsInstance()
{
return IsObject() && !IsClass();
}
BOOL ParsedObjectPath::IsObject()
{
BOOL bRet = FALSE;
// It's not a valid object unless we have a class name
if(m_pClass != NULL)
{
// If we have a server name, we must have namespaces. If no
// server name, then we must have zero namespaces.
if(m_pServer)
{
bRet = (m_dwNumNamespaces > 0);
}
else
{
bRet = (m_dwNumNamespaces == 0);
}
}
return bRet;
}
BOOL ParsedObjectPath::AddNamespace(LPCWSTR wszNamespace)
{
BOOL bRet = TRUE;
// See if we have filled all our existing ns slots
if(m_dwNumNamespaces == m_dwAllocNamespaces)
{
DWORD dwNewAllocNamespaces = m_dwAllocNamespaces * 2;
LPWSTR* paNewNamespaces = new LPWSTR[dwNewAllocNamespaces];
if(paNewNamespaces != NULL)
{
memcpy(paNewNamespaces, m_paNamespaces, sizeof(LPWSTR) * m_dwAllocNamespaces);
delete [] m_paNamespaces;
m_paNamespaces = paNewNamespaces;
m_dwAllocNamespaces = dwNewAllocNamespaces;
}
else
{
bRet = FALSE;
}
}
if (bRet)
{
DWORD dwLen = wcslen(wszNamespace) + 1;
m_paNamespaces[m_dwNumNamespaces] = new WCHAR[dwLen];
if (m_paNamespaces[m_dwNumNamespaces])
{
memcpy(m_paNamespaces[m_dwNumNamespaces++], wszNamespace, dwLen * sizeof(WCHAR));
}
else
{
bRet = FALSE;
}
}
return bRet;
}
BOOL ParsedObjectPath::AddKeyRefEx(LPCWSTR wszKeyName, VARIANT* pvValue )
{
BOOL bStatus = TRUE ;
BOOL bFound = FALSE ;
BOOL bUnNamed = FALSE ;
for ( ULONG dwIndex = 0 ; dwIndex < m_dwNumKeys ; dwIndex ++ )
{
if ( ( m_paKeys [ dwIndex ]->m_pName ) && wszKeyName )
{
if ( _wcsicmp ( m_paKeys [ dwIndex ]->m_pName , wszKeyName )
== 0 )
{
bFound = TRUE ;
break ;
}
}
else
{
if ( ( ( m_paKeys [ dwIndex ]->m_pName ) == 0 ) )
{
bUnNamed = TRUE ;
if ( ( wszKeyName == 0 ) )
{
bFound = TRUE ;
break ;
}
}
}
}
if ( ! wszKeyName )
{
/* Remove all existing keys */
for ( ULONG dwDeleteIndex = 0 ; dwDeleteIndex < m_dwNumKeys ;
dwDeleteIndex ++ )
{
delete [] ( m_paKeys [ dwDeleteIndex ]->m_pName ) ;
m_paKeys [ dwDeleteIndex ]->m_pName = NULL ;
VariantClear ( & ( m_paKeys [ dwDeleteIndex ]->m_vValue ) ) ;
}
bStatus = SUCCEEDED(VariantCopy(&m_paKeys [ 0 ]->m_vValue, pvValue));
m_dwNumKeys = 1 ;
}
else
{
if ( bFound )
{
/*
* If key already exists then just replace the value
*/
if ( wszKeyName )
{
m_paKeys [ dwIndex ]->m_pName = new WCHAR [ wcslen ( wszKeyName ) + 1 ] ;
if (m_paKeys [ dwIndex ]->m_pName)
{
wcscpy ( m_paKeys [ dwIndex ]->m_pName , wszKeyName ) ;
}
else
{
bStatus = FALSE;
}
}
if (bStatus)
{
bStatus = SUCCEEDED(VariantCopy(&m_paKeys [ dwIndex ]->m_vValue, pvValue));
if (!bStatus)
{
delete [] m_paKeys [ dwIndex ]->m_pName;
m_paKeys [ dwIndex ]->m_pName = NULL;
VariantClear(&m_paKeys [ dwIndex ]->m_vValue);
}
}
}
else
{
if ( bUnNamed )
{
/* Add an un named key */
for ( ULONG dwDeleteIndex = 0 ; dwDeleteIndex < m_dwNumKeys ;
dwDeleteIndex ++ )
{
delete [] ( m_paKeys [ dwDeleteIndex ]->m_pName ) ;
m_paKeys [ dwDeleteIndex ]->m_pName = NULL ;
VariantClear (& ( m_paKeys [ dwDeleteIndex ]->m_vValue ) );
}
m_paKeys [ 0 ]->m_pName = new WCHAR [ wcslen ( wszKeyName ) + 1 ] ;
if (m_paKeys [ 0 ]->m_pName)
{
wcscpy ( m_paKeys [ 0 ]->m_pName , wszKeyName ) ;
}
else
{
bStatus = FALSE;
}
if (bStatus)
{
bStatus = SUCCEEDED(VariantCopy(&m_paKeys [ 0 ]->m_vValue, pvValue));
m_dwNumKeys = 1 ;
}
if (!bStatus)
{
delete [] m_paKeys [ 0 ]->m_pName;
m_paKeys [ 0 ]->m_pName = NULL;
VariantClear(&m_paKeys [ 0 ]->m_vValue);
m_dwNumKeys = 0;
}
}
else
{
/* Add a Named Key */
AddKeyRef(wszKeyName, pvValue);
}
}
}
return bStatus;
}
void ParsedObjectPath::ClearKeys ()
{
for ( ULONG dwDeleteIndex = 0 ; dwDeleteIndex < m_dwNumKeys ;
dwDeleteIndex ++ )
{
delete m_paKeys [ dwDeleteIndex ] ;
m_paKeys [ dwDeleteIndex ] = NULL ;
}
delete [] m_paKeys ;
m_dwNumKeys = 0;
m_paKeys = new KeyRef *[2];
// Note: We don't HAVE to throw here. We're trying to
// pre-allocate space. However, m_dwAllocNamespaces
// will correctly show how many pre-alloocated spaces we have
// available. During the add, we will new again
if (m_paKeys)
{
m_dwAllocKeys = 2;
}
}
BOOL ParsedObjectPath::AddKeyRef(LPCWSTR wszKeyName, VARIANT* pvValue)
{
BOOL bRet = TRUE;
if(m_dwNumKeys == m_dwAllocKeys)
{
DWORD dwNewAllocKeys = m_dwAllocKeys * 2;
KeyRef** paNewKeys = new KeyRef*[dwNewAllocKeys];
if (paNewKeys)
{
memcpy(paNewKeys, m_paKeys, sizeof(KeyRef*) * m_dwAllocKeys);
delete [] m_paKeys;
m_paKeys = paNewKeys;
m_dwAllocKeys = dwNewAllocKeys;
}
else
{
bRet = FALSE;
}
}
if (bRet)
{
m_paKeys[m_dwNumKeys] = new KeyRef;
if (m_paKeys[m_dwNumKeys])
{
DWORD dwLen = wcslen(wszKeyName) + 1;
m_paKeys[m_dwNumKeys]->m_pName = new WCHAR[dwLen];
if (m_paKeys[m_dwNumKeys]->m_pName)
{
memcpy(m_paKeys[m_dwNumKeys]->m_pName, wszKeyName, dwLen * sizeof(WCHAR));
bRet = SUCCEEDED(VariantCopy(&m_paKeys[m_dwNumKeys]->m_vValue, pvValue));
if (bRet)
{
m_dwNumKeys++;
}
else
{
delete [] m_paKeys[m_dwNumKeys]->m_pName;
m_paKeys[m_dwNumKeys]->m_pName = NULL;
}
}
else
{
bRet = FALSE;
}
}
else
{
bRet = FALSE;
}
}
return bRet;
}
BOOL ParsedObjectPath::AddKeyRef(KeyRef* pAcquireRef)
{
BOOL bRet = TRUE;
if(m_dwNumKeys == m_dwAllocKeys)
{
DWORD dwNewAllocKeys = m_dwAllocKeys * 2;
KeyRef** paNewKeys = new KeyRef*[dwNewAllocKeys];
if(paNewKeys != NULL)
{
memcpy(paNewKeys, m_paKeys, sizeof(KeyRef*) * m_dwAllocKeys);
delete [] m_paKeys;
m_paKeys = paNewKeys;
m_dwAllocKeys = dwNewAllocKeys;
}
else
{
bRet = FALSE;
}
}
if (bRet)
{
m_paKeys[m_dwNumKeys] = pAcquireRef;
m_dwNumKeys++;
}
return bRet;
}
LPWSTR ParsedObjectPath::GetNamespacePart()
{
if (m_dwNumNamespaces == 0)
return NULL;
// Compute necessary space
// =======================
int nSpace = 0;
for(DWORD i = 0; i < m_dwNumNamespaces; i++)
{
nSpace += 1 + wcslen(m_paNamespaces[i]);
}
nSpace--;
// Allocate buffer
// ===============
LPWSTR wszOut = new WCHAR[nSpace + 1];
if (wszOut)
{
*wszOut = L'\0';
// Output
// ======
for(i = 0; i < m_dwNumNamespaces; i++)
{
if(i != 0)
{
wcscat(wszOut, L"\\");
}
wcscat(wszOut, m_paNamespaces[i]);
}
}
return wszOut;
}
LPWSTR ParsedObjectPath::GetParentNamespacePart()
{
if(m_dwNumNamespaces < 2)
{
return NULL;
}
// Compute necessary space
// =======================
int nSpace = 0;
for(DWORD i = 0; i < m_dwNumNamespaces - 1; i++)
{
nSpace += 1 + wcslen(m_paNamespaces[i]);
}
nSpace--;
// Allocate buffer
// ===============
LPWSTR wszOut = new wchar_t[nSpace + 1];
if(wszOut != NULL)
{
*wszOut = 0;
// Output
// ======
for(i = 0; i < m_dwNumNamespaces - 1; i++)
{
if(i != 0)
{
wcscat(wszOut, L"\\");
}
wcscat(wszOut, m_paNamespaces[i]);
}
}
return wszOut;
}
BOOL ParsedObjectPath::IsRelative(LPCWSTR wszMachine, LPCWSTR wszNamespace)
{
// I have no idea what this routine is for. If we are checking
// whether the parsed object is relative, why do we need params? If
// we are checking the params, why do we need the data members?
//
// On the plus side, it does the same thing as the old object parser did.
if(!IsLocal(wszMachine))
return FALSE;
if(m_dwNumNamespaces == 0)
return TRUE;
LPWSTR wszCopy = new wchar_t[wcslen(wszNamespace) + 1];
if(wszCopy == NULL)
{
return FALSE;
}
wcscpy(wszCopy, wszNamespace);
LPWSTR wszLeft = wszCopy;
BOOL bFailed = FALSE;
for(DWORD i = 0; i < m_dwNumNamespaces; i++)
{
unsigned int nLen = wcslen(m_paNamespaces[i]);
if(nLen > wcslen(wszLeft))
{
bFailed = TRUE;
break;
}
if(i == m_dwNumNamespaces - 1 && wszLeft[nLen] != 0)
{
bFailed = TRUE;
break;
}
if(i != m_dwNumNamespaces - 1 && wszLeft[nLen] != L'\\')
{
bFailed = TRUE;
break;
}
wszLeft[nLen] = 0;
if(_wcsicmp(wszLeft, m_paNamespaces[i]))
{
bFailed = TRUE;
break;
}
wszLeft += nLen+1;
}
delete [] wszCopy;
return !bFailed;
}
BOOL ParsedObjectPath::IsLocal(LPCWSTR wszMachine)
{
return (m_pServer == NULL || !wcscmp(m_pServer, L".") ||
!_wcsicmp(m_pServer, wszMachine));
}
//=================================================================================================
KeyRef::KeyRef()
{
m_pName = NULL;
VariantInit(&m_vValue);
}
KeyRef::~KeyRef()
{
delete [] m_pName;
VariantClear(&m_vValue);
}
void* __cdecl KeyRef::operator new( size_t n)
{
void *ptr = ::new BYTE[n];
return ptr;
}
void __cdecl KeyRef::operator delete( void *ptr )
{
::delete ptr;
}
void* __cdecl KeyRef::operator new[]( size_t n)
{
void *ptr = ::new BYTE[n];
return ptr;
}
void __cdecl KeyRef::operator delete[]( void *ptr )
{
::delete [] ptr;
}
//=================================================================================================
CObjectPathParser::CObjectPathParser(ObjectParserFlags eFlags)
: m_eFlags(eFlags)
{
}
CObjectPathParser::~CObjectPathParser()
{
}
void* __cdecl CObjectPathParser::operator new( size_t n)
{
void *ptr = ::new BYTE[n];
return ptr;
}
void __cdecl CObjectPathParser::operator delete( void *ptr )
{
::delete ptr;
}
void* __cdecl CObjectPathParser::operator new[]( size_t n)
{
void *ptr = ::new BYTE[n];
return ptr;
}
void __cdecl CObjectPathParser::operator delete[]( void *ptr )
{
::delete [] ptr;
}
int WINAPI CObjectPathParser::Unparse(
ParsedObjectPath* pInput,
DELETE_ME LPWSTR* pwszPath)
{
if ( (pInput == NULL) || (pInput->m_pClass == NULL) )
{
return CObjectPathParser::InvalidParameter;
}
int iRet = CObjectPathParser::NoError;
SCODE sc = S_OK;
IWbemPath *pTempParser = NULL;
sc = CoCreateInstance(CLSID_WbemDefPath, 0, CLSCTX_INPROC_SERVER,
IID_IWbemPath, (LPVOID *) &pTempParser);
if (SUCCEEDED(sc))
{
sc = pTempParser->SetClassName(pInput->m_pClass);
if (SUCCEEDED(sc))
{
sc = pTempParser->SetServer(pInput->m_pServer);
for (DWORD x=0; (x < pInput->m_dwNumNamespaces) && SUCCEEDED(sc); x++)
{
sc = pTempParser->SetNamespaceAt(x, pInput->m_paNamespaces[x]);
}
if (SUCCEEDED(sc))
{
IWbemPathKeyList *pKeyList = NULL;
sc = pTempParser->GetKeyList(&pKeyList);
if (SUCCEEDED(sc))
{
for (x=0; x < (pInput->m_dwNumKeys) && SUCCEEDED(sc); x++)
{
sc = pKeyList->SetKey2(pInput->m_paKeys[x]->m_pName,
0,
CalcCimType(pInput->m_paKeys[x]->m_vValue.vt),
&pInput->m_paKeys[x]->m_vValue);
}
pKeyList->Release();
}
if (SUCCEEDED(sc))
{
DWORD dwLen = 0;
sc = pTempParser->GetText(WBEMPATH_GET_SERVER_TOO, &dwLen, NULL);
if (SUCCEEDED(sc))
{
*pwszPath = new WCHAR[dwLen];
if (*pwszPath)
{
sc = pTempParser->GetText(WBEMPATH_GET_SERVER_TOO, &dwLen, *pwszPath);
}
else
{
iRet = CObjectPathParser::OutOfMemory;
}
}
}
}
}
pTempParser->Release();
}
if (FAILED(sc))
{
if (sc == WBEM_E_OUT_OF_MEMORY)
{
iRet = CObjectPathParser::OutOfMemory;
}
else
{
iRet = CObjectPathParser::InvalidParameter;
}
}
return iRet;
}
LPWSTR WINAPI CObjectPathParser::GetRelativePath(LPWSTR wszFullPath)
{
LPWSTR wsz = wcschr(wszFullPath, L':');
if(wsz)
return wsz + 1;
else
return NULL;
}
int CObjectPathParser::Parse(
LPCWSTR pRawPath,
ParsedObjectPath **pOutput
)
{
if (pOutput == 0 || pRawPath == 0 || pRawPath[0] == L'\0')
{
return CObjectPathParser::InvalidParameter;
}
// Check for leading / trailing ws.
// ================================
if (iswspace(pRawPath[wcslen(pRawPath)-1]) || iswspace(pRawPath[0]))
{
return InvalidParameter;
}
ParsedObjectPath *pTempPath = new ParsedObjectPath;
if (!pTempPath)
return OutOfMemory;
int iRet = CObjectPathParser::NoError;
SCODE sc = S_OK;
BOOL bRet = TRUE;
IWbemPath *pTempParser = NULL;
sc = CoCreateInstance(CLSID_WbemDefPath, 0, CLSCTX_INPROC_SERVER,
IID_IWbemPath, (LPVOID *) &pTempParser);
if (SUCCEEDED(sc))
{
sc = pTempParser->SetText(WBEMPATH_CREATE_ACCEPT_ALL, pRawPath);
if (SUCCEEDED(sc))
{
WCHAR wTemp[256];
DWORD dwSize;
//
dwSize = 256;
sc = pTempParser->GetClassName(&dwSize, wTemp);
if (SUCCEEDED(sc))
{
bRet = pTempPath->SetClassName(wTemp);
if (bRet)
{
//
dwSize = 256;
sc = pTempParser->GetServer(&dwSize, wTemp);
if (SUCCEEDED(sc))
{
bRet = pTempPath->SetServerName(wTemp);
if (bRet)
{
//
ULONG lCnt;
sc = pTempParser->GetNamespaceCount(&lCnt);
for(DWORD dwCnt = 0; (dwCnt < lCnt) && SUCCEEDED(sc) && bRet; dwCnt++)
{
dwSize = 256;
sc = pTempParser->GetNamespaceAt(dwCnt, &dwSize, wTemp);
bRet = pTempPath->AddNamespace(wTemp);
}
if (SUCCEEDED(sc) && bRet)
{
//
unsigned __int64 ull;
sc = pTempParser->GetInfo(0, &ull);
if (SUCCEEDED(sc))
{
pTempPath->m_bSingletonObj = (ull & WBEMPATH_INFO_CONTAINS_SINGLETON) > 0;
//
IWbemPathKeyList *pKeyList = NULL;
sc = pTempParser->GetKeyList(&pKeyList);
if (SUCCEEDED(sc))
{
unsigned long uNumKey;
sc = pKeyList->GetCount(&uNumKey);
ULONG ulType;
VARIANT var;
for(DWORD uKeyIx = 0;
(uKeyIx < uNumKey) && SUCCEEDED(sc) && bRet;
uKeyIx++)
{
dwSize = 256;
sc = pKeyList->GetKey2(uKeyIx, 0, &dwSize, wTemp, &var, &ulType);
if(SUCCEEDED(sc))
{
bRet = pTempPath->AddKeyRefEx(wTemp, &var);
VariantClear(&var);
}
}
pKeyList->Release();
}
}
}
}
}
}
}
}
pTempParser->Release();
}
if (!bRet)
{
iRet = CObjectPathParser::OutOfMemory;
}
else if (FAILED(sc))
{
if (sc == WBEM_E_OUT_OF_MEMORY)
{
iRet = CObjectPathParser::OutOfMemory;
}
else
{
iRet = CObjectPathParser::InvalidParameter;
}
}
// Add in key refs.
// ================
*pOutput = pTempPath;
return iRet;
}
void CObjectPathParser::Free(ParsedObjectPath *pOutput)
{
delete pOutput;
}
void CObjectPathParser::Free( LPWSTR wszUnparsedPath )
{
delete wszUnparsedPath;
}