You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
924 lines
27 KiB
924 lines
27 KiB
/*++
|
|
|
|
Copyright (C) 1996-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
MOFDATA.CPP
|
|
|
|
Abstract:
|
|
|
|
Entry points for the WBEM MOF compiler.
|
|
|
|
History:
|
|
|
|
a-davj 12-April-97 Added WMI support.
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <cominit.h>
|
|
#include "mofout.h"
|
|
#include "mofdata.h"
|
|
#include "typehelp.h"
|
|
#include "bmof.h"
|
|
#include "cbmofout.h"
|
|
#include "trace.h"
|
|
#include "strings.h"
|
|
#include "arrtempl.h"
|
|
#include <genutils.h>
|
|
|
|
#define TEMP_BUF 128
|
|
|
|
WCHAR * Macro_CloneStr(LPCWSTR pFr)
|
|
{
|
|
if(pFr == NULL)
|
|
return NULL;
|
|
DWORD dwLen = wcslen(pFr) + 1;
|
|
WCHAR * pTo = new WCHAR[dwLen];
|
|
if(pTo)
|
|
{
|
|
StringCchCopyW(pTo, dwLen, pFr);
|
|
return pTo;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
HRESULT MofdSetInterfaceSecurity(IUnknown * pInterface, LPWSTR pAuthority, LPWSTR pUser,
|
|
LPWSTR pPassword)
|
|
{
|
|
SCODE sc;
|
|
BOOL bUseAuthInfo = FALSE;
|
|
|
|
DWORD dwQueryAuthnLevel, dwQueryImpLevel, dwQueryCapabilities;
|
|
DWORD dwAuthnSvc = RPC_C_AUTHN_GSS_NEGOTIATE;
|
|
WCHAR * pwCSPBPrincipal = NULL;
|
|
|
|
HRESULT hr = CoQueryProxyBlanket(
|
|
pInterface, //Location for the proxy to query
|
|
&dwAuthnSvc, //Location for the current authentication service
|
|
NULL, //Location for the current authorization service
|
|
NULL, //Location for the current principal name
|
|
&dwQueryAuthnLevel, //Location for the current authentication level
|
|
&dwQueryImpLevel, //Location for the current impersonation level
|
|
NULL,
|
|
&dwQueryCapabilities //Location for flags indicating further capabilities of the proxy
|
|
);
|
|
if(SUCCEEDED(hr) && dwAuthnSvc != RPC_C_AUTHN_WINNT)
|
|
{
|
|
pwCSPBPrincipal = COLE_DEFAULT_PRINCIPAL;
|
|
}
|
|
else
|
|
{
|
|
dwAuthnSvc = RPC_C_AUTHN_WINNT;
|
|
pwCSPBPrincipal = NULL;
|
|
}
|
|
|
|
|
|
|
|
// If we are doing trivial case, just pass in a null authenication structure which is used
|
|
// if the current logged in user's credentials are OK.
|
|
|
|
if((pAuthority == NULL || wcslen(pAuthority) < 1) &&
|
|
(pUser == NULL || wcslen(pUser) < 1) &&
|
|
(pPassword == NULL || wcslen(pPassword) < 1))
|
|
{
|
|
return WbemSetProxyBlanket(pInterface, dwAuthnSvc, RPC_C_AUTHZ_NONE,
|
|
pwCSPBPrincipal,
|
|
RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE,
|
|
NULL,
|
|
EOAC_STATIC_CLOAKING);
|
|
}
|
|
|
|
// If user, or Authority was passed in, the we need to create an authority argument for the login
|
|
|
|
COAUTHIDENTITY authident;
|
|
BSTR AuthArg = NULL, UserArg = NULL, PrincipalArg = NULL;
|
|
sc = DetermineLoginTypeEx(AuthArg, UserArg, PrincipalArg, pAuthority, pUser);
|
|
if(sc != S_OK)
|
|
return sc;
|
|
CSysFreeMe fm1(UserArg), fm2(AuthArg), fm3(PrincipalArg);
|
|
|
|
memset((void *)&authident,0,sizeof(COAUTHIDENTITY));
|
|
if(UserArg)
|
|
{
|
|
authident.UserLength = wcslen(UserArg);
|
|
authident.User = (LPWSTR)UserArg;
|
|
bUseAuthInfo = TRUE;
|
|
}
|
|
if(AuthArg)
|
|
{
|
|
authident.DomainLength = wcslen(AuthArg);
|
|
authident.Domain = (LPWSTR)AuthArg;
|
|
bUseAuthInfo = TRUE;
|
|
}
|
|
if(pPassword)
|
|
{
|
|
authident.PasswordLength = wcslen(pPassword);
|
|
authident.Password = (LPWSTR)pPassword;
|
|
bUseAuthInfo = TRUE;
|
|
}
|
|
authident.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
|
|
|
|
sc = WbemSetProxyBlanket(pInterface,
|
|
(PrincipalArg) ? RPC_C_AUTHN_GSS_KERBEROS : dwAuthnSvc,
|
|
RPC_C_AUTHZ_NONE,
|
|
(PrincipalArg) ? PrincipalArg : pwCSPBPrincipal,
|
|
RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE,
|
|
(bUseAuthInfo) ? &authident : NULL,
|
|
(bUseAuthInfo) ? 0 : EOAC_STATIC_CLOAKING
|
|
);
|
|
return sc;
|
|
}
|
|
|
|
CNamespaceCache::CNamespaceRecord::CNamespaceRecord(
|
|
COPY LPCWSTR wszName,
|
|
ADDREF IWbemServices* pNamespace)
|
|
{
|
|
m_wszName = Macro_CloneStr(wszName);
|
|
m_pNamespace = pNamespace;
|
|
m_pNamespace->AddRef();
|
|
}
|
|
|
|
CNamespaceCache::CNamespaceRecord::~CNamespaceRecord()
|
|
{
|
|
delete [] m_wszName;
|
|
if(m_pNamespace) m_pNamespace->Release();
|
|
}
|
|
|
|
//*****************************************************************************
|
|
|
|
CNamespaceCache::CNamespaceCache(ADDREF IWbemLocator* pLocator)
|
|
{
|
|
if(pLocator)
|
|
pLocator->AddRef();
|
|
m_pLocator = pLocator;
|
|
}
|
|
|
|
CNamespaceCache::~CNamespaceCache()
|
|
{
|
|
if(m_pLocator) m_pLocator->Release();
|
|
for(int i = 0; i < m_aRecords.GetSize(); i++)
|
|
{
|
|
delete (CNamespaceRecord*)m_aRecords[i];
|
|
}
|
|
}
|
|
|
|
RELEASE_ME IWbemServices* CNamespaceCache::GetNamespace(COPY LPCWSTR wszName, SCODE & scRet,
|
|
WCHAR * pUserName, WCHAR * pPassword , WCHAR * pAuthority,
|
|
IWbemContext * pCtx, GUID LocatorGUID, LONG fConnectFlags)
|
|
{
|
|
// Check if it is the cache
|
|
// ========================
|
|
|
|
scRet = S_OK;
|
|
|
|
for(int i = 0; i < m_aRecords.GetSize(); i++)
|
|
{
|
|
CNamespaceRecord* pRecord = (CNamespaceRecord*)m_aRecords[i];
|
|
if(!wbem_wcsicmp(pRecord->m_wszName, wszName))
|
|
{
|
|
// Found it
|
|
// ========
|
|
|
|
pRecord->m_pNamespace->AddRef();
|
|
return pRecord->m_pNamespace;
|
|
}
|
|
}
|
|
|
|
// Not found --- open it
|
|
// =====================
|
|
|
|
IWbemServices* pNamespace;
|
|
|
|
if(wszName == NULL)
|
|
return NULL;
|
|
|
|
LPOLESTR pwszName;
|
|
pwszName = SysAllocString(wszName);
|
|
if(pwszName == NULL)
|
|
return NULL;
|
|
CSysFreeMe fm0(pwszName);
|
|
|
|
LPOLESTR bstrPassword = NULL;
|
|
LPOLESTR bstrUserName = NULL;
|
|
LPOLESTR bstrAuthority = NULL;
|
|
if(pUserName && wcslen(pUserName) > 0)
|
|
{
|
|
bstrUserName = SysAllocString(pUserName);
|
|
if(bstrUserName == NULL)
|
|
return NULL;
|
|
}
|
|
CSysFreeMe fm1(bstrUserName);
|
|
|
|
if(pPassword)
|
|
{
|
|
bstrPassword = SysAllocString(pPassword);
|
|
if(bstrPassword == NULL)
|
|
return NULL;
|
|
}
|
|
CSysFreeMe fm2(bstrPassword);
|
|
if(pAuthority && wcslen(pAuthority) > 0)
|
|
{
|
|
bstrAuthority = SysAllocString(pAuthority);
|
|
if(bstrAuthority == NULL)
|
|
return NULL;
|
|
}
|
|
CSysFreeMe fm3(bstrAuthority);
|
|
|
|
// Determine if the connection is to the regular locator, or to one of the special inproc ones
|
|
// used for autocompile. If it is inproc, then remote connections are not valid.
|
|
|
|
bool bInProc = false;
|
|
if(LocatorGUID != CLSID_WbemLocator)
|
|
bInProc = true;
|
|
|
|
if(bInProc)
|
|
{
|
|
WCHAR * pMachine = ExtractMachineName(pwszName);
|
|
if(pMachine)
|
|
{
|
|
BOOL bLocal = bAreWeLocal(pMachine);
|
|
delete pMachine;
|
|
if(!bLocal)
|
|
{
|
|
scRet = WBEM_E_INVALID_NAMESPACE;
|
|
ERRORTRACE((LOG_MOFCOMP,"Error, tried to do a remote connect during autocomp\n"));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Connect up to namespace. //TODO, PASS AUTHORITY IN THE CONTEXT
|
|
|
|
if(scRet == S_OK)
|
|
scRet = m_pLocator->ConnectServer((LPWSTR)pwszName,
|
|
bstrUserName, bstrPassword,
|
|
NULL, fConnectFlags,
|
|
pAuthority, pCtx, &pNamespace);
|
|
|
|
if(scRet == S_OK && !bInProc)
|
|
{
|
|
|
|
// Set the impersonation level up so that puts to providers can be done
|
|
|
|
DWORD dwAuthLevel, dwImpLevel;
|
|
SCODE sc = GetAuthImp( pNamespace, &dwAuthLevel, &dwImpLevel);
|
|
if(sc != S_OK || dwAuthLevel != RPC_C_AUTHN_LEVEL_NONE)
|
|
sc = MofdSetInterfaceSecurity(pNamespace, bstrAuthority, bstrUserName, bstrPassword);
|
|
|
|
}
|
|
|
|
if(FAILED(scRet)) return NULL;
|
|
|
|
// Add it to the cache
|
|
// ===================
|
|
|
|
CNamespaceRecord * pNew = new CNamespaceRecord(wszName, pNamespace);
|
|
if(pNew)
|
|
m_aRecords.Add(pNew); // AddRef'ed
|
|
|
|
return pNamespace;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//*****************************************************************************
|
|
//*****************************************************************************
|
|
|
|
void CMofData::SetQualifierDefault(ACQUIRE CMoQualifier* pDefault)
|
|
{
|
|
// Search for this qualifier in the defaults list
|
|
// ==============================================
|
|
|
|
for(int i = 0; i < m_aQualDefaults.GetSize(); i++)
|
|
{
|
|
CMoQualifier* pOrig = (CMoQualifier*)m_aQualDefaults[i];
|
|
|
|
if(wbem_wcsicmp(pOrig->GetName(), pDefault->GetName()) == 0)
|
|
{
|
|
// Found it. Replace
|
|
// =================
|
|
|
|
delete pOrig;
|
|
m_aQualDefaults[i] = (void*)pDefault;
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Not found. Add
|
|
// ==============
|
|
|
|
m_aQualDefaults.Add((void*)pDefault);
|
|
}
|
|
|
|
HRESULT CMofData::SetDefaultFlavor(MODIFY CMoQualifier& Qual, bool bTopLevel, QUALSCOPE qs, PARSESTATE ps)
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
// Search for this qualifier in the defaults list
|
|
// ==============================================
|
|
|
|
for(int i = 0; i < m_aQualDefaults.GetSize(); i++)
|
|
{
|
|
CMoQualifier* pOrig = (CMoQualifier*)m_aQualDefaults[i];
|
|
|
|
if(wbem_wcsicmp(pOrig->GetName(), Qual.GetName()) == 0)
|
|
{
|
|
// Found it. SetFlavor
|
|
// ===================
|
|
|
|
if(pOrig->IsCimDefault())
|
|
{
|
|
// dont bother if the parse state is the initial scan
|
|
|
|
if(ps == INITIAL)
|
|
continue;
|
|
if(Qual.IsUsingDefaultValue())
|
|
{
|
|
|
|
// see if the scope matches what we have here
|
|
|
|
DWORD dwScope = pOrig->GetScope();
|
|
bool bInScope = false;
|
|
if((dwScope & SCOPE_CLASS) || (dwScope & SCOPE_INSTANCE))
|
|
if(qs == CLASSINST_SCOPE)
|
|
bInScope = true;
|
|
if(dwScope & SCOPE_PROPERTY)
|
|
if(qs == PROPMETH_SCOPE)
|
|
bInScope = true;
|
|
|
|
if(bInScope)
|
|
{
|
|
CMoValue& Src = pOrig->AccessValue();
|
|
CMoValue& Dest = Qual.AccessValue();
|
|
Dest.SetType(Src.GetType());
|
|
VARIANT & varSrc = Src.AccessVariant();
|
|
VARIANT & varDest = Dest.AccessVariant();
|
|
hr = VariantCopy(&varDest, &varSrc);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
Qual.SetFlavor(pOrig->GetFlavor());
|
|
Qual.SetAmended(pOrig->IsAmended());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Qual.SetFlavor(pOrig->GetFlavor());
|
|
Qual.SetAmended(pOrig->IsAmended());
|
|
}
|
|
return S_OK;
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
BOOL CMofData::IsAliasInUse(READ_ONLY LPWSTR wszAlias)
|
|
{
|
|
for(int i = 0; i < m_aObjects.GetSize(); i++)
|
|
{
|
|
CMObject* pObject = (CMObject*)m_aObjects[i];
|
|
if(pObject->GetAlias() && !wbem_wcsicmp(pObject->GetAlias(), wszAlias))
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL IsGuid(LPWSTR pTest)
|
|
{
|
|
int i;
|
|
int iSoFar = 0;
|
|
|
|
#define HEXCHECK(n) \
|
|
for (i = 0; i < n; i++) \
|
|
if (!iswxdigit(*pTest++)) \
|
|
return FALSE;
|
|
|
|
#define HYPHENCHECK() \
|
|
if (*pTest++ != L'-') \
|
|
return FALSE;
|
|
|
|
if(*pTest++ != L'{')
|
|
return FALSE;
|
|
|
|
HEXCHECK(8);
|
|
HYPHENCHECK();
|
|
HEXCHECK(4);
|
|
HYPHENCHECK();
|
|
HEXCHECK(4);
|
|
HYPHENCHECK();
|
|
HEXCHECK(4);
|
|
HYPHENCHECK();
|
|
HEXCHECK(12);
|
|
|
|
if(*pTest++ != L'}')
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
INTERNAL LPCWSTR CMofData::FindAliasee(READ_ONLY LPWSTR wszAlias)
|
|
{
|
|
for(int i = 0; i < m_aObjects.GetSize(); i++)
|
|
{
|
|
CMObject* pObject = (CMObject*)m_aObjects[i];
|
|
if(pObject->GetAlias() && !wbem_wcsicmp(pObject->GetAlias(), wszAlias))
|
|
{
|
|
IWbemClassObject * pTemp;
|
|
pTemp = pObject->GetWbemObject();
|
|
|
|
// check for unresolved aliases in keys
|
|
|
|
if(pTemp && pObject->IsDone() == FALSE)
|
|
{
|
|
|
|
SCODE sc = pTemp->BeginEnumeration(WBEM_FLAG_KEYS_ONLY | WBEM_FLAG_REFS_ONLY);
|
|
if(sc != S_OK)
|
|
return NULL;
|
|
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
while ((sc = pTemp->Next(0, NULL, &var, NULL, NULL)) == S_OK)
|
|
{
|
|
if(var.vt == VT_BSTR && IsGuid(var.bstrVal))
|
|
{
|
|
VariantClear(&var);
|
|
return NULL;
|
|
}
|
|
VariantClear(&var);
|
|
}
|
|
}
|
|
return pObject->GetFullPath();
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
HRESULT CMofData::Store(CMofParser & Parser, OLE_MODIFY IWbemLocator* pLocator,IWbemServices *pOverride,BOOL bRollbackable,
|
|
WCHAR * pUserName, WCHAR * pPassword, WCHAR * pAuthority,
|
|
IWbemContext * pCtx, GUID LocatorGUID, WBEM_COMPILE_STATUS_INFO *pInfo,
|
|
BOOL bClassOwnerUpdate,
|
|
BOOL bInstanceOwnerUpdate,
|
|
LONG fConnectFlags)
|
|
{
|
|
HRESULT hres = WBEM_E_FAILED;
|
|
int i;
|
|
CNamespaceCache Cache(pLocator);
|
|
BOOL bMakingProgress = TRUE;
|
|
long lClassFlags = 0;
|
|
long lInstanceFlags = 0;
|
|
|
|
|
|
while(bMakingProgress)
|
|
{
|
|
bMakingProgress = FALSE;
|
|
for(i = 0; i< m_aObjects.GetSize(); i++)
|
|
{
|
|
CMObject* pObject = (CMObject*)m_aObjects[i];
|
|
|
|
if(pObject->IsDone())
|
|
continue;
|
|
lClassFlags = pObject->GetClassFlags();
|
|
lInstanceFlags = pObject->GetInstanceFlags();
|
|
if(bClassOwnerUpdate)
|
|
{
|
|
lClassFlags |= WBEM_FLAG_OWNER_UPDATE;
|
|
}
|
|
if(bInstanceOwnerUpdate)
|
|
{
|
|
lInstanceFlags |= WBEM_FLAG_OWNER_UPDATE;
|
|
}
|
|
// Get a namespace pointer for this object.
|
|
|
|
SCODE scRet;
|
|
IWbemServices* pNamespace = NULL;
|
|
if(pOverride && !wbem_wcsicmp(L"root\\default", pObject->GetNamespace()))
|
|
{
|
|
// AddRef() the namespace pointer, since we will be Releasing
|
|
// it below
|
|
pOverride->AddRef();
|
|
pNamespace = pOverride;
|
|
}
|
|
else
|
|
{
|
|
// This will return an AddRef'd pointer
|
|
pNamespace = Cache.GetNamespace(pObject->GetNamespace(), scRet,
|
|
pUserName, pPassword ,pAuthority, pCtx,
|
|
LocatorGUID, fConnectFlags);
|
|
}
|
|
|
|
if(pNamespace == NULL)
|
|
{
|
|
int iMsg = (GotLineNumber(i)) ? ERROR_OPENING : ERROR_OPENING_NO_LINES;
|
|
PrintError(i, iMsg, scRet, pInfo);
|
|
return scRet;
|
|
}
|
|
|
|
// Ensures we release the namespace pointer when we go out of scope
|
|
CReleaseMe rmns( pNamespace );
|
|
|
|
// If there isnt a wbem object, try to get one. This will fail if this is a
|
|
// instance for which the class hasn't been saved just yet.
|
|
|
|
if(pObject->GetWbemObject() == NULL)
|
|
{
|
|
|
|
IWbemClassObject* pWbemObject = NULL;
|
|
hres = pObject->CreateWbemObject(pNamespace, &pWbemObject,pCtx);
|
|
if(hres != S_OK)
|
|
if(pObject->IsInstance())
|
|
continue;
|
|
else
|
|
{
|
|
PrintError(i,
|
|
(GotLineNumber(i)) ? ERROR_CREATING : ERROR_CREATING_NO_LINES,
|
|
hres, pInfo);
|
|
return WBEM_E_FAILED;
|
|
}
|
|
bMakingProgress = TRUE;
|
|
pObject->Reflate(Parser);
|
|
pObject->SetWbemObject(pWbemObject);
|
|
|
|
if(!pObject->ApplyToWbemObject(pWbemObject, pNamespace,pCtx))
|
|
{
|
|
hres = m_pDbg->hresError;
|
|
PrintError(i,
|
|
(GotLineNumber(i)) ? ERROR_CREATING : ERROR_CREATING_NO_LINES,
|
|
hres, pInfo);
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
}
|
|
|
|
// If there are no unresolved aliases, save it!
|
|
|
|
if(pObject->GetNumAliasedValues() == 0 ||
|
|
S_OK == pObject->ResolveAliasesInWbemObject(pObject->GetWbemObject(),
|
|
(CMofAliasCollection*)this))
|
|
{
|
|
|
|
// Save this into WinMgmt
|
|
// ==================
|
|
|
|
hres = pObject->StoreWbemObject(pObject->GetWbemObject(), lClassFlags, lInstanceFlags,
|
|
pNamespace, pCtx, pUserName, pPassword ,pAuthority);
|
|
if(hres != S_OK)
|
|
{
|
|
PrintError(i,
|
|
(GotLineNumber(i)) ? ERROR_STORING : ERROR_STORING_NO_LINES,
|
|
hres, pInfo);
|
|
return WBEM_E_FAILED;
|
|
}
|
|
pObject->FreeWbemObjectIfPossible();
|
|
pObject->Deflate(false);
|
|
pObject->SetDone();
|
|
bMakingProgress = TRUE;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// If there is one or more objects that cant be resolved, print and bail
|
|
|
|
for(i = 0; i < m_aObjects.GetSize(); i++)
|
|
{
|
|
CMObject* pObject = (CMObject*)m_aObjects[i];
|
|
if(pObject && !pObject->IsDone())
|
|
{
|
|
PrintError(i,
|
|
(GotLineNumber(i)) ? ERROR_RESOLVING : ERROR_RESOLVING_NO_LINES,
|
|
hres, pInfo);
|
|
return WBEM_E_FAILED;
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
HRESULT CMofData::RollBack(int nObjects)
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
BOOL CMofData::GotLineNumber(int nIndex)
|
|
{
|
|
CMObject* pObject = (CMObject*)m_aObjects[nIndex];
|
|
if(pObject == NULL || (pObject->GetFirstLine() == 0 && pObject->GetLastLine() == 0))
|
|
return FALSE;
|
|
else
|
|
return TRUE;
|
|
}
|
|
void CMofData::PrintError(int nIndex, long lMsgNum, HRESULT hres, WBEM_COMPILE_STATUS_INFO *pInfo)
|
|
{
|
|
CMObject* pObject = (CMObject*)m_aObjects[nIndex];
|
|
TCHAR szMsg[500];
|
|
bool bErrorFound = false;
|
|
|
|
if(pInfo)
|
|
pInfo->ObjectNum = nIndex+1;
|
|
if(!GotLineNumber(nIndex))
|
|
Trace(true, m_pDbg, lMsgNum, nIndex+1);
|
|
else
|
|
{
|
|
Trace(true, m_pDbg, lMsgNum, nIndex+1, pObject->GetFirstLine(),
|
|
pObject->GetLastLine(), pObject->GetFileName());
|
|
if(pInfo)
|
|
{
|
|
pInfo->FirstLine = pObject->GetFirstLine();
|
|
pInfo->LastLine = pObject->GetLastLine();
|
|
}
|
|
}
|
|
if(hres)
|
|
{
|
|
|
|
// A few error messages are retrived from the local resources. This is so that the name can be
|
|
// injected into the name.
|
|
|
|
if(hres == WBEM_E_NOT_FOUND || hres == WBEM_E_TYPE_MISMATCH || hres == WBEM_E_OVERRIDE_NOT_ALLOWED ||
|
|
hres == WBEM_E_PROPAGATED_QUALIFIER || hres == WBEM_E_VALUE_OUT_OF_RANGE)
|
|
{
|
|
Trace(true, m_pDbg, ERROR_FORMAT, hres);
|
|
Trace(true, m_pDbg, hres, m_pDbg->GetString());
|
|
bErrorFound = true;
|
|
}
|
|
else
|
|
{
|
|
// Get the error from the standard error facility
|
|
|
|
IWbemStatusCodeText * pStatus = NULL;
|
|
SCODE sc = CoCreateInstance(CLSID_WbemStatusCodeText, 0, CLSCTX_INPROC_SERVER,
|
|
IID_IWbemStatusCodeText, (LPVOID *) &pStatus);
|
|
|
|
if(sc == S_OK)
|
|
{
|
|
BSTR bstrError = 0;
|
|
BSTR bstrFacility = 0;
|
|
sc = pStatus->GetErrorCodeText(hres, 0, 0, &bstrError);
|
|
if(sc == S_OK)
|
|
{
|
|
sc = pStatus->GetFacilityCodeText(hres, 0, 0, &bstrFacility);
|
|
if(sc == S_OK)
|
|
{
|
|
IntString is(ERROR_FORMAT_LONG);
|
|
StringCchPrintfW(szMsg, 500, is, hres, bstrFacility, bstrError);
|
|
bErrorFound = true;
|
|
SysFreeString(bstrFacility);
|
|
}
|
|
SysFreeString(bstrError);
|
|
}
|
|
pStatus->Release();
|
|
}
|
|
|
|
// if all else fails, just use the generic error message
|
|
|
|
if(!bErrorFound)
|
|
{
|
|
IntString is(ERROR_FORMATEX);
|
|
StringCchPrintfW(szMsg, 500 ,is, hres);
|
|
}
|
|
|
|
// Print the error message
|
|
|
|
if(m_pDbg->m_bPrint)
|
|
printf("%S", szMsg);
|
|
ERRORTRACE((LOG_MOFCOMP,"%S", szMsg));
|
|
|
|
} // ELSE get error from standard facility
|
|
|
|
} // IF hres
|
|
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// GetFileNames
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// The amendment local, the localized and neutral file names are passed
|
|
// in using the BMOF string. These values are separated by commas and
|
|
// a single letter which indicates what follows. An example string
|
|
// would be ",aMS_409,nNEUTRAL.MOF,lLocalMof" Notice that the amendment
|
|
// substring starts with an 'a', the neutral starts with 'n', and the
|
|
// locale starts with 'l'.
|
|
//
|
|
// While the neutral name is required, the locale version isnt. If not
|
|
// supplied, it will be created. The two character inputs are ASSUMED to
|
|
// point to preallocated buffers of MAX_PATH size!
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT GetFileNames(TCHAR * pcNeutral, TCHAR * pcLocale, LPWSTR pwszBMOF)
|
|
{
|
|
WCHAR * pNeutral=NULL;
|
|
WCHAR * pLocale=NULL;
|
|
|
|
if(pwszBMOF == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// make a copy of the string
|
|
|
|
DWORD dwLen = wcslen(pwszBMOF)+1;
|
|
WCHAR *pTemp = new WCHAR[dwLen];
|
|
if(pTemp == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
CDeleteMe<WCHAR> dm1(pTemp);
|
|
StringCchCopyW(pTemp, dwLen, pwszBMOF);
|
|
|
|
// use wcstok to do a seach
|
|
|
|
WCHAR * token = wcstok( pTemp, L"," );
|
|
while( token != NULL )
|
|
{
|
|
if(token[0] == L'n')
|
|
{
|
|
pNeutral = token+1;
|
|
CopyOrConvert(pcNeutral, pNeutral, MAX_PATH);
|
|
}
|
|
else if(token[0] == L'l')
|
|
{
|
|
pLocale = token+1;
|
|
CopyOrConvert(pcLocale, pLocale, MAX_PATH);
|
|
}
|
|
token = wcstok( NULL, L"," );
|
|
}
|
|
|
|
// If the neutral name was not specified, that is an error
|
|
|
|
if(pNeutral == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// If the local name was not specified, create it and make it the
|
|
// same as the neutral name except for changing the mfl extension
|
|
|
|
if(pLocale == NULL)
|
|
{
|
|
TCHAR * pFr = pcNeutral,* pTo = pcLocale;
|
|
for(; *pFr && *pFr != '.'; pTo++, pFr++)
|
|
*pTo = *pFr;
|
|
*pTo=0;
|
|
StringCchCatW(pcLocale, MAX_PATH, TEXT(".mfl"));
|
|
}
|
|
|
|
// make sure that the locale and neutral names are not the same
|
|
|
|
if(!lstrcmpi(pcLocale, pcNeutral))
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// GetLocale
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Converts the amendment string to a local number. An example string
|
|
// would be "MS_409"
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT GetLocale(long * plLocale, WCHAR * pwszAmendment)
|
|
{
|
|
if(pwszAmendment == NULL || wcslen(pwszAmendment) != 6)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
*plLocale = 0;
|
|
swscanf(pwszAmendment+3,L"%x", plLocale);
|
|
return (*plLocale != 0) ? S_OK : WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// RecursiveSetAmended
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Sets the boolean indicating that an object is to be amended and all of
|
|
// its parents
|
|
//
|
|
//***************************************************************************
|
|
|
|
void CMofData::RecursiveSetAmended(CMObject * pObj)
|
|
{
|
|
|
|
// If the object is already amended, then its parents are already set.
|
|
// In that case, our job is done here!
|
|
|
|
if(pObj->IsAmended())
|
|
return;
|
|
|
|
// If the object hasnt been set yet, set it and also set its parents
|
|
|
|
pObj->SetAmended(true);
|
|
|
|
// Look for the parent and do the same
|
|
|
|
if(pObj->IsInstance() || pObj->IsDelete())
|
|
return; // run away now if this is a instance!
|
|
|
|
CMoClass * pClass = (CMoClass *)pObj;
|
|
const WCHAR *pClassName = pClass->GetParentName();
|
|
if(pClassName == NULL)
|
|
return;
|
|
|
|
// Find the parent and recursively set it!
|
|
|
|
for(int i = 0; i< m_aObjects.GetSize(); i++)
|
|
{
|
|
CMObject* pObject = (CMObject*)m_aObjects[i];
|
|
if(pObject && pObject->GetClassName() &&
|
|
!wbem_wcsicmp(pClassName, pObject->GetClassName()))
|
|
{
|
|
RecursiveSetAmended(pObject);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CMofData::Split
|
|
//
|
|
// DESCRIPTION:
|
|
//
|
|
// Creates a neutral and locale specific mof.
|
|
//
|
|
// Parameters:
|
|
// pwszBMOF See the GetFileNames() comments
|
|
// pInfo usual error info
|
|
// bUnicode if true, then the orignal file was unicode and so the
|
|
// new files will also be unicode
|
|
// bAutoRecovery Need to add this pragma if true
|
|
// pwszAmendment See the GetLocale() comments
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CMofData::Split(CMofParser & Parser, LPWSTR pwszBMOF, WBEM_COMPILE_STATUS_INFO *pInfo, BOOL bUnicode,
|
|
BOOL bAutoRecovery, LPWSTR pwszAmendment)
|
|
{
|
|
int i;
|
|
TCHAR cNeutral[MAX_PATH];
|
|
TCHAR cLocale[MAX_PATH];
|
|
|
|
// Determine the file names and locale
|
|
|
|
HRESULT hRes = GetFileNames(cNeutral, cLocale, pwszBMOF);
|
|
if(hRes != S_OK)
|
|
return S_OK;
|
|
|
|
long lLocale;
|
|
hRes = GetLocale(&lLocale, pwszAmendment);
|
|
if(hRes != S_OK)
|
|
return S_OK;
|
|
|
|
// Create the output objects
|
|
|
|
COutput Neutral(cNeutral, NEUTRAL, bUnicode, bAutoRecovery, lLocale);
|
|
COutput Local(cLocale, LOCALIZED, bUnicode, bAutoRecovery, lLocale);
|
|
if(!Neutral.IsOK() || !Local.IsOK())
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// Start by determining what is amended
|
|
|
|
for(i = 0; i< m_aObjects.GetSize(); i++)
|
|
{
|
|
CMObject* pObject = (CMObject*)m_aObjects[i];
|
|
pObject->Reflate(Parser);
|
|
if(pObject->CheckIfAmended())
|
|
{
|
|
RecursiveSetAmended(pObject);
|
|
}
|
|
}
|
|
|
|
|
|
// Create the neutral output and the localized output.
|
|
// These two loops could have been combined, but are
|
|
// separate for debugging purposes
|
|
|
|
for(i = 0; i< m_aObjects.GetSize(); i++)
|
|
{
|
|
CMObject* pObject = (CMObject*)m_aObjects[i];
|
|
pObject->Split(Neutral);
|
|
}
|
|
for(i = 0; i< m_aObjects.GetSize(); i++)
|
|
{
|
|
CMObject* pObject = (CMObject*)m_aObjects[i];
|
|
pObject->Split(Local);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|