// unparse singleton // check parser return codes /*++ Copyright (c) 1999-2001 Microsoft Corporation, All Rights Reserved Module Name: OBJPATH.CPP Abstract: Object path parser. --*/ #include #include #include #include #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; }