Leaked source code of windows server 2003
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

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. MOFDATA.CPP
  5. Abstract:
  6. Entry points for the WBEM MOF compiler.
  7. History:
  8. a-davj 12-April-97 Added WMI support.
  9. --*/
  10. #include "precomp.h"
  11. #include <cominit.h>
  12. #include "mofout.h"
  13. #include "mofdata.h"
  14. #include "typehelp.h"
  15. #include "bmof.h"
  16. #include "cbmofout.h"
  17. #include "trace.h"
  18. #include "strings.h"
  19. #include "arrtempl.h"
  20. #include <genutils.h>
  21. #define TEMP_BUF 128
  22. WCHAR * Macro_CloneStr(LPCWSTR pFr)
  23. {
  24. if(pFr == NULL)
  25. return NULL;
  26. DWORD dwLen = wcslen(pFr) + 1;
  27. WCHAR * pTo = new WCHAR[dwLen];
  28. if(pTo)
  29. {
  30. StringCchCopyW(pTo, dwLen, pFr);
  31. return pTo;
  32. }
  33. return NULL;
  34. }
  35. HRESULT MofdSetInterfaceSecurity(IUnknown * pInterface, LPWSTR pAuthority, LPWSTR pUser,
  36. LPWSTR pPassword)
  37. {
  38. SCODE sc;
  39. BOOL bUseAuthInfo = FALSE;
  40. DWORD dwQueryAuthnLevel, dwQueryImpLevel, dwQueryCapabilities;
  41. DWORD dwAuthnSvc = RPC_C_AUTHN_GSS_NEGOTIATE;
  42. WCHAR * pwCSPBPrincipal = NULL;
  43. HRESULT hr = CoQueryProxyBlanket(
  44. pInterface, //Location for the proxy to query
  45. &dwAuthnSvc, //Location for the current authentication service
  46. NULL, //Location for the current authorization service
  47. NULL, //Location for the current principal name
  48. &dwQueryAuthnLevel, //Location for the current authentication level
  49. &dwQueryImpLevel, //Location for the current impersonation level
  50. NULL,
  51. &dwQueryCapabilities //Location for flags indicating further capabilities of the proxy
  52. );
  53. if(SUCCEEDED(hr) && dwAuthnSvc != RPC_C_AUTHN_WINNT)
  54. {
  55. pwCSPBPrincipal = COLE_DEFAULT_PRINCIPAL;
  56. }
  57. else
  58. {
  59. dwAuthnSvc = RPC_C_AUTHN_WINNT;
  60. pwCSPBPrincipal = NULL;
  61. }
  62. // If we are doing trivial case, just pass in a null authenication structure which is used
  63. // if the current logged in user's credentials are OK.
  64. if((pAuthority == NULL || wcslen(pAuthority) < 1) &&
  65. (pUser == NULL || wcslen(pUser) < 1) &&
  66. (pPassword == NULL || wcslen(pPassword) < 1))
  67. {
  68. return WbemSetProxyBlanket(pInterface, dwAuthnSvc, RPC_C_AUTHZ_NONE,
  69. pwCSPBPrincipal,
  70. RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE,
  71. NULL,
  72. EOAC_STATIC_CLOAKING);
  73. }
  74. // If user, or Authority was passed in, the we need to create an authority argument for the login
  75. COAUTHIDENTITY authident;
  76. BSTR AuthArg = NULL, UserArg = NULL, PrincipalArg = NULL;
  77. sc = DetermineLoginTypeEx(AuthArg, UserArg, PrincipalArg, pAuthority, pUser);
  78. if(sc != S_OK)
  79. return sc;
  80. CSysFreeMe fm1(UserArg), fm2(AuthArg), fm3(PrincipalArg);
  81. memset((void *)&authident,0,sizeof(COAUTHIDENTITY));
  82. if(UserArg)
  83. {
  84. authident.UserLength = wcslen(UserArg);
  85. authident.User = (LPWSTR)UserArg;
  86. bUseAuthInfo = TRUE;
  87. }
  88. if(AuthArg)
  89. {
  90. authident.DomainLength = wcslen(AuthArg);
  91. authident.Domain = (LPWSTR)AuthArg;
  92. bUseAuthInfo = TRUE;
  93. }
  94. if(pPassword)
  95. {
  96. authident.PasswordLength = wcslen(pPassword);
  97. authident.Password = (LPWSTR)pPassword;
  98. bUseAuthInfo = TRUE;
  99. }
  100. authident.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  101. sc = WbemSetProxyBlanket(pInterface,
  102. (PrincipalArg) ? RPC_C_AUTHN_GSS_KERBEROS : dwAuthnSvc,
  103. RPC_C_AUTHZ_NONE,
  104. (PrincipalArg) ? PrincipalArg : pwCSPBPrincipal,
  105. RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE,
  106. (bUseAuthInfo) ? &authident : NULL,
  107. (bUseAuthInfo) ? 0 : EOAC_STATIC_CLOAKING
  108. );
  109. return sc;
  110. }
  111. CNamespaceCache::CNamespaceRecord::CNamespaceRecord(
  112. COPY LPCWSTR wszName,
  113. ADDREF IWbemServices* pNamespace)
  114. {
  115. m_wszName = Macro_CloneStr(wszName);
  116. m_pNamespace = pNamespace;
  117. m_pNamespace->AddRef();
  118. }
  119. CNamespaceCache::CNamespaceRecord::~CNamespaceRecord()
  120. {
  121. delete [] m_wszName;
  122. if(m_pNamespace) m_pNamespace->Release();
  123. }
  124. //*****************************************************************************
  125. CNamespaceCache::CNamespaceCache(ADDREF IWbemLocator* pLocator)
  126. {
  127. if(pLocator)
  128. pLocator->AddRef();
  129. m_pLocator = pLocator;
  130. }
  131. CNamespaceCache::~CNamespaceCache()
  132. {
  133. if(m_pLocator) m_pLocator->Release();
  134. for(int i = 0; i < m_aRecords.GetSize(); i++)
  135. {
  136. delete (CNamespaceRecord*)m_aRecords[i];
  137. }
  138. }
  139. RELEASE_ME IWbemServices* CNamespaceCache::GetNamespace(COPY LPCWSTR wszName, SCODE & scRet,
  140. WCHAR * pUserName, WCHAR * pPassword , WCHAR * pAuthority,
  141. IWbemContext * pCtx, GUID LocatorGUID, LONG fConnectFlags)
  142. {
  143. // Check if it is the cache
  144. // ========================
  145. scRet = S_OK;
  146. for(int i = 0; i < m_aRecords.GetSize(); i++)
  147. {
  148. CNamespaceRecord* pRecord = (CNamespaceRecord*)m_aRecords[i];
  149. if(!wbem_wcsicmp(pRecord->m_wszName, wszName))
  150. {
  151. // Found it
  152. // ========
  153. pRecord->m_pNamespace->AddRef();
  154. return pRecord->m_pNamespace;
  155. }
  156. }
  157. // Not found --- open it
  158. // =====================
  159. IWbemServices* pNamespace;
  160. if(wszName == NULL)
  161. return NULL;
  162. LPOLESTR pwszName;
  163. pwszName = SysAllocString(wszName);
  164. if(pwszName == NULL)
  165. return NULL;
  166. CSysFreeMe fm0(pwszName);
  167. LPOLESTR bstrPassword = NULL;
  168. LPOLESTR bstrUserName = NULL;
  169. LPOLESTR bstrAuthority = NULL;
  170. if(pUserName && wcslen(pUserName) > 0)
  171. {
  172. bstrUserName = SysAllocString(pUserName);
  173. if(bstrUserName == NULL)
  174. return NULL;
  175. }
  176. CSysFreeMe fm1(bstrUserName);
  177. if(pPassword)
  178. {
  179. bstrPassword = SysAllocString(pPassword);
  180. if(bstrPassword == NULL)
  181. return NULL;
  182. }
  183. CSysFreeMe fm2(bstrPassword);
  184. if(pAuthority && wcslen(pAuthority) > 0)
  185. {
  186. bstrAuthority = SysAllocString(pAuthority);
  187. if(bstrAuthority == NULL)
  188. return NULL;
  189. }
  190. CSysFreeMe fm3(bstrAuthority);
  191. // Determine if the connection is to the regular locator, or to one of the special inproc ones
  192. // used for autocompile. If it is inproc, then remote connections are not valid.
  193. bool bInProc = false;
  194. if(LocatorGUID != CLSID_WbemLocator)
  195. bInProc = true;
  196. if(bInProc)
  197. {
  198. WCHAR * pMachine = ExtractMachineName(pwszName);
  199. if(pMachine)
  200. {
  201. BOOL bLocal = bAreWeLocal(pMachine);
  202. delete pMachine;
  203. if(!bLocal)
  204. {
  205. scRet = WBEM_E_INVALID_NAMESPACE;
  206. ERRORTRACE((LOG_MOFCOMP,"Error, tried to do a remote connect during autocomp\n"));
  207. }
  208. }
  209. }
  210. // Connect up to namespace. //TODO, PASS AUTHORITY IN THE CONTEXT
  211. if(scRet == S_OK)
  212. scRet = m_pLocator->ConnectServer((LPWSTR)pwszName,
  213. bstrUserName, bstrPassword,
  214. NULL, fConnectFlags,
  215. pAuthority, pCtx, &pNamespace);
  216. if(scRet == S_OK && !bInProc)
  217. {
  218. // Set the impersonation level up so that puts to providers can be done
  219. DWORD dwAuthLevel, dwImpLevel;
  220. SCODE sc = GetAuthImp( pNamespace, &dwAuthLevel, &dwImpLevel);
  221. if(sc != S_OK || dwAuthLevel != RPC_C_AUTHN_LEVEL_NONE)
  222. sc = MofdSetInterfaceSecurity(pNamespace, bstrAuthority, bstrUserName, bstrPassword);
  223. }
  224. if(FAILED(scRet)) return NULL;
  225. // Add it to the cache
  226. // ===================
  227. CNamespaceRecord * pNew = new CNamespaceRecord(wszName, pNamespace);
  228. if(pNew)
  229. m_aRecords.Add(pNew); // AddRef'ed
  230. return pNamespace;
  231. }
  232. //*****************************************************************************
  233. //*****************************************************************************
  234. void CMofData::SetQualifierDefault(ACQUIRE CMoQualifier* pDefault)
  235. {
  236. // Search for this qualifier in the defaults list
  237. // ==============================================
  238. for(int i = 0; i < m_aQualDefaults.GetSize(); i++)
  239. {
  240. CMoQualifier* pOrig = (CMoQualifier*)m_aQualDefaults[i];
  241. if(wbem_wcsicmp(pOrig->GetName(), pDefault->GetName()) == 0)
  242. {
  243. // Found it. Replace
  244. // =================
  245. delete pOrig;
  246. m_aQualDefaults[i] = (void*)pDefault;
  247. return;
  248. }
  249. }
  250. // Not found. Add
  251. // ==============
  252. m_aQualDefaults.Add((void*)pDefault);
  253. }
  254. HRESULT CMofData::SetDefaultFlavor(MODIFY CMoQualifier& Qual, bool bTopLevel, QUALSCOPE qs, PARSESTATE ps)
  255. {
  256. HRESULT hr;
  257. // Search for this qualifier in the defaults list
  258. // ==============================================
  259. for(int i = 0; i < m_aQualDefaults.GetSize(); i++)
  260. {
  261. CMoQualifier* pOrig = (CMoQualifier*)m_aQualDefaults[i];
  262. if(wbem_wcsicmp(pOrig->GetName(), Qual.GetName()) == 0)
  263. {
  264. // Found it. SetFlavor
  265. // ===================
  266. if(pOrig->IsCimDefault())
  267. {
  268. // dont bother if the parse state is the initial scan
  269. if(ps == INITIAL)
  270. continue;
  271. if(Qual.IsUsingDefaultValue())
  272. {
  273. // see if the scope matches what we have here
  274. DWORD dwScope = pOrig->GetScope();
  275. bool bInScope = false;
  276. if((dwScope & SCOPE_CLASS) || (dwScope & SCOPE_INSTANCE))
  277. if(qs == CLASSINST_SCOPE)
  278. bInScope = true;
  279. if(dwScope & SCOPE_PROPERTY)
  280. if(qs == PROPMETH_SCOPE)
  281. bInScope = true;
  282. if(bInScope)
  283. {
  284. CMoValue& Src = pOrig->AccessValue();
  285. CMoValue& Dest = Qual.AccessValue();
  286. Dest.SetType(Src.GetType());
  287. VARIANT & varSrc = Src.AccessVariant();
  288. VARIANT & varDest = Dest.AccessVariant();
  289. hr = VariantCopy(&varDest, &varSrc);
  290. if(FAILED(hr))
  291. return hr;
  292. Qual.SetFlavor(pOrig->GetFlavor());
  293. Qual.SetAmended(pOrig->IsAmended());
  294. }
  295. }
  296. }
  297. else
  298. {
  299. Qual.SetFlavor(pOrig->GetFlavor());
  300. Qual.SetAmended(pOrig->IsAmended());
  301. }
  302. return S_OK;
  303. }
  304. }
  305. return S_OK;
  306. }
  307. BOOL CMofData::IsAliasInUse(READ_ONLY LPWSTR wszAlias)
  308. {
  309. for(int i = 0; i < m_aObjects.GetSize(); i++)
  310. {
  311. CMObject* pObject = (CMObject*)m_aObjects[i];
  312. if(pObject->GetAlias() && !wbem_wcsicmp(pObject->GetAlias(), wszAlias))
  313. {
  314. return TRUE;
  315. }
  316. }
  317. return FALSE;
  318. }
  319. BOOL IsGuid(LPWSTR pTest)
  320. {
  321. int i;
  322. int iSoFar = 0;
  323. #define HEXCHECK(n) \
  324. for (i = 0; i < n; i++) \
  325. if (!iswxdigit(*pTest++)) \
  326. return FALSE;
  327. #define HYPHENCHECK() \
  328. if (*pTest++ != L'-') \
  329. return FALSE;
  330. if(*pTest++ != L'{')
  331. return FALSE;
  332. HEXCHECK(8);
  333. HYPHENCHECK();
  334. HEXCHECK(4);
  335. HYPHENCHECK();
  336. HEXCHECK(4);
  337. HYPHENCHECK();
  338. HEXCHECK(4);
  339. HYPHENCHECK();
  340. HEXCHECK(12);
  341. if(*pTest++ != L'}')
  342. return FALSE;
  343. return TRUE;
  344. }
  345. INTERNAL LPCWSTR CMofData::FindAliasee(READ_ONLY LPWSTR wszAlias)
  346. {
  347. for(int i = 0; i < m_aObjects.GetSize(); i++)
  348. {
  349. CMObject* pObject = (CMObject*)m_aObjects[i];
  350. if(pObject->GetAlias() && !wbem_wcsicmp(pObject->GetAlias(), wszAlias))
  351. {
  352. IWbemClassObject * pTemp;
  353. pTemp = pObject->GetWbemObject();
  354. // check for unresolved aliases in keys
  355. if(pTemp && pObject->IsDone() == FALSE)
  356. {
  357. SCODE sc = pTemp->BeginEnumeration(WBEM_FLAG_KEYS_ONLY | WBEM_FLAG_REFS_ONLY);
  358. if(sc != S_OK)
  359. return NULL;
  360. VARIANT var;
  361. VariantInit(&var);
  362. while ((sc = pTemp->Next(0, NULL, &var, NULL, NULL)) == S_OK)
  363. {
  364. if(var.vt == VT_BSTR && IsGuid(var.bstrVal))
  365. {
  366. VariantClear(&var);
  367. return NULL;
  368. }
  369. VariantClear(&var);
  370. }
  371. }
  372. return pObject->GetFullPath();
  373. }
  374. }
  375. return NULL;
  376. }
  377. HRESULT CMofData::Store(CMofParser & Parser, OLE_MODIFY IWbemLocator* pLocator,IWbemServices *pOverride,BOOL bRollbackable,
  378. WCHAR * pUserName, WCHAR * pPassword, WCHAR * pAuthority,
  379. IWbemContext * pCtx, GUID LocatorGUID, WBEM_COMPILE_STATUS_INFO *pInfo,
  380. BOOL bClassOwnerUpdate,
  381. BOOL bInstanceOwnerUpdate,
  382. LONG fConnectFlags)
  383. {
  384. HRESULT hres = WBEM_E_FAILED;
  385. int i;
  386. CNamespaceCache Cache(pLocator);
  387. BOOL bMakingProgress = TRUE;
  388. long lClassFlags = 0;
  389. long lInstanceFlags = 0;
  390. while(bMakingProgress)
  391. {
  392. bMakingProgress = FALSE;
  393. for(i = 0; i< m_aObjects.GetSize(); i++)
  394. {
  395. CMObject* pObject = (CMObject*)m_aObjects[i];
  396. if(pObject->IsDone())
  397. continue;
  398. lClassFlags = pObject->GetClassFlags();
  399. lInstanceFlags = pObject->GetInstanceFlags();
  400. if(bClassOwnerUpdate)
  401. {
  402. lClassFlags |= WBEM_FLAG_OWNER_UPDATE;
  403. }
  404. if(bInstanceOwnerUpdate)
  405. {
  406. lInstanceFlags |= WBEM_FLAG_OWNER_UPDATE;
  407. }
  408. // Get a namespace pointer for this object.
  409. SCODE scRet;
  410. IWbemServices* pNamespace = NULL;
  411. if(pOverride && !wbem_wcsicmp(L"root\\default", pObject->GetNamespace()))
  412. {
  413. // AddRef() the namespace pointer, since we will be Releasing
  414. // it below
  415. pOverride->AddRef();
  416. pNamespace = pOverride;
  417. }
  418. else
  419. {
  420. // This will return an AddRef'd pointer
  421. pNamespace = Cache.GetNamespace(pObject->GetNamespace(), scRet,
  422. pUserName, pPassword ,pAuthority, pCtx,
  423. LocatorGUID, fConnectFlags);
  424. }
  425. if(pNamespace == NULL)
  426. {
  427. int iMsg = (GotLineNumber(i)) ? ERROR_OPENING : ERROR_OPENING_NO_LINES;
  428. PrintError(i, iMsg, scRet, pInfo);
  429. return scRet;
  430. }
  431. // Ensures we release the namespace pointer when we go out of scope
  432. CReleaseMe rmns( pNamespace );
  433. // If there isnt a wbem object, try to get one. This will fail if this is a
  434. // instance for which the class hasn't been saved just yet.
  435. if(pObject->GetWbemObject() == NULL)
  436. {
  437. IWbemClassObject* pWbemObject = NULL;
  438. hres = pObject->CreateWbemObject(pNamespace, &pWbemObject,pCtx);
  439. if(hres != S_OK)
  440. if(pObject->IsInstance())
  441. continue;
  442. else
  443. {
  444. PrintError(i,
  445. (GotLineNumber(i)) ? ERROR_CREATING : ERROR_CREATING_NO_LINES,
  446. hres, pInfo);
  447. return WBEM_E_FAILED;
  448. }
  449. bMakingProgress = TRUE;
  450. pObject->Reflate(Parser);
  451. pObject->SetWbemObject(pWbemObject);
  452. if(!pObject->ApplyToWbemObject(pWbemObject, pNamespace,pCtx))
  453. {
  454. hres = m_pDbg->hresError;
  455. PrintError(i,
  456. (GotLineNumber(i)) ? ERROR_CREATING : ERROR_CREATING_NO_LINES,
  457. hres, pInfo);
  458. return WBEM_E_FAILED;
  459. }
  460. }
  461. // If there are no unresolved aliases, save it!
  462. if(pObject->GetNumAliasedValues() == 0 ||
  463. S_OK == pObject->ResolveAliasesInWbemObject(pObject->GetWbemObject(),
  464. (CMofAliasCollection*)this))
  465. {
  466. // Save this into WinMgmt
  467. // ==================
  468. hres = pObject->StoreWbemObject(pObject->GetWbemObject(), lClassFlags, lInstanceFlags,
  469. pNamespace, pCtx, pUserName, pPassword ,pAuthority);
  470. if(hres != S_OK)
  471. {
  472. PrintError(i,
  473. (GotLineNumber(i)) ? ERROR_STORING : ERROR_STORING_NO_LINES,
  474. hres, pInfo);
  475. return WBEM_E_FAILED;
  476. }
  477. pObject->FreeWbemObjectIfPossible();
  478. pObject->Deflate(false);
  479. pObject->SetDone();
  480. bMakingProgress = TRUE;
  481. }
  482. }
  483. }
  484. // If there is one or more objects that cant be resolved, print and bail
  485. for(i = 0; i < m_aObjects.GetSize(); i++)
  486. {
  487. CMObject* pObject = (CMObject*)m_aObjects[i];
  488. if(pObject && !pObject->IsDone())
  489. {
  490. PrintError(i,
  491. (GotLineNumber(i)) ? ERROR_RESOLVING : ERROR_RESOLVING_NO_LINES,
  492. hres, pInfo);
  493. return WBEM_E_FAILED;
  494. }
  495. }
  496. return S_OK;
  497. }
  498. HRESULT CMofData::RollBack(int nObjects)
  499. {
  500. return WBEM_E_FAILED;
  501. }
  502. BOOL CMofData::GotLineNumber(int nIndex)
  503. {
  504. CMObject* pObject = (CMObject*)m_aObjects[nIndex];
  505. if(pObject == NULL || (pObject->GetFirstLine() == 0 && pObject->GetLastLine() == 0))
  506. return FALSE;
  507. else
  508. return TRUE;
  509. }
  510. void CMofData::PrintError(int nIndex, long lMsgNum, HRESULT hres, WBEM_COMPILE_STATUS_INFO *pInfo)
  511. {
  512. CMObject* pObject = (CMObject*)m_aObjects[nIndex];
  513. TCHAR szMsg[500];
  514. bool bErrorFound = false;
  515. if(pInfo)
  516. pInfo->ObjectNum = nIndex+1;
  517. if(!GotLineNumber(nIndex))
  518. Trace(true, m_pDbg, lMsgNum, nIndex+1);
  519. else
  520. {
  521. Trace(true, m_pDbg, lMsgNum, nIndex+1, pObject->GetFirstLine(),
  522. pObject->GetLastLine(), pObject->GetFileName());
  523. if(pInfo)
  524. {
  525. pInfo->FirstLine = pObject->GetFirstLine();
  526. pInfo->LastLine = pObject->GetLastLine();
  527. }
  528. }
  529. if(hres)
  530. {
  531. // A few error messages are retrived from the local resources. This is so that the name can be
  532. // injected into the name.
  533. if(hres == WBEM_E_NOT_FOUND || hres == WBEM_E_TYPE_MISMATCH || hres == WBEM_E_OVERRIDE_NOT_ALLOWED ||
  534. hres == WBEM_E_PROPAGATED_QUALIFIER || hres == WBEM_E_VALUE_OUT_OF_RANGE)
  535. {
  536. Trace(true, m_pDbg, ERROR_FORMAT, hres);
  537. Trace(true, m_pDbg, hres, m_pDbg->GetString());
  538. bErrorFound = true;
  539. }
  540. else
  541. {
  542. // Get the error from the standard error facility
  543. IWbemStatusCodeText * pStatus = NULL;
  544. SCODE sc = CoCreateInstance(CLSID_WbemStatusCodeText, 0, CLSCTX_INPROC_SERVER,
  545. IID_IWbemStatusCodeText, (LPVOID *) &pStatus);
  546. if(sc == S_OK)
  547. {
  548. BSTR bstrError = 0;
  549. BSTR bstrFacility = 0;
  550. sc = pStatus->GetErrorCodeText(hres, 0, 0, &bstrError);
  551. if(sc == S_OK)
  552. {
  553. sc = pStatus->GetFacilityCodeText(hres, 0, 0, &bstrFacility);
  554. if(sc == S_OK)
  555. {
  556. IntString is(ERROR_FORMAT_LONG);
  557. StringCchPrintfW(szMsg, 500, is, hres, bstrFacility, bstrError);
  558. bErrorFound = true;
  559. SysFreeString(bstrFacility);
  560. }
  561. SysFreeString(bstrError);
  562. }
  563. pStatus->Release();
  564. }
  565. // if all else fails, just use the generic error message
  566. if(!bErrorFound)
  567. {
  568. IntString is(ERROR_FORMATEX);
  569. StringCchPrintfW(szMsg, 500 ,is, hres);
  570. }
  571. // Print the error message
  572. if(m_pDbg->m_bPrint)
  573. printf("%S", szMsg);
  574. ERRORTRACE((LOG_MOFCOMP,"%S", szMsg));
  575. } // ELSE get error from standard facility
  576. } // IF hres
  577. }
  578. //***************************************************************************
  579. //
  580. // GetFileNames
  581. //
  582. // DESCRIPTION:
  583. //
  584. // The amendment local, the localized and neutral file names are passed
  585. // in using the BMOF string. These values are separated by commas and
  586. // a single letter which indicates what follows. An example string
  587. // would be ",aMS_409,nNEUTRAL.MOF,lLocalMof" Notice that the amendment
  588. // substring starts with an 'a', the neutral starts with 'n', and the
  589. // locale starts with 'l'.
  590. //
  591. // While the neutral name is required, the locale version isnt. If not
  592. // supplied, it will be created. The two character inputs are ASSUMED to
  593. // point to preallocated buffers of MAX_PATH size!
  594. //
  595. //***************************************************************************
  596. HRESULT GetFileNames(TCHAR * pcNeutral, TCHAR * pcLocale, LPWSTR pwszBMOF)
  597. {
  598. WCHAR * pNeutral=NULL;
  599. WCHAR * pLocale=NULL;
  600. if(pwszBMOF == NULL)
  601. return WBEM_E_INVALID_PARAMETER;
  602. // make a copy of the string
  603. DWORD dwLen = wcslen(pwszBMOF)+1;
  604. WCHAR *pTemp = new WCHAR[dwLen];
  605. if(pTemp == NULL)
  606. return WBEM_E_OUT_OF_MEMORY;
  607. CDeleteMe<WCHAR> dm1(pTemp);
  608. StringCchCopyW(pTemp, dwLen, pwszBMOF);
  609. // use wcstok to do a seach
  610. WCHAR * token = wcstok( pTemp, L"," );
  611. while( token != NULL )
  612. {
  613. if(token[0] == L'n')
  614. {
  615. pNeutral = token+1;
  616. CopyOrConvert(pcNeutral, pNeutral, MAX_PATH);
  617. }
  618. else if(token[0] == L'l')
  619. {
  620. pLocale = token+1;
  621. CopyOrConvert(pcLocale, pLocale, MAX_PATH);
  622. }
  623. token = wcstok( NULL, L"," );
  624. }
  625. // If the neutral name was not specified, that is an error
  626. if(pNeutral == NULL)
  627. return WBEM_E_INVALID_PARAMETER;
  628. // If the local name was not specified, create it and make it the
  629. // same as the neutral name except for changing the mfl extension
  630. if(pLocale == NULL)
  631. {
  632. TCHAR * pFr = pcNeutral,* pTo = pcLocale;
  633. for(; *pFr && *pFr != '.'; pTo++, pFr++)
  634. *pTo = *pFr;
  635. *pTo=0;
  636. StringCchCatW(pcLocale, MAX_PATH, TEXT(".mfl"));
  637. }
  638. // make sure that the locale and neutral names are not the same
  639. if(!lstrcmpi(pcLocale, pcNeutral))
  640. return WBEM_E_INVALID_PARAMETER;
  641. return S_OK;
  642. }
  643. //***************************************************************************
  644. //
  645. // GetLocale
  646. //
  647. // DESCRIPTION:
  648. //
  649. // Converts the amendment string to a local number. An example string
  650. // would be "MS_409"
  651. //
  652. //***************************************************************************
  653. HRESULT GetLocale(long * plLocale, WCHAR * pwszAmendment)
  654. {
  655. if(pwszAmendment == NULL || wcslen(pwszAmendment) != 6)
  656. return WBEM_E_INVALID_PARAMETER;
  657. *plLocale = 0;
  658. swscanf(pwszAmendment+3,L"%x", plLocale);
  659. return (*plLocale != 0) ? S_OK : WBEM_E_INVALID_PARAMETER;
  660. }
  661. //***************************************************************************
  662. //
  663. // RecursiveSetAmended
  664. //
  665. // DESCRIPTION:
  666. //
  667. // Sets the boolean indicating that an object is to be amended and all of
  668. // its parents
  669. //
  670. //***************************************************************************
  671. void CMofData::RecursiveSetAmended(CMObject * pObj)
  672. {
  673. // If the object is already amended, then its parents are already set.
  674. // In that case, our job is done here!
  675. if(pObj->IsAmended())
  676. return;
  677. // If the object hasnt been set yet, set it and also set its parents
  678. pObj->SetAmended(true);
  679. // Look for the parent and do the same
  680. if(pObj->IsInstance() || pObj->IsDelete())
  681. return; // run away now if this is a instance!
  682. CMoClass * pClass = (CMoClass *)pObj;
  683. const WCHAR *pClassName = pClass->GetParentName();
  684. if(pClassName == NULL)
  685. return;
  686. // Find the parent and recursively set it!
  687. for(int i = 0; i< m_aObjects.GetSize(); i++)
  688. {
  689. CMObject* pObject = (CMObject*)m_aObjects[i];
  690. if(pObject && pObject->GetClassName() &&
  691. !wbem_wcsicmp(pClassName, pObject->GetClassName()))
  692. {
  693. RecursiveSetAmended(pObject);
  694. }
  695. }
  696. }
  697. //***************************************************************************
  698. //
  699. // CMofData::Split
  700. //
  701. // DESCRIPTION:
  702. //
  703. // Creates a neutral and locale specific mof.
  704. //
  705. // Parameters:
  706. // pwszBMOF See the GetFileNames() comments
  707. // pInfo usual error info
  708. // bUnicode if true, then the orignal file was unicode and so the
  709. // new files will also be unicode
  710. // bAutoRecovery Need to add this pragma if true
  711. // pwszAmendment See the GetLocale() comments
  712. //
  713. //***************************************************************************
  714. HRESULT CMofData::Split(CMofParser & Parser, LPWSTR pwszBMOF, WBEM_COMPILE_STATUS_INFO *pInfo, BOOL bUnicode,
  715. BOOL bAutoRecovery, LPWSTR pwszAmendment)
  716. {
  717. int i;
  718. TCHAR cNeutral[MAX_PATH];
  719. TCHAR cLocale[MAX_PATH];
  720. // Determine the file names and locale
  721. HRESULT hRes = GetFileNames(cNeutral, cLocale, pwszBMOF);
  722. if(hRes != S_OK)
  723. return S_OK;
  724. long lLocale;
  725. hRes = GetLocale(&lLocale, pwszAmendment);
  726. if(hRes != S_OK)
  727. return S_OK;
  728. // Create the output objects
  729. COutput Neutral(cNeutral, NEUTRAL, bUnicode, bAutoRecovery, lLocale);
  730. COutput Local(cLocale, LOCALIZED, bUnicode, bAutoRecovery, lLocale);
  731. if(!Neutral.IsOK() || !Local.IsOK())
  732. return WBEM_E_INVALID_PARAMETER;
  733. // Start by determining what is amended
  734. for(i = 0; i< m_aObjects.GetSize(); i++)
  735. {
  736. CMObject* pObject = (CMObject*)m_aObjects[i];
  737. pObject->Reflate(Parser);
  738. if(pObject->CheckIfAmended())
  739. {
  740. RecursiveSetAmended(pObject);
  741. }
  742. }
  743. // Create the neutral output and the localized output.
  744. // These two loops could have been combined, but are
  745. // separate for debugging purposes
  746. for(i = 0; i< m_aObjects.GetSize(); i++)
  747. {
  748. CMObject* pObject = (CMObject*)m_aObjects[i];
  749. pObject->Split(Neutral);
  750. }
  751. for(i = 0; i< m_aObjects.GetSize(); i++)
  752. {
  753. CMObject* pObject = (CMObject*)m_aObjects[i];
  754. pObject->Split(Local);
  755. }
  756. return S_OK;
  757. }