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.

3096 lines
84 KiB

  1. /*++
  2. Copyright (C) 1995-2001 Microsoft Corporation
  3. Module Name:
  4. MOFPARSE.CPP
  5. Abstract:
  6. This is a recursive descent parser for the MOF syntax.
  7. It is based on the MOF.BNF file which defines the LL(1) MOF grammar.
  8. In each production, nonterminals are represented by functions
  9. with the same name.
  10. NOTES:
  11. (a) The lexer is implemented by class CMofLexer.
  12. (b) Right-recursion in the grammar is consistently implemented
  13. directly as a loop for that nonterminal.
  14. OUTPUT:
  15. Output is an unchecked list of classes and instances.
  16. This is contained in the CMofData object.
  17. Verification of output is done elsewhere, depending on the
  18. compile context.
  19. History:
  20. a-raymcc 18-Oct-95 created.
  21. a-raymcc 25-Oct-95 semantic stack operational
  22. a-raymcc 27-Jan-96 reference & alias support
  23. a-levn 18-Oct-96 Rewrote not to use semantic stack.
  24. Converted to new mof syntax and new
  25. WINMGMT interfaces.
  26. --*/
  27. #include "precomp.h"
  28. #include <stdio.h>
  29. #include <float.h>
  30. #include "mofout.h"
  31. #include <mofparse.h>
  32. #include <moflex.h>
  33. #include <mofdata.h>
  34. #include <typehelp.h>
  35. #include <io.h>
  36. #include <fcntl.h>
  37. #include <stdio.h>
  38. #include <sys/stat.h>
  39. #include "bmofhelp.h"
  40. #include "trace.h"
  41. #include "strings.h"
  42. #include "moflex.h"
  43. #include <wbemutil.h>
  44. #include <genutils.h>
  45. #include <arrtempl.h>
  46. #include <autoptr.h>
  47. //***************************************************************************
  48. //
  49. // Global defs
  50. //
  51. //***************************************************************************
  52. static BOOL KnownBoolQualifier(wchar_t *pIdent, DWORD *pdwQualifierVal);
  53. //***************************************************************************
  54. //
  55. // Useful macros.
  56. //
  57. //***************************************************************************
  58. #define CHECK(tok) \
  59. if (m_nToken != tok) return FALSE; \
  60. NextToken();
  61. //***************************************************************************
  62. //
  63. // ValidFlags.
  64. //
  65. //***************************************************************************
  66. bool ValidFlags(bool bClass, long lFlags)
  67. {
  68. if(bClass)
  69. return ((lFlags == WBEM_FLAG_CREATE_OR_UPDATE) ||
  70. (lFlags == WBEM_FLAG_UPDATE_ONLY) ||
  71. (lFlags == WBEM_FLAG_CREATE_ONLY) ||
  72. (lFlags == WBEM_FLAG_UPDATE_SAFE_MODE) ||
  73. (lFlags == WBEM_FLAG_UPDATE_FORCE_MODE) ||
  74. (lFlags == (WBEM_FLAG_UPDATE_ONLY | WBEM_FLAG_UPDATE_SAFE_MODE)) ||
  75. (lFlags == (WBEM_FLAG_UPDATE_ONLY | WBEM_FLAG_UPDATE_FORCE_MODE)));
  76. else
  77. return
  78. ((lFlags == WBEM_FLAG_CREATE_OR_UPDATE) ||
  79. (lFlags == WBEM_FLAG_UPDATE_ONLY) ||
  80. (lFlags == WBEM_FLAG_CREATE_ONLY));
  81. }
  82. //***************************************************************************
  83. //
  84. //***************************************************************************
  85. CMofParser::CMofParser(const TCHAR *pFileName, PDBG pDbg)
  86. : m_Lexer(pFileName, pDbg), m_Output(pDbg)
  87. {
  88. m_nToken = 0;
  89. m_bOK = true;
  90. m_pDbg = pDbg;
  91. m_nErrorContext = 0;
  92. m_nErrorLineNumber = 0;
  93. StringCchCopyW(m_cFileName, MAX_PATH, pFileName);
  94. m_wszNamespace = Macro_CloneStr(L"root\\default");
  95. if(m_wszNamespace == NULL)
  96. m_bOK = false;
  97. m_bAutoRecover = false;
  98. m_wszAmendment = NULL;
  99. m_bRemotePragmaPaths = false;
  100. m_bNotBMOFCompatible = false;
  101. m_State = INITIAL;
  102. m_bDoScopeCheck = true;
  103. }
  104. //***************************************************************************
  105. //
  106. //***************************************************************************
  107. CMofParser::CMofParser(PDBG pDbg
  108. )
  109. : m_Lexer(pDbg), m_Output(pDbg)
  110. {
  111. m_bOK = true;
  112. m_nToken = 0;
  113. m_nErrorContext = 0;
  114. m_pDbg = pDbg;
  115. m_nErrorLineNumber = 0;
  116. m_bAutoRecover = false;
  117. m_bRemotePragmaPaths = false;
  118. m_wszAmendment = NULL;
  119. m_cFileName[0] = 0;
  120. m_bNotBMOFCompatible = false;
  121. m_wszNamespace = Macro_CloneStr(L"root\\default");
  122. if(m_wszNamespace == NULL)
  123. m_bOK = false;
  124. m_State = INITIAL;
  125. m_bDoScopeCheck = true;
  126. }
  127. //***************************************************************************
  128. //
  129. //***************************************************************************
  130. CMofParser::~CMofParser()
  131. {
  132. delete [] m_wszNamespace;
  133. delete [] m_wszAmendment;
  134. }
  135. //***************************************************************************
  136. //
  137. //***************************************************************************
  138. HRESULT CMofParser::SetDefaultNamespace(LPCWSTR wszDefault)
  139. {
  140. delete [] m_wszNamespace;
  141. m_wszNamespace = Macro_CloneStr(wszDefault);
  142. if(m_wszNamespace == NULL && wszDefault != NULL)
  143. return WBEM_E_OUT_OF_MEMORY;
  144. else
  145. return S_OK;
  146. }
  147. HRESULT CMofParser::SetAmendment(LPCWSTR wszDefault)
  148. {
  149. delete [] m_wszAmendment;
  150. m_wszAmendment = Macro_CloneStr(wszDefault);
  151. if(m_wszAmendment == NULL && wszDefault != NULL)
  152. return WBEM_E_OUT_OF_MEMORY;
  153. else
  154. return S_OK;
  155. }
  156. //***************************************************************************
  157. //
  158. //***************************************************************************
  159. bool CMofParser::GetErrorInfo(
  160. TCHAR *pBuffer,
  161. DWORD dwBufSize,
  162. int *pLineNumber,
  163. int *pColumn,
  164. int *pError,
  165. LPWSTR * pErrorFile
  166. )
  167. {
  168. if(m_Lexer.IsBMOF())
  169. return false;
  170. if (pLineNumber)
  171. *pLineNumber = m_Lexer.GetLineNumber();
  172. if (pColumn)
  173. *pColumn = m_Lexer.GetColumn();
  174. if (pError)
  175. *pError = m_nErrorContext;
  176. TCHAR *pErrText = TEXT("Undefined error");
  177. IntString Err(m_nErrorContext);
  178. if(lstrlen(Err) > 0)
  179. pErrText = Err;
  180. StringCchCopy(pBuffer, dwBufSize, pErrText);
  181. *pErrorFile = m_Lexer.GetErrorFile();
  182. return true;
  183. }
  184. //***************************************************************************
  185. //
  186. // <Parse> ::= <top_level_decl><Parse>
  187. // <Parse> ::= <preprocessor_command><Parse>
  188. // <Parse> ::= <>
  189. //
  190. //***************************************************************************
  191. // v1.10
  192. BOOL CMofParser::Parse()
  193. {
  194. if(m_bOK == false)
  195. {
  196. m_nErrorContext = WBEM_E_OUT_OF_MEMORY;
  197. return FALSE;
  198. }
  199. // Check for the special case of the binary mof file. If it is so,
  200. // dont parse, instead get the classes, attributes and props
  201. // from the file
  202. if(m_Lexer.IsBMOF())
  203. {
  204. return ConvertBufferIntoIntermediateForm(&m_Output,m_Lexer.GetBuff(), m_pDbg,
  205. m_Lexer.GetToFar());
  206. }
  207. if(m_Lexer.GetError() != 0)
  208. {
  209. if(CMofLexer::problem_creating_temp_file == m_Lexer.GetError())
  210. m_nErrorContext = WBEMMOF_E_ERROR_CREATING_TEMP_FILE;
  211. else if(CMofLexer::invalid_include_file == m_Lexer.GetError())
  212. m_nErrorContext = WBEMMOF_E_ERROR_INVALID_INCLUDE_FILE;
  213. else
  214. m_nErrorContext = WBEMMOF_E_INVALID_FILE;
  215. return FALSE;
  216. }
  217. NextToken();
  218. BOOL bEnd = FALSE;
  219. while(!bEnd)
  220. {
  221. switch(m_nToken)
  222. {
  223. case TOK_POUND:
  224. if(!preprocessor_command())
  225. return FALSE;
  226. break;
  227. case TOK_QUALIFIER:
  228. if(!qualifier_default())
  229. return FALSE;
  230. break;
  231. case 0: // nothing left to parse
  232. bEnd = TRUE;
  233. break;
  234. default:
  235. if (!top_level_decl())
  236. return FALSE;
  237. break;
  238. }
  239. }
  240. return TRUE;
  241. }
  242. //***************************************************************************
  243. //
  244. // <preprocessor_command> ::= <pound_define> // not impl
  245. // <preprocessor_command> ::= TOK_PRAGMA <pound_pragma>
  246. // <preprocessor_command> ::= TOK_LINE TOK_UNSIGNED_NUMERIC_CONST TOK_LPWSTR
  247. //
  248. //***************************************************************************
  249. BOOL CMofParser::preprocessor_command()
  250. {
  251. NextToken();
  252. DWORD dwType = m_nToken;
  253. if(dwType == TOK_SIMPLE_IDENT && !wbem_wcsicmp(L"line", m_Lexer.GetText()))
  254. dwType = TOK_LINE;
  255. switch(dwType)
  256. {
  257. case TOK_PRAGMA:
  258. if(!pound_pragma())
  259. return FALSE;
  260. break;
  261. case TOK_LINE:
  262. NextToken();
  263. if(m_nToken != TOK_UNSIGNED64_NUMERIC_CONST)
  264. return false;
  265. m_Lexer.SetLineNumber((int)m_Lexer.GetLastInt());
  266. NextToken();
  267. if(m_nToken != TOK_LPWSTR)
  268. return false;
  269. m_Lexer.SetErrorFile(m_Lexer.GetText());
  270. NextToken();
  271. return TRUE;
  272. case TOK_INCLUDE:
  273. case TOK_DEFINE:
  274. Trace(true, m_pDbg, PREPROCESSOR);
  275. return FALSE;
  276. }
  277. return TRUE;
  278. }
  279. //***************************************************************************
  280. //
  281. // <FailOrNoFail> ::= FAIL;
  282. // <FailOrNoFail> ::= NOFAIL;
  283. //
  284. //***************************************************************************
  285. BOOL CMofParser::FailOrNoFail(bool * pbFail)
  286. {
  287. NextToken();
  288. if(m_nToken == TOK_FAIL)
  289. *pbFail = true;
  290. else if(m_nToken == TOK_NOFAIL)
  291. *pbFail = false;
  292. else return FALSE;
  293. return TRUE;
  294. }
  295. //***************************************************************************
  296. //
  297. //<pound_pragma> ::= TOK_LPWSTR // Where string is "namespace"
  298. // TOK_OPEN_PAREN TOK_LPWSTR TOK_CLOSE_PAREN;
  299. //
  300. //<pound_pragma> ::= TOK_AMENDMENT
  301. // TOK_OPEN_PAREN TOK_LPWSTR TOK_CLOSE_PAREN;
  302. //
  303. //<pound_pragma> ::= TOK_CLASSFLAGS
  304. // TOK_OPEN_PAREN <flag_list> TOK_CLOSE_PAREN;
  305. //
  306. //<pound_pragma> ::= TOK_INSTANCEFLAGS
  307. // TOK_OPEN_PAREN <flag_list> TOK_CLOSE_PAREN;
  308. //
  309. //<pound_pragma> ::= TOK_AUTORECOVER
  310. //
  311. //<pound_pragma> ::= TOK_DELETECLASS
  312. // TOK_OPEN_PAREN TOK_LPWSTR TOK_COMMA <FailOrNoFail> TOK_CLOSE_PAREN;
  313. //
  314. //***************************************************************************
  315. BOOL CMofParser::pound_pragma()
  316. {
  317. NextToken();
  318. DWORD dwType = m_nToken;
  319. if(dwType == TOK_AUTORECOVER)
  320. {
  321. m_bAutoRecover = true;
  322. NextToken();
  323. return TRUE;
  324. }
  325. if(dwType == TOK_SIMPLE_IDENT && !wbem_wcsicmp(L"locale", m_Lexer.GetText()))
  326. {
  327. dwType = TOK_LOCALE;
  328. ERRORTRACE((LOG_MOFCOMP,"Warning, unsupported LOCALE pragma\n"));
  329. }
  330. if(dwType == TOK_SIMPLE_IDENT && !wbem_wcsicmp(L"INSTANCELOCALE", m_Lexer.GetText()))
  331. {
  332. dwType = TOK_INSTANCELOCALE;
  333. ERRORTRACE((LOG_MOFCOMP,"Warning, unsupported INSTANCELOCALE pragma\n"));
  334. }
  335. if(dwType == TOK_SIMPLE_IDENT && !wbem_wcsicmp(L"NONLOCAL", m_Lexer.GetText()))
  336. {
  337. dwType = TOK_NONLOCAL;
  338. ERRORTRACE((LOG_MOFCOMP,"Warning, unsupported NONLOCAL pragma\n"));
  339. }
  340. if(dwType == TOK_SIMPLE_IDENT && !wbem_wcsicmp(L"NONLOCALTYPE", m_Lexer.GetText()))
  341. {
  342. dwType = TOK_NONLOCALTYPE;
  343. ERRORTRACE((LOG_MOFCOMP,"Warning, unsupported NONLOCALTYPE pragma\n"));
  344. }
  345. if(dwType == TOK_SIMPLE_IDENT && !wbem_wcsicmp(L"SOURCE", m_Lexer.GetText()))
  346. {
  347. dwType = TOK_SOURCE;
  348. ERRORTRACE((LOG_MOFCOMP,"Warning, unsupported SOURCE pragma\n"));
  349. }
  350. if(dwType == TOK_SIMPLE_IDENT && !wbem_wcsicmp(L"SOURCETYPE", m_Lexer.GetText()))
  351. {
  352. dwType = TOK_SOURCETYPE;
  353. ERRORTRACE((LOG_MOFCOMP,"Warning, unsupported SOURCETYPE pragma\n"));
  354. }
  355. if(dwType == TOK_SIMPLE_IDENT && !wbem_wcsicmp(L"namespace", m_Lexer.GetText()))
  356. dwType = TOK_NAMESPACE;
  357. if(dwType == TOK_SIMPLE_IDENT && !wbem_wcsicmp(L"deleteinstance", m_Lexer.GetText()))
  358. dwType = TOK_DELETEINSTANCE;
  359. if(dwType != TOK_NAMESPACE && dwType != TOK_INSTANCEFLAGS && dwType != TOK_CLASSFLAGS &&
  360. dwType != TOK_AMENDMENT && dwType != TOK_DELETECLASS && dwType != TOK_DELETEINSTANCE &&
  361. dwType != TOK_LOCALE && dwType != TOK_INSTANCELOCALE && dwType != TOK_NONLOCAL &&
  362. dwType != TOK_NONLOCALTYPE && dwType != TOK_SOURCE && dwType != TOK_SOURCETYPE)
  363. {
  364. m_nErrorContext = WBEMMOF_E_INVALID_PRAGMA;
  365. return FALSE;
  366. }
  367. m_nErrorContext = WBEMMOF_E_EXPECTED_OPEN_PAREN;
  368. NextToken();
  369. CHECK(TOK_OPEN_PAREN);
  370. LPWSTR wszNewNamespace;
  371. BOOL bRet = FALSE;
  372. WCHAR * pClassName;
  373. WCHAR *pMachine;
  374. BOOL bClass;
  375. switch(dwType)
  376. {
  377. case TOK_CLASSFLAGS:
  378. case TOK_INSTANCEFLAGS:
  379. if(!flag_list(dwType ==TOK_CLASSFLAGS))
  380. return FALSE;
  381. break;
  382. case TOK_AMENDMENT:
  383. m_nErrorContext = WBEMMOF_E_INVALID_AMENDMENT_SYNTAX;
  384. if(m_nToken != TOK_LPWSTR) return FALSE;
  385. if(m_wszAmendment)
  386. {
  387. m_nErrorContext = WBEMMOF_E_INVALID_DUPLICATE_AMENDMENT;
  388. return FALSE;
  389. }
  390. m_wszAmendment = Macro_CloneStr((LPWSTR)m_Lexer.GetText());
  391. if(m_wszAmendment == NULL && (LPWSTR)m_Lexer.GetText() != NULL)
  392. {
  393. m_nErrorContext = WBEM_E_OUT_OF_MEMORY;
  394. return FALSE;
  395. }
  396. break;
  397. case TOK_DELETEINSTANCE:
  398. case TOK_DELETECLASS:
  399. if(TOK_DELETECLASS == dwType)
  400. {
  401. bClass = TRUE;
  402. m_nErrorContext = WBEMMOF_E_INVALID_DELETECLASS_SYNTAX;
  403. }
  404. else
  405. {
  406. bClass = FALSE;
  407. m_nErrorContext = WBEMMOF_E_INVALID_DELETEINSTANCE_SYNTAX;
  408. }
  409. m_bNotBMOFCompatible = true;
  410. if(m_nToken != TOK_LPWSTR)
  411. return FALSE;
  412. pClassName = Macro_CloneStr((LPWSTR)m_Lexer.GetText());
  413. if(pClassName == NULL)
  414. return FALSE;
  415. if(wcslen(pClassName) >= 1)
  416. {
  417. bool bFail;
  418. NextToken();
  419. if(m_nToken == TOK_COMMA)
  420. if(FailOrNoFail(&bFail))
  421. {
  422. wmilib::auto_ptr<CMoActionPragma> pObject(new CMoActionPragma(pClassName, m_pDbg, bFail, bClass));
  423. if(pObject.get() == NULL)
  424. {
  425. m_nErrorContext = WBEM_E_OUT_OF_MEMORY;
  426. return FALSE;
  427. }
  428. if(pObject->IsOK() == false)
  429. {
  430. m_nErrorContext = WBEM_E_OUT_OF_MEMORY;
  431. return FALSE;
  432. }
  433. HRESULT hr2 = pObject->SetNamespace(m_wszNamespace);
  434. if(FAILED(hr2))
  435. {
  436. m_nErrorContext = hr2;
  437. return FALSE;
  438. }
  439. pObject->SetOtherDefaults(GetClassFlags(), GetInstanceFlags());
  440. m_Output.AddObject(pObject.get());
  441. pObject.release();
  442. bRet = TRUE;
  443. }
  444. }
  445. delete pClassName;
  446. if(bRet == FALSE)
  447. return FALSE;
  448. break;
  449. case TOK_NAMESPACE:
  450. m_nErrorContext = WBEMMOF_E_INVALID_NAMESPACE_SYNTAX;
  451. if(m_nToken != TOK_LPWSTR) return FALSE;
  452. wszNewNamespace = (LPWSTR)m_Lexer.GetText();
  453. pMachine = ExtractMachineName(wszNewNamespace);
  454. if(pMachine)
  455. {
  456. if(!bAreWeLocal(pMachine))
  457. m_bRemotePragmaPaths = true;
  458. delete [] pMachine;
  459. }
  460. if(wszNewNamespace[0] == L'\\' || wszNewNamespace[0] == L'/')
  461. {
  462. if(wszNewNamespace[1] == L'\\' || wszNewNamespace[1] == L'/')
  463. {
  464. }
  465. else
  466. {
  467. // Cut off the slash
  468. // =================
  469. wszNewNamespace += 1;
  470. }
  471. delete [] m_wszNamespace;
  472. m_wszNamespace = Macro_CloneStr(wszNewNamespace);
  473. if(m_wszNamespace == NULL && wszNewNamespace != NULL)
  474. {
  475. m_nErrorContext = WBEM_E_OUT_OF_MEMORY;
  476. return FALSE;
  477. }
  478. }
  479. else
  480. {
  481. // Append to the old value
  482. // =======================
  483. DWORD dwLen = wcslen(m_wszNamespace) + 2 +
  484. wcslen(wszNewNamespace);
  485. LPWSTR wszFullNamespace = new WCHAR[dwLen];
  486. if(wszFullNamespace == NULL)
  487. {
  488. m_nErrorContext = WBEM_E_OUT_OF_MEMORY;
  489. return FALSE;
  490. }
  491. StringCchPrintfW(wszFullNamespace, dwLen, L"%s\\%s", m_wszNamespace, wszNewNamespace);
  492. delete [] m_wszNamespace;
  493. m_wszNamespace = wszFullNamespace;
  494. }
  495. break;
  496. }
  497. if(dwType != TOK_CLASSFLAGS && dwType != TOK_INSTANCEFLAGS)
  498. NextToken();
  499. m_nErrorContext = WBEMMOF_E_EXPECTED_CLOSE_PAREN;
  500. CHECK(TOK_CLOSE_PAREN);
  501. return TRUE;
  502. }
  503. //***************************************************************************
  504. //
  505. // <flag_list> ::= TOK_LPWSTR <string_list_rest>;
  506. // <flag_list> ::= TOK_UNSIGNED_NUMERIC_CONST;
  507. // <flag_list> ::= <>;
  508. //
  509. //***************************************************************************
  510. bool CMofParser::GetFlagValue(long & lNewValue)
  511. {
  512. if(!wbem_wcsicmp(L"createonly", (LPWSTR)m_Lexer.GetText()))
  513. lNewValue |= WBEM_FLAG_CREATE_ONLY;
  514. else if(!wbem_wcsicmp(L"updateonly", (LPWSTR)m_Lexer.GetText()))
  515. lNewValue |= WBEM_FLAG_UPDATE_ONLY;
  516. else if(!wbem_wcsicmp(L"safeupdate", (LPWSTR)m_Lexer.GetText()))
  517. lNewValue |= WBEM_FLAG_UPDATE_SAFE_MODE;
  518. else if(!wbem_wcsicmp(L"forceupdate", (LPWSTR)m_Lexer.GetText()))
  519. lNewValue |= WBEM_FLAG_UPDATE_FORCE_MODE;
  520. else
  521. return false;
  522. return true;
  523. }
  524. bool CMofParser::flag_list(bool bClass)
  525. {
  526. long lNewValue = 0;
  527. m_nErrorContext = WBEMMOF_E_INVALID_FLAGS_SYNTAX;
  528. if(m_nToken == TOK_UNSIGNED64_NUMERIC_CONST)
  529. {
  530. lNewValue = _wtol(m_Lexer.GetText());
  531. NextToken();
  532. }
  533. else if (m_nToken == TOK_CLOSE_PAREN)
  534. lNewValue = 0;
  535. else if (m_nToken == TOK_LPWSTR)
  536. {
  537. if(!GetFlagValue(lNewValue))
  538. return false;
  539. NextToken();
  540. if(!string_list(bClass, lNewValue))
  541. return false;
  542. if(!ValidFlags(bClass, lNewValue))
  543. return false;
  544. }
  545. else
  546. return false;
  547. if(bClass)
  548. m_lDefClassFlags = lNewValue;
  549. else
  550. m_lDefInstanceFlags = lNewValue;
  551. return true;
  552. }
  553. //***************************************************************************
  554. //
  555. // <string_list> ::= <>;
  556. // <string_list> ::= TOK_COMMA TOK_LPWSTR <string_list>;
  557. //
  558. //***************************************************************************
  559. bool CMofParser::string_list(bool bClass, long & lNewValue)
  560. {
  561. if (m_nToken == TOK_COMMA)
  562. {
  563. NextToken();
  564. if (m_nToken != TOK_LPWSTR)
  565. return false;
  566. if(!GetFlagValue(lNewValue))
  567. return false;
  568. NextToken();
  569. return string_list(bClass, lNewValue);
  570. }
  571. return true;
  572. }
  573. //***************************************************************************
  574. //
  575. // <top_level_decl> ::= <qualifier_decl> <decl_type>
  576. //
  577. // Note: <decl_type> is implicit in the switch() statement.
  578. //
  579. //***************************************************************************
  580. // 1.10
  581. BOOL CMofParser::top_level_decl()
  582. {
  583. std::auto_ptr<CMoQualifierArray> paQualifiers(new CMoQualifierArray(m_pDbg));
  584. ParseState QualPosition;
  585. GetParserPosition(&QualPosition);
  586. if (paQualifiers.get() == NULL || !qualifier_decl(*(paQualifiers.get()), true, CLASSINST_SCOPE))
  587. {
  588. return FALSE;
  589. }
  590. // Branch to the correct top-level declaration.
  591. // =============================================
  592. switch (m_nToken) {
  593. case TOK_CLASS:
  594. {
  595. if(m_bDoScopeCheck && (FALSE == CheckScopes(IN_CLASS, paQualifiers.get(), NULL))){
  596. return FALSE;
  597. }
  598. paQualifiers.release();
  599. if(!class_decl(paQualifiers.get(), NULL, &QualPosition))
  600. return FALSE;
  601. m_nErrorContext = WBEMMOF_E_EXPECTED_SEMI;
  602. if(m_nToken != TOK_SEMI)
  603. return FALSE;
  604. NextToken();
  605. return TRUE;
  606. }
  607. case TOK_INSTANCE:
  608. {
  609. if(m_bDoScopeCheck && (FALSE == CheckScopes(IN_INSTANCE, paQualifiers.get(), NULL))){
  610. return FALSE;
  611. }
  612. paQualifiers.release();
  613. if(!instance_decl(paQualifiers.get(), NULL, &QualPosition))
  614. return FALSE;
  615. m_nErrorContext = WBEMMOF_E_EXPECTED_SEMI;
  616. if(m_nToken != TOK_SEMI)
  617. return FALSE;
  618. NextToken();
  619. return TRUE;
  620. }
  621. case TOK_TYPEDEF:
  622. return typedef_(paQualifiers.get());
  623. default:
  624. m_nErrorContext = WBEMMOF_E_UNRECOGNIZED_TOKEN;
  625. // Syntax error
  626. }
  627. return FALSE;
  628. }
  629. //***************************************************************************
  630. //
  631. // <typedef> ::= see BNF. Not supported.
  632. //
  633. //***************************************************************************
  634. BOOL CMofParser::typedef_(ACQUIRE CMoQualifierArray* paQualifiers)
  635. {
  636. m_nErrorContext = WBEMMOF_E_TYPEDEF_NOT_SUPPORTED;
  637. Trace(true, m_pDbg, NO_TYPEDEFS);
  638. return FALSE;
  639. }
  640. //***************************************************************************
  641. //
  642. // <class_decl> ::=
  643. // TOK_CLASS
  644. // TOK_SIMPLE_IDENT
  645. // <class_def>
  646. //
  647. // Adds the resulting class to the member CMofData
  648. //
  649. //***************************************************************************
  650. // v1.10
  651. BOOL CMofParser::class_decl(ACQUIRE CMoQualifierArray* paQualifiers, VARIANT * pValue, ParseState * pQualPosition)
  652. {
  653. BSTR strClassName;
  654. // Begin syntax check.
  655. // ===================
  656. m_nErrorContext = WBEMMOF_E_INVALID_CLASS_DECLARATION;
  657. int nFirstLine = m_Lexer.GetLineNumber();
  658. if (m_nToken != TOK_CLASS)
  659. {
  660. delete paQualifiers;
  661. return FALSE;
  662. }
  663. NextToken();
  664. // Get the class name.
  665. // ====================
  666. if (m_nToken != TOK_SIMPLE_IDENT)
  667. {
  668. m_nErrorContext = WBEMMOF_E_EXPECTED_CLASS_NAME;
  669. delete paQualifiers;
  670. return FALSE;
  671. }
  672. strClassName = SysAllocString((LPWSTR)m_Lexer.GetText());
  673. if(strClassName == NULL)
  674. {
  675. m_nErrorContext = WBEM_E_OUT_OF_MEMORY;
  676. return FALSE;
  677. }
  678. // This finishes up and does the necessary freeing
  679. return class_def(paQualifiers, strClassName, nFirstLine, pQualPosition, pValue);
  680. }
  681. //***************************************************************************
  682. //
  683. // <class_def> ::=;
  684. // <class_def> ::=
  685. // <as_alias>
  686. // <opt_parent_class>
  687. // TOK_OPEN_BRACE
  688. // <property_decl_list>
  689. // TOK_CLOSE_BRACE;
  690. //
  691. // Adds the resulting class to the member CMofData
  692. //
  693. //***************************************************************************
  694. // v1.10
  695. BOOL CMofParser::class_def(ACQUIRE CMoQualifierArray* paQualifiers,
  696. BSTR strClassName, int nFirstLine, ParseState * pQualPosition,
  697. VARIANT * pVar)
  698. {
  699. BOOL bRetVal = FALSE; // Default
  700. BSTR strParentName = NULL;
  701. LPWSTR wszAlias = NULL;
  702. // Begin syntax check.
  703. // ===================
  704. NextToken();
  705. // Check for the case where its just a semi. That would be the case
  706. // where the entire line was [qual] class myclass;
  707. if(m_nToken == TOK_SEMI)
  708. {
  709. CMoClass* pObject = new CMoClass(strParentName, strClassName, m_pDbg, TRUE);
  710. if(pObject == NULL)
  711. return FALSE;
  712. if(pObject->IsOK() == false)
  713. {
  714. m_nErrorContext = WBEM_E_OUT_OF_MEMORY;
  715. delete pObject;
  716. return FALSE;
  717. }
  718. HRESULT hr2 = pObject->SetNamespace(m_wszNamespace);
  719. if(FAILED(hr2))
  720. {
  721. m_nErrorContext = hr2;
  722. delete pObject;
  723. return FALSE;
  724. }
  725. pObject->SetOtherDefaults(GetClassFlags(), GetInstanceFlags());
  726. SysFreeString(strClassName);
  727. // Apply qualifiers (already parsed)
  728. // =================================
  729. pObject->SetQualifiers(paQualifiers);
  730. m_Output.AddObject(pObject);
  731. return TRUE;
  732. }
  733. // Get the alias (if any)
  734. // ======================
  735. if(!as_alias(wszAlias))
  736. {
  737. delete paQualifiers;
  738. SysFreeString(strClassName);
  739. return FALSE;
  740. }
  741. // Get the parent type name, if there is one.
  742. // ===========================================
  743. if (!opt_parent_class(&strParentName))
  744. {
  745. SysFreeString(strClassName);
  746. delete paQualifiers;
  747. return FALSE;
  748. }
  749. // Check for the open brace.
  750. // =========================
  751. if (m_nToken != TOK_OPEN_BRACE)
  752. {
  753. m_nErrorContext = WBEMMOF_E_EXPECTED_OPEN_BRACE;
  754. SysFreeString(strClassName);
  755. SysFreeString(strParentName);
  756. delete paQualifiers;
  757. return FALSE;
  758. }
  759. // Create new object
  760. // =================
  761. CMoClass* pObject = new CMoClass(strParentName, strClassName, m_pDbg);
  762. if(pObject == NULL)
  763. return FALSE;
  764. if(pObject->IsOK() == false)
  765. {
  766. delete pObject;
  767. return FALSE;
  768. }
  769. GetParserPosition(pObject->GetDataState());
  770. if(pQualPosition)
  771. pObject->SetQualState(pQualPosition);
  772. NextToken();
  773. HRESULT hr2 = pObject->SetNamespace(m_wszNamespace);
  774. if(FAILED(hr2))
  775. {
  776. m_nErrorContext = hr2;
  777. return FALSE;
  778. }
  779. pObject->SetOtherDefaults(GetClassFlags(), GetInstanceFlags());
  780. SysFreeString(strClassName);
  781. SysFreeString(strParentName);
  782. // Apply qualifiers (already parsed)
  783. // =================================
  784. pObject->SetQualifiers(paQualifiers);
  785. // Set alias
  786. // =========
  787. if(wszAlias != NULL)
  788. {
  789. HRESULT hr2 = pObject->SetAlias(wszAlias);
  790. delete [] wszAlias;
  791. if(FAILED(hr2))
  792. {
  793. m_nErrorContext = hr2;
  794. goto Exit;
  795. }
  796. }
  797. // Now get the list properties.
  798. // ============================
  799. if (!property_decl_list(pObject))
  800. goto Exit;
  801. // Final close brace and semicolon.
  802. // ================================
  803. m_nErrorContext = WBEMMOF_E_EXPECTED_BRACE_OR_BAD_TYPE;
  804. if (m_nToken != TOK_CLOSE_BRACE)
  805. goto Exit;
  806. hr2 = pObject->SetLineRange(nFirstLine, m_Lexer.GetLineNumber(), m_Lexer.GetErrorFile());
  807. if(FAILED(hr2))
  808. {
  809. m_nErrorContext = hr2;
  810. goto Exit;
  811. }
  812. NextToken();
  813. // We have now syntactially recognized a class
  814. // but done no context-sensitive verification. This is
  815. // deferred to whatever module is using the parser output.
  816. // =======================================================
  817. if(pVar)
  818. {
  819. pVar->vt = VT_EMBEDDED_OBJECT;
  820. pVar->punkVal = (IUnknown *)pObject;
  821. }
  822. else
  823. {
  824. pObject->Deflate(false);
  825. m_Output.AddObject(pObject);
  826. }
  827. return TRUE;
  828. Exit:
  829. delete pObject;
  830. return FALSE;
  831. }
  832. //***************************************************************************
  833. //
  834. // <sys_or_regular> ::= TOK_SIMPLE_IDENT;
  835. // <sys_or_regular> ::= TOK_SYSTEM_IDENT;
  836. //
  837. //***************************************************************************
  838. bool CMofParser::sys_or_regular()
  839. {
  840. if(m_nToken == TOK_SIMPLE_IDENT || m_nToken == TOK_SYSTEM_IDENT)
  841. return true;
  842. else
  843. return false;
  844. }
  845. //***************************************************************************
  846. //
  847. // <opt_parent_class> ::= TOK_COLON <SYS_OR_REGULAR>;
  848. // <opt_parent_class> ::= <>;
  849. //
  850. //***************************************************************************
  851. // v1.10
  852. BOOL CMofParser::opt_parent_class(OUT BSTR* pstrParentName)
  853. {
  854. // If a colon is present, there is a parent type.
  855. // ==============================================
  856. if (m_nToken == TOK_COLON)
  857. {
  858. NextToken();
  859. // Get the parent type identifier.
  860. // ===============================
  861. if (!sys_or_regular())
  862. {
  863. m_nErrorContext = WBEMMOF_E_EXPECTED_CLASS_NAME;
  864. return FALSE;
  865. }
  866. *pstrParentName = SysAllocString((LPWSTR)m_Lexer.GetText());
  867. if(*pstrParentName == NULL)
  868. {
  869. m_nErrorContext = WBEM_E_OUT_OF_MEMORY;
  870. return FALSE;
  871. }
  872. NextToken();
  873. }
  874. else *pstrParentName = NULL;
  875. return TRUE;
  876. }
  877. //***************************************************************************
  878. //
  879. // <property_decl_list> ::= <PropOrMeth_decl> <property_decl_list>;
  880. // <property_decl_list> ::= <>;
  881. //
  882. // Adds the properties to the CMObject passed.
  883. //
  884. //***************************************************************************
  885. // v1.10
  886. BOOL CMofParser::property_decl_list(MODIFY CMObject* pObject)
  887. {
  888. // Begin parsing.
  889. // ==============
  890. while (m_nToken == TOK_SIMPLE_IDENT || m_nToken == TOK_OPEN_BRACKET ||
  891. m_nToken == TOK_VOID || m_nToken == TOK_SYSTEM_IDENT)
  892. {
  893. CMoProperty* pProp = NULL;
  894. if (!PropOrMeth_decl(&pProp))
  895. {
  896. delete pProp;
  897. return FALSE;
  898. }
  899. if(!pObject->AddProperty(pProp))
  900. {
  901. // Duplicate property
  902. // ==================
  903. m_nErrorContext = WBEMMOF_E_DUPLICATE_PROPERTY;
  904. return FALSE;
  905. }
  906. }
  907. return TRUE;
  908. }
  909. //***************************************************************************
  910. //
  911. // <PropOrMeth_decl> ::=
  912. // <qualifier_decl>
  913. // <PropOrMeth_decl2>;
  914. //
  915. // Stores itself in the passed CMoProperty object (unintialized)
  916. //
  917. //***************************************************************************
  918. // v1.10
  919. BOOL CMofParser::PropOrMeth_decl(OUT CMoProperty ** ppProp)
  920. {
  921. // Get the qualifiers
  922. // ==================
  923. CMoQualifierArray* paQualifiers = new CMoQualifierArray(m_pDbg);
  924. if (paQualifiers == NULL || !qualifier_decl(*paQualifiers, false, PROPMETH_SCOPE))
  925. return FALSE;
  926. // Read the rest of the property information
  927. // =========================================
  928. if (!PropOrMeth_decl2(ppProp, paQualifiers))
  929. return FALSE;
  930. SCOPE_CHECK scheck = IN_METHOD;
  931. if((*ppProp)->IsValueProperty())
  932. scheck = IN_PROPERTY;
  933. if(m_bDoScopeCheck && (FALSE == CheckScopes(scheck, paQualifiers, *ppProp)))
  934. return FALSE;
  935. return TRUE;
  936. }
  937. //***************************************************************************
  938. //
  939. // <PropOrMeth_decl2> ::= <TypeAndName> <finish_PropOrMeth>;
  940. // <PropOrMeth_decl2> ::= TOK_VOID TOK_SIMPLE_IDENT <finish_meth>;
  941. //
  942. // Modifies the CMoProperty object passed in (the qualifiers are already
  943. // set by this time).
  944. //
  945. //***************************************************************************
  946. // v1.10
  947. BOOL CMofParser::PropOrMeth_decl2(MODIFY CMoProperty ** ppProp, CMoQualifierArray* paQualifiers)
  948. {
  949. if(m_nToken != TOK_VOID)
  950. {
  951. CMoType Type(m_pDbg);
  952. WString sName;
  953. BOOL bRet = TypeAndName(Type, sName);
  954. if(bRet)
  955. bRet = finish_PropOrMeth(Type, sName, ppProp, paQualifiers);
  956. return bRet;
  957. }
  958. else
  959. {
  960. CMoType Type(m_pDbg);
  961. WString sName;
  962. HRESULT hr2 = Type.SetTitle(L"NULL");
  963. if(FAILED(hr2))
  964. {
  965. m_nErrorContext = hr2;
  966. return FALSE;
  967. }
  968. // Now get the property name.
  969. // ==========================
  970. NextToken();
  971. if (m_nToken != TOK_SIMPLE_IDENT)
  972. {
  973. m_nErrorContext = WBEMMOF_E_EXPECTED_PROPERTY_NAME;
  974. return FALSE;
  975. }
  976. sName = m_Lexer.GetText();
  977. NextToken();
  978. return finish_meth(Type, sName, ppProp, paQualifiers);
  979. }
  980. }
  981. //***************************************************************************
  982. //
  983. // <finish_PropOrMeth> ::= <finish_prop>;
  984. // <finish_PropOrMeth> ::= <finish_meth>;
  985. //
  986. // examines the string, gets the name and determines if it is a property or
  987. // method and then calls the appropriate routine to finish.
  988. //
  989. //***************************************************************************
  990. BOOL CMofParser::finish_PropOrMeth(CMoType & Type, WString & sName,MODIFY CMoProperty ** ppProp,
  991. CMoQualifierArray* paQualifiers)
  992. {
  993. if(m_nToken == TOK_OPEN_PAREN)
  994. return finish_meth(Type, sName, ppProp, paQualifiers);
  995. else
  996. return finish_prop(Type, sName, ppProp, paQualifiers);
  997. }
  998. //***************************************************************************
  999. //
  1000. // <finish_prop> ::= <opt_array> <default_value> TOK_SEMI
  1001. //
  1002. //***************************************************************************
  1003. BOOL CMofParser::finish_prop(CMoType & Type, WString & sName, CMoProperty ** ppProp,
  1004. CMoQualifierArray * paQualifiers)
  1005. {
  1006. unsigned uSuggestedSize = 0xffffffff;
  1007. *ppProp = new CValueProperty(paQualifiers, m_pDbg);
  1008. if(*ppProp == NULL)
  1009. return FALSE;
  1010. if(FAILED((*ppProp)->SetPropName((wchar_t *) sName)))
  1011. return FALSE;
  1012. if(FAILED((*ppProp)->SetTypeTitle(Type.GetTitle())))
  1013. return FALSE;
  1014. // Check to see if this is an array type.
  1015. // ======================================
  1016. if (!opt_array(Type, paQualifiers))
  1017. return FALSE;
  1018. // Type parsing complete. Check it
  1019. // ===============================
  1020. VARTYPE vtType = Type.GetCIMType();
  1021. if(vtType == VT_ERROR)
  1022. {
  1023. m_nErrorContext = WBEMMOF_E_UNRECOGNIZED_TYPE;
  1024. return FALSE;
  1025. }
  1026. // Get the default value and assign it to the property.
  1027. // ====================================================
  1028. if (!default_value(Type, (*ppProp)->AccessValue()))
  1029. return FALSE;
  1030. // If Type resulted in extra qualifiers (CIMTYPE), add them to the prop
  1031. // ===================================================================
  1032. CMoValue & Val = (*ppProp)->AccessValue();
  1033. Val.SetType(vtType);
  1034. Type.StoreIntoQualifiers(paQualifiers);
  1035. // Check closing semicolon.
  1036. // ========================
  1037. if (m_nToken != TOK_SEMI)
  1038. {
  1039. m_nErrorContext = WBEMMOF_E_EXPECTED_SEMI;
  1040. return FALSE;
  1041. }
  1042. NextToken();
  1043. return TRUE;
  1044. }
  1045. //***************************************************************************
  1046. //
  1047. // <finish_meth> ::= TOK_OPEN_PAREN <arg_list> TOK_CLOSE_PAREN TOK_SEMI
  1048. //
  1049. //***************************************************************************
  1050. BOOL CMofParser::finish_meth(CMoType & Type, WString & sName, CMoProperty ** ppProp,
  1051. CMoQualifierArray * paQualifiers)
  1052. {
  1053. CMethodProperty * pMeth = new CMethodProperty(paQualifiers, m_pDbg, FALSE);
  1054. if(pMeth == NULL)
  1055. return FALSE;
  1056. *ppProp = pMeth;
  1057. if(FAILED(pMeth->SetPropName((wchar_t *) sName)))
  1058. return FALSE;
  1059. if(FAILED(pMeth->SetTypeTitle(Type.GetTitle())))
  1060. return FALSE;
  1061. // Check to see if this is an array type.
  1062. // ======================================
  1063. if (!arg_list(pMeth))
  1064. return FALSE;
  1065. // If Type resulted in extra qualifiers (CIMTYPE), add them to the prop
  1066. // ===================================================================
  1067. // Type.StoreIntoQualifiers((*ppProp)->GetQualifiers());
  1068. if (m_nToken != TOK_CLOSE_PAREN)
  1069. {
  1070. m_nErrorContext = WBEMMOF_E_EXPECTED_CLOSE_PAREN;
  1071. return FALSE;
  1072. }
  1073. if(Type.IsArray())
  1074. {
  1075. m_nErrorContext = WBEMMOF_E_NO_ARRAYS_RETURNED;
  1076. return FALSE;
  1077. }
  1078. WString sTemp = L"ReturnValue";
  1079. CMoValue Value(m_pDbg);
  1080. if(wbem_wcsicmp(L"NULL",Type.GetTitle()))
  1081. if(!pMeth->AddToArgObjects(NULL, sTemp, Type, TRUE, m_nErrorContext, NULL, Value))
  1082. return FALSE;
  1083. NextToken();
  1084. // Check closing semicolon.
  1085. // ========================
  1086. if (m_nToken != TOK_SEMI)
  1087. {
  1088. m_nErrorContext = WBEMMOF_E_EXPECTED_SEMI;
  1089. return FALSE;
  1090. }
  1091. NextToken();
  1092. return TRUE;
  1093. }
  1094. //***************************************************************************
  1095. //
  1096. // <arg_list> ::= <arg_decl> <rest_of_args>;
  1097. // <arg_list> ::= <>;
  1098. //
  1099. //***************************************************************************
  1100. BOOL CMofParser::arg_list(CMethodProperty * pMethProp)
  1101. {
  1102. NextToken();
  1103. if (m_nToken == TOK_CLOSE_PAREN)
  1104. {
  1105. return TRUE;
  1106. }
  1107. BOOL bRet = arg_decl(pMethProp);
  1108. if(!bRet)
  1109. return FALSE;
  1110. else
  1111. return rest_of_args(pMethProp);
  1112. }
  1113. //***************************************************************************
  1114. //
  1115. // <arg_decl> ::= <qualifier_decl><TypeAndName><opt_array>;
  1116. //
  1117. //***************************************************************************
  1118. BOOL CMofParser::arg_decl(CMethodProperty * pMethProp)
  1119. {
  1120. CMoQualifierArray * paQualifiers = new CMoQualifierArray(m_pDbg);
  1121. if(paQualifiers == NULL || !qualifier_decl(*paQualifiers,false, PROPMETH_SCOPE))
  1122. return FALSE;
  1123. CValueProperty * pArg = new CValueProperty(paQualifiers, m_pDbg);
  1124. if(pArg == NULL)
  1125. return FALSE;
  1126. CMoType Type(m_pDbg);
  1127. WString sName;
  1128. if(!TypeAndName(Type, sName))
  1129. return FALSE;
  1130. if(FAILED(pArg->SetPropName(sName)))
  1131. return FALSE;
  1132. if(FAILED(pArg->SetTypeTitle(Type.GetTitle())))
  1133. return FALSE;
  1134. if(!opt_array(Type, paQualifiers))
  1135. return FALSE;
  1136. VARIANT * pVar = pArg->GetpVar();
  1137. if(!default_value(Type, pArg->AccessValue()))
  1138. return FALSE;
  1139. if(m_bDoScopeCheck && (FALSE == CheckScopes(IN_PARAM, paQualifiers, pArg)))
  1140. return FALSE;
  1141. m_nErrorContext = WBEM_E_INVALID_PARAMETER;
  1142. if(!pMethProp->AddToArgObjects(paQualifiers, sName, Type, FALSE, m_nErrorContext, pVar,
  1143. pArg->AccessValue()))
  1144. return FALSE;
  1145. // Type parsing complete. Check it
  1146. // ===============================
  1147. if(Type.GetCIMType() == VT_ERROR)
  1148. {
  1149. m_nErrorContext = WBEMMOF_E_UNRECOGNIZED_TYPE;
  1150. return FALSE;
  1151. }
  1152. // If Type resulted in extra qualifiers (CIMTYPE), add them to the prop
  1153. // ===================================================================
  1154. Type.StoreIntoQualifiers(paQualifiers);
  1155. pMethProp->AddArg(pArg);
  1156. return TRUE;
  1157. }
  1158. //***************************************************************************
  1159. //
  1160. // <rest_of_args> ::= TOK_COMMA <arg_decl> <rest_of_args>;
  1161. // <rest_of_args> ::= <>;
  1162. //
  1163. //***************************************************************************
  1164. BOOL CMofParser::rest_of_args(CMethodProperty * pMethProp)
  1165. {
  1166. if(m_nToken == TOK_COMMA)
  1167. {
  1168. NextToken();
  1169. BOOL bRet = arg_decl(pMethProp);
  1170. if(!bRet)
  1171. return FALSE;
  1172. return rest_of_args(pMethProp);
  1173. }
  1174. return TRUE;
  1175. }
  1176. //***************************************************************************
  1177. //
  1178. // <TypeAndName> ::= <type> <opt_ref> TOK_SIMPLE_IDENT;
  1179. //
  1180. //***************************************************************************
  1181. BOOL CMofParser::TypeAndName(MODIFY CMoType& Type, WString &sName)
  1182. {
  1183. if (!type(Type))
  1184. {
  1185. return FALSE;
  1186. }
  1187. // Check if it is actually a reference to a type
  1188. // =============================================
  1189. if (!opt_ref(Type))
  1190. return FALSE;
  1191. // Now get the property name.
  1192. // ==========================
  1193. if (m_nToken != TOK_SIMPLE_IDENT)
  1194. {
  1195. m_nErrorContext = WBEMMOF_E_EXPECTED_PROPERTY_NAME;
  1196. return FALSE;
  1197. }
  1198. sName = m_Lexer.GetText();
  1199. NextToken();
  1200. return TRUE;
  1201. }
  1202. //***************************************************************************
  1203. //
  1204. // <opt_ref> ::= TOK_REF;
  1205. // <opt_ref> ::= <>;
  1206. //
  1207. // Modifies the type object to reflect that this is a ref.
  1208. //
  1209. //***************************************************************************
  1210. // v1.10
  1211. BOOL CMofParser::opt_ref(MODIFY CMoType& Type)
  1212. {
  1213. if (m_nToken == TOK_REF)
  1214. {
  1215. Type.SetIsRef(TRUE);
  1216. Type.SetIsEmbedding(FALSE);
  1217. NextToken();
  1218. }
  1219. else if(Type.GetCIMType() == VT_ERROR) // Probably a class name
  1220. {
  1221. if(Type.IsUnsupportedType())
  1222. {
  1223. m_nErrorContext = WBEMMOF_E_UNSUPPORTED_CIMV22_DATA_TYPE;
  1224. return false;
  1225. }
  1226. Type.SetIsEmbedding(TRUE);
  1227. Type.SetIsRef(FALSE);
  1228. }
  1229. else
  1230. {
  1231. Type.SetIsRef(FALSE);
  1232. Type.SetIsEmbedding(FALSE);
  1233. }
  1234. return TRUE;
  1235. }
  1236. //***************************************************************************
  1237. //
  1238. // <opt_array> ::= TOK_OPEN_BRACKET <opt_array_detail>;
  1239. // <opt_array> ::= <>;
  1240. //
  1241. //
  1242. //***************************************************************************
  1243. // v1.10
  1244. BOOL CMofParser::opt_array(MODIFY CMoType& Type, CMoQualifierArray * paQualifiers)
  1245. {
  1246. if (m_nToken == TOK_OPEN_BRACKET)
  1247. {
  1248. return opt_array_detail(Type, paQualifiers);
  1249. }
  1250. else Type.SetIsArray(FALSE);
  1251. return TRUE;
  1252. }
  1253. //***************************************************************************
  1254. //
  1255. // <opt_array_detail> ::= TOK_UNSIGNED64_NUMERIC_CONST TOK_CLOSE_BRACKET;
  1256. // <opt_array_detail> ::= TOK_CLOSE_BRACKET;
  1257. //
  1258. //***************************************************************************
  1259. BOOL CMofParser::opt_array_detail(MODIFY CMoType& Type, CMoQualifierArray * paQualifiers)
  1260. {
  1261. Type.SetIsArray(TRUE);
  1262. // check if next token is a unsigned constant
  1263. NextToken();
  1264. if(m_nToken == TOK_UNSIGNED64_NUMERIC_CONST)
  1265. {
  1266. unsigned uSuggestedSize = _wtoi(m_Lexer.GetText());
  1267. // If a max suggested size is set, then add a qualifier named max()
  1268. // ================================================================
  1269. CMoQualifier* pNewQualifier = new CMoQualifier(m_pDbg);
  1270. if(pNewQualifier == NULL)
  1271. return FALSE;
  1272. if(FAILED(pNewQualifier->SetQualName(L"MAX")))
  1273. return FALSE;
  1274. VARIANT * pvar = pNewQualifier->GetpVar();
  1275. pvar->vt = VT_I4;
  1276. pvar->lVal = (int)uSuggestedSize;
  1277. if(!paQualifiers->Add(pNewQualifier))
  1278. {
  1279. // Duplicate qualifier
  1280. // ===================
  1281. m_nErrorContext = WBEMMOF_E_DUPLICATE_QUALIFIER;
  1282. return FALSE;
  1283. }
  1284. NextToken();
  1285. }
  1286. m_nErrorContext = WBEMMOF_E_EXPECTED_CLOSE_BRACKET;
  1287. CHECK(TOK_CLOSE_BRACKET);
  1288. return TRUE;
  1289. }
  1290. //***************************************************************************
  1291. //
  1292. // <default_value> ::= <>;
  1293. // <default_value> ::= TOK_EQUALS <initializer>;
  1294. //
  1295. // This function only applies to class declarations.
  1296. //
  1297. //***************************************************************************
  1298. // v1.10
  1299. BOOL CMofParser::default_value(READ_ONLY CMoType& Type,
  1300. OUT CMoValue& Value)
  1301. {
  1302. if (m_nToken == TOK_EQUALS) {
  1303. NextToken();
  1304. // Get the value
  1305. // =============
  1306. return initializer(Type, Value);
  1307. }
  1308. else {
  1309. Value.SetType(Type.GetCIMType());
  1310. VariantClear(&Value.AccessVariant());
  1311. V_VT(&Value.AccessVariant()) = VT_NULL;
  1312. /*
  1313. // HACK!!!! Clear the VARIANT's data field
  1314. // =======================================
  1315. memset(&Value.AccessVariant(), 0, sizeof(VARIANT));
  1316. // No initializer. Set type to whatever we can discern from Type
  1317. // =============================================================
  1318. V_VT(&Value.AccessVariant()) = Type.GetVarType();
  1319. if(V_VT(&Value.AccessVariant()) == VT_BSTR)
  1320. {
  1321. // NULL strings are not well-supported
  1322. // ===================================
  1323. V_BSTR(&Value.AccessVariant()) = SysAllocString(L"");
  1324. }
  1325. */
  1326. }
  1327. return TRUE;
  1328. }
  1329. //***************************************************************************
  1330. //
  1331. // Qualifier parsing
  1332. //
  1333. //***************************************************************************
  1334. //***************************************************************************
  1335. //
  1336. // <qualifier_decl> ::= TOK_OPEN_BRACKET <qualifier_list> TOK_CLOSE_BRACKET;
  1337. // <qualifier_decl> ::= <>;
  1338. //
  1339. //
  1340. //***************************************************************************
  1341. // v1.10
  1342. BOOL CMofParser::qualifier_decl(OUT CMoQualifierArray& aQualifiers, bool bTopLevel, QUALSCOPE qs)
  1343. {
  1344. if (m_nToken == TOK_OPEN_BRACKET) {
  1345. NextToken();
  1346. if (!qualifier_list(aQualifiers, bTopLevel, qs)) {
  1347. return FALSE;
  1348. }
  1349. // Check closing bracket.
  1350. // ======================
  1351. if (m_nToken != TOK_CLOSE_BRACKET) {
  1352. m_nErrorContext = WBEMMOF_E_EXPECTED_CLOSE_BRACKET;
  1353. return FALSE;
  1354. }
  1355. NextToken();
  1356. }
  1357. return TRUE;
  1358. }
  1359. //***************************************************************************
  1360. //
  1361. // <qualifier_list> ::= <qualifier><qualifier_list_rest>;
  1362. //
  1363. //***************************************************************************
  1364. // v1.10
  1365. BOOL CMofParser::qualifier_list(OUT CMoQualifierArray& aQualifiers, bool bTopLevel, QUALSCOPE qs)
  1366. {
  1367. CMoQualifier* pNewQualifier = new CMoQualifier(m_pDbg);
  1368. if(pNewQualifier == NULL)
  1369. return FALSE;
  1370. if (!qualifier(*pNewQualifier, bTopLevel, qs))
  1371. {
  1372. delete pNewQualifier;
  1373. return FALSE;
  1374. }
  1375. // if the qualifier is null, then just ignore it
  1376. VARIANT * pVar = pNewQualifier->GetpVar();
  1377. if(pVar->vt == VT_NULL)
  1378. {
  1379. delete pNewQualifier;
  1380. return qualifier_list_rest(aQualifiers, bTopLevel, qs);
  1381. }
  1382. // Stuff the qualifier into the array
  1383. // ==================================
  1384. if(!aQualifiers.Add(pNewQualifier))
  1385. {
  1386. // Duplicate qualifier
  1387. // ===================
  1388. m_nErrorContext = WBEMMOF_E_DUPLICATE_QUALIFIER;
  1389. return FALSE;
  1390. }
  1391. return qualifier_list_rest(aQualifiers, bTopLevel, qs);
  1392. }
  1393. //***************************************************************************
  1394. //
  1395. // <qualifier_list_rest> ::= TOK_COMMA <qualifier><qualifier_list_rest>;
  1396. // <qualifier_list_rest> ::= <>;
  1397. //
  1398. //***************************************************************************
  1399. // v1.10
  1400. BOOL CMofParser::qualifier_list_rest(MODIFY CMoQualifierArray& aQualifiers, bool bTopLevel, QUALSCOPE qs)
  1401. {
  1402. while (m_nToken == TOK_COMMA)
  1403. {
  1404. NextToken();
  1405. CMoQualifier* pQualifier = new CMoQualifier(m_pDbg);
  1406. if(pQualifier == NULL)
  1407. return FALSE;
  1408. if (!qualifier(*pQualifier, bTopLevel, qs))
  1409. {
  1410. delete pQualifier;
  1411. return FALSE;
  1412. }
  1413. // if the qualifier is null, then just ignore it
  1414. VARIANT * pVar = pQualifier->GetpVar();
  1415. if(pVar->vt == VT_NULL)
  1416. {
  1417. delete pQualifier;
  1418. }
  1419. else if(!aQualifiers.Add(pQualifier))
  1420. {
  1421. // Duplicate qualifier
  1422. // ===================
  1423. m_nErrorContext = WBEMMOF_E_DUPLICATE_QUALIFIER;
  1424. return FALSE;
  1425. }
  1426. }
  1427. return TRUE;
  1428. }
  1429. //***************************************************************************
  1430. //
  1431. // <qualifier> ::= TOK_SIMPLE_IDENT <qualifier_parms>;
  1432. //
  1433. //***************************************************************************
  1434. // v1.10
  1435. BOOL CMofParser::qualifier(OUT CMoQualifier& Qualifier, bool bTopLevel, QUALSCOPE qs)
  1436. {
  1437. m_nErrorContext = WBEMMOF_E_EXPECTED_QUALIFIER_NAME;
  1438. if (m_nToken != TOK_SIMPLE_IDENT && m_nToken != TOK_AMENDMENT)
  1439. return FALSE;
  1440. // Check that this qualifier is not illegal in a MOF
  1441. // =================================================
  1442. if(!wbem_wcsicmp(m_Lexer.GetText(), L"CIMTYPE"))
  1443. {
  1444. m_nErrorContext = WBEMMOF_E_CIMTYPE_QUALIFIER;
  1445. return FALSE;
  1446. }
  1447. if(FAILED(Qualifier.SetQualName(m_Lexer.GetText())))
  1448. {
  1449. m_nErrorContext = WBEM_E_OUT_OF_MEMORY;
  1450. return FALSE;
  1451. }
  1452. NextToken();
  1453. if (!qualifier_parm(Qualifier, bTopLevel, qs))
  1454. {
  1455. return FALSE;
  1456. }
  1457. return TRUE;
  1458. }
  1459. //***************************************************************************
  1460. //
  1461. // <qualifier_parm> ::= <flavor_param>;
  1462. // <qualifier_parm> ::= TOK_OPEN_PAREN <qualifier_initializer_list> TOK_CLOSE_PAREN <flavor_param>;
  1463. //
  1464. //***************************************************************************
  1465. // v1.10
  1466. BOOL CMofParser::qualifier_parm(OUT CMoQualifier& Qualifier, bool bTopLevel, QUALSCOPE qs)
  1467. {
  1468. HRESULT hr;
  1469. CMoValue & Value = Qualifier.AccessValue();
  1470. if (m_nToken == TOK_OPEN_PAREN)
  1471. {
  1472. NextToken();
  1473. // Read the parameter.
  1474. // ====================
  1475. CMoType Type(m_pDbg);
  1476. if (!simple_initializer(Type, Value, true))
  1477. return FALSE;
  1478. m_nErrorContext = WBEMMOF_E_EXPECTED_CLOSE_PAREN;
  1479. CHECK(TOK_CLOSE_PAREN);
  1480. }
  1481. else if (m_nToken == TOK_OPEN_BRACE)
  1482. {
  1483. NextToken();
  1484. // Read the parameters.
  1485. // ====================
  1486. if (!qualifier_initializer_list(Value))
  1487. return FALSE;
  1488. m_nErrorContext = WBEMMOF_E_EXPECTED_CLOSE_BRACE;
  1489. CHECK(TOK_CLOSE_BRACE);
  1490. }
  1491. else
  1492. {
  1493. // Boolean qualifier: set to TRUE
  1494. // ==============================
  1495. V_VT(&Value.AccessVariant()) = VT_BOOL;
  1496. V_BOOL(&Value.AccessVariant()) = VARIANT_TRUE;
  1497. Qualifier.SetUsingDefaultValue(true);
  1498. }
  1499. // Get the default flavor for this qualifier
  1500. // =========================================
  1501. hr = m_Output.SetDefaultFlavor(Qualifier, bTopLevel, qs, m_State);
  1502. if(FAILED(hr))
  1503. return FALSE;
  1504. return flavor_param(Qualifier, false);
  1505. }
  1506. //****************************************************************************
  1507. //
  1508. // qualifier_initializer_list ::= initializer_list
  1509. //
  1510. // Their syntax is the same, but the storage model is different.
  1511. //
  1512. //***************************************************************************
  1513. BOOL CMofParser::qualifier_initializer_list(OUT CMoValue& Value)
  1514. {
  1515. // We don't know the type, so create an initialized one
  1516. // ====================================================
  1517. CMoType Type(m_pDbg);
  1518. if(!initializer_list(Type, Value, true))
  1519. return FALSE;
  1520. return TRUE;
  1521. }
  1522. //***************************************************************************
  1523. //
  1524. // Basic low-level productions for types, idents, etc.
  1525. //***************************************************************************
  1526. //
  1527. // <type> ::= TOK_SIMPLE_IDENT;
  1528. //
  1529. //***************************************************************************
  1530. // v1.10
  1531. BOOL CMofParser::type(OUT CMoType& Type)
  1532. {
  1533. m_nErrorContext = WBEMMOF_E_EXPECTED_TYPE_IDENTIFIER;
  1534. if (!sys_or_regular())
  1535. return FALSE;
  1536. HRESULT hr = Type.SetTitle(m_Lexer.GetText());
  1537. if(FAILED(hr))
  1538. {
  1539. m_nErrorContext = hr;
  1540. return FALSE;
  1541. }
  1542. NextToken();
  1543. return TRUE;
  1544. }
  1545. //***************************************************************************
  1546. //
  1547. // <const_value> ::= TOK_LPSTR;
  1548. // <const_value> ::= TOK_LPWSTR;
  1549. // <const_value> ::= TOK_SIGNED64_NUMERIC_CONST;
  1550. // <const_value> ::= TOK_UNSIGNED64_NUMERIC_CONST;
  1551. // <const_value> ::= TOK_UUID;
  1552. // <const_value> ::= TOK_KEYWORD_NULL;
  1553. //
  1554. //***************************************************************************
  1555. // 1.10
  1556. BOOL CMofParser::const_value(MODIFY CMoType& Type, OUT VARIANT& varValue, bool bQualifier)
  1557. {
  1558. varValue.lVal = 0;
  1559. VARIANT var;
  1560. SCODE sc;
  1561. m_nErrorContext = WBEMMOF_E_TYPE_MISMATCH;
  1562. __int64 iTemp;
  1563. switch (m_nToken)
  1564. {
  1565. case TOK_PLUS:
  1566. // Just ignore '+'
  1567. NextToken();
  1568. if (m_nToken != TOK_SIGNED64_NUMERIC_CONST &&
  1569. m_nToken != TOK_UNSIGNED64_NUMERIC_CONST)
  1570. return FALSE;
  1571. case TOK_SIGNED64_NUMERIC_CONST:
  1572. case TOK_UNSIGNED64_NUMERIC_CONST:
  1573. WCHAR wcTemp[30];
  1574. iTemp = m_Lexer.GetLastInt();
  1575. if(m_nToken == TOK_SIGNED64_NUMERIC_CONST)
  1576. StringCchPrintfW(wcTemp, 30, L"%I64d", m_Lexer.GetLastInt());
  1577. else
  1578. StringCchPrintfW(wcTemp, 30, L"%I64u", m_Lexer.GetLastInt());
  1579. var.vt = VT_BSTR;
  1580. var.bstrVal = SysAllocString(wcTemp);
  1581. if(var.bstrVal == NULL)
  1582. {
  1583. m_nErrorContext = WBEM_E_OUT_OF_MEMORY;
  1584. return FALSE;
  1585. }
  1586. sc = WbemVariantChangeType(&varValue, &var, VT_I4);
  1587. VariantClear(&var);
  1588. if(sc != S_OK)
  1589. {
  1590. varValue.vt = VT_BSTR;
  1591. varValue.bstrVal = SysAllocString(wcTemp);
  1592. if(varValue.bstrVal == NULL)
  1593. {
  1594. m_nErrorContext = WBEM_E_OUT_OF_MEMORY;
  1595. return FALSE;
  1596. }
  1597. sc = S_OK;
  1598. }
  1599. break;
  1600. case TOK_KEYWORD_NULL:
  1601. V_VT(&varValue) = VT_NULL;
  1602. // if(bQualifier)
  1603. // {
  1604. // m_nErrorContext = WBEMMOF_E_UNSUPPORTED_CIMV22_QUAL_VALUE;
  1605. // return FALSE;
  1606. // }
  1607. break;
  1608. case TOK_FLOAT_VALUE:
  1609. // if(bQualifier)
  1610. // {
  1611. var.vt = VT_BSTR;
  1612. var.bstrVal = SysAllocString(m_Lexer.GetText());
  1613. if(var.bstrVal == NULL)
  1614. {
  1615. m_nErrorContext = WBEM_E_OUT_OF_MEMORY;
  1616. return FALSE;
  1617. }
  1618. sc = VariantChangeTypeEx(&varValue, &var, 0x409, 0, VT_R8);
  1619. VariantClear(&var);
  1620. if(sc != S_OK)
  1621. return FALSE;
  1622. break;
  1623. // } //intentional lack of a break!!!!
  1624. case TOK_LPWSTR:
  1625. case TOK_UUID:
  1626. V_VT(&varValue) = VT_BSTR;
  1627. V_BSTR(&varValue) = SysAllocString(m_Lexer.GetText());
  1628. if(varValue.bstrVal == NULL)
  1629. {
  1630. m_nErrorContext = WBEM_E_OUT_OF_MEMORY;
  1631. return FALSE;
  1632. }
  1633. break;
  1634. case TOK_WCHAR:
  1635. varValue.vt = VT_I2;
  1636. varValue.iVal = (short)m_Lexer.GetLastInt();
  1637. if(bQualifier)
  1638. {
  1639. m_nErrorContext = WBEMMOF_E_UNSUPPORTED_CIMV22_QUAL_VALUE;
  1640. return FALSE;
  1641. }
  1642. break;
  1643. case TOK_TRUE:
  1644. V_VT(&varValue) = VT_BOOL;
  1645. V_BOOL(&varValue) = VARIANT_TRUE;
  1646. break;
  1647. case TOK_FALSE:
  1648. V_VT(&varValue) = VT_BOOL;
  1649. V_BOOL(&varValue) = VARIANT_FALSE;
  1650. break;
  1651. default:
  1652. m_nErrorContext = WBEMMOF_E_ILLEGAL_CONSTANT_VALUE;
  1653. return FALSE;
  1654. }
  1655. NextToken();
  1656. return TRUE;
  1657. }
  1658. //***************************************************************************
  1659. //
  1660. // <initializer> ::= <simple_initializer>;
  1661. // <initializer> ::= TOK_EXTERNAL;
  1662. // <initializer> ::= TOK_OPEN_BRACE <initializer_list> TOK_CLOSE_BRACE;
  1663. //
  1664. //***************************************************************************
  1665. // v1.10
  1666. BOOL CMofParser::initializer(MODIFY CMoType& Type, OUT CMoValue& Value)
  1667. {
  1668. // A complex initializer list.
  1669. // ===========================
  1670. if (m_nToken == TOK_OPEN_BRACE)
  1671. {
  1672. NextToken();
  1673. if(!initializer_list(Type, Value, false))
  1674. {
  1675. return FALSE;
  1676. }
  1677. m_nErrorContext = WBEMMOF_E_EXPECTED_CLOSE_BRACE;
  1678. CHECK(TOK_CLOSE_BRACE);
  1679. }
  1680. // If the syntax says "prop = external" for MO Provided types...
  1681. // =============================================================
  1682. else if (m_nToken == TOK_EXTERNAL || m_nToken == TOK_KEYWORD_NULL)
  1683. {
  1684. Value.SetType(Type.GetCIMType());
  1685. V_VT(&Value.AccessVariant()) = VT_NULL;
  1686. NextToken();
  1687. return TRUE;
  1688. }
  1689. else if (!simple_initializer(Type, Value, false))
  1690. {
  1691. return FALSE;
  1692. }
  1693. return TRUE;
  1694. }
  1695. //***************************************************************************
  1696. //
  1697. // <simple_initializer> ::= <const_value>;
  1698. // <simple_initializer> ::= <alias>;
  1699. // <simple_initializer> ::= <instance_decl>;
  1700. //
  1701. // Semantic stack actions:
  1702. // On TRUE returns an MCST_CONST_VALUE token, an MCST_ALIAS, or
  1703. // an MCST_KEYREF token, depending on which branch is taken.
  1704. //
  1705. //***************************************************************************
  1706. // v1.10
  1707. BOOL CMofParser::simple_initializer(MODIFY CMoType& Type,
  1708. OUT CMoValue& Value, bool bQualifier)
  1709. {
  1710. if (m_nToken == TOK_DOLLAR_SIGN)
  1711. {
  1712. // It's an alias. Check the type
  1713. // =============================
  1714. if(Type.IsDefined())
  1715. {
  1716. if(!Type.IsRef())
  1717. {
  1718. m_nErrorContext = WBEMMOF_E_UNEXPECTED_ALIAS;
  1719. return FALSE;
  1720. }
  1721. }
  1722. else
  1723. {
  1724. // Type unknown at start-up. Set to object ref now
  1725. // ===============================================
  1726. HRESULT hr = Type.SetTitle(L"object");
  1727. if(FAILED(hr))
  1728. {
  1729. m_nErrorContext = hr;
  1730. return FALSE;
  1731. }
  1732. Type.SetIsRef(TRUE);
  1733. }
  1734. NextToken(true);
  1735. m_nErrorContext = WBEMMOF_E_EXPECTED_ALIAS_NAME;
  1736. if (m_nToken != TOK_SIMPLE_IDENT)
  1737. return FALSE;
  1738. AddAliasReplaceValue(Value, m_Lexer.GetText());
  1739. NextToken();
  1740. return TRUE;
  1741. }
  1742. if (m_nToken == TOK_INSTANCE || m_nToken == TOK_OPEN_BRACKET || m_nToken == TOK_CLASS )
  1743. {
  1744. VARIANT & var = Value.AccessVariant();
  1745. CMoQualifierArray* paQualifiers = new CMoQualifierArray(m_pDbg);
  1746. if (paQualifiers == NULL || !qualifier_decl(*paQualifiers, false, CLASSINST_SCOPE))
  1747. return FALSE;
  1748. BOOL bClass = (m_nToken == TOK_CLASS);
  1749. if(bClass)
  1750. return class_decl(paQualifiers, &var, NULL);
  1751. else
  1752. return instance_decl(paQualifiers, &var, NULL);
  1753. }
  1754. else
  1755. return const_value(Type, Value.AccessVariant(),bQualifier);
  1756. }
  1757. //***************************************************************************
  1758. //
  1759. // <initializer_list> ::= <simple_initializer><init_list_2>;
  1760. //
  1761. //***************************************************************************
  1762. // v1.10
  1763. BOOL CMofParser::initializer_list(MODIFY CMoType& Type,
  1764. OUT CMoValue& Value, bool bQualifier)
  1765. {
  1766. HRESULT hres;
  1767. // Check if the type is compatible with array
  1768. // ==========================================
  1769. if(Type.IsDefined())
  1770. {
  1771. if(!Type.IsArray())
  1772. {
  1773. m_nErrorContext = WBEMMOF_E_UNEXPECTED_ARRAY_INIT;
  1774. return FALSE;
  1775. }
  1776. }
  1777. // Get the initializers.
  1778. // =====================
  1779. CPtrArray aValues; // CMoValue*
  1780. BOOL bFirst = TRUE;
  1781. do
  1782. {
  1783. // Allow for the empty array case
  1784. if(m_nToken == TOK_CLOSE_BRACE && bFirst)
  1785. break;
  1786. // Skip the comma, unless it is the first element
  1787. // ==============================================
  1788. if(!bFirst) NextToken();
  1789. // Get single initializer
  1790. // ======================
  1791. CMoValue* pSimpleValue = new CMoValue(m_pDbg);
  1792. if(pSimpleValue == NULL || !simple_initializer(Type, *pSimpleValue, bQualifier))
  1793. return FALSE;
  1794. // Add it to the list
  1795. // ==================
  1796. aValues.Add(pSimpleValue);
  1797. bFirst = FALSE;
  1798. }
  1799. while(m_nToken == TOK_COMMA);
  1800. // Now, stuff them into a SAFEARRAY and register their aliases
  1801. // ===========================================================
  1802. // Create the SAFEARRAY of appropriate type
  1803. // ========================================
  1804. // start by figuring the type. If all the entries are of the same
  1805. // type, then use it. If there is a mix, use BSTR.
  1806. VARTYPE vt = VT_BSTR;
  1807. if(aValues.GetSize() > 0)
  1808. {
  1809. VARIANT& varFirst = ((CMoValue*)aValues[0])->AccessVariant();
  1810. vt = V_VT(&varFirst); // normally this is what is set!
  1811. for(int ii = 1; ii < aValues.GetSize(); ii++)
  1812. {
  1813. VARIANT& varCur = ((CMoValue*)aValues[ii])->AccessVariant();
  1814. if(vt != V_VT(&varCur))
  1815. {
  1816. // If we just have a mix of i2 and i4, go for i4
  1817. if((vt == VT_I4 || vt == VT_I2) &&
  1818. (V_VT(&varCur) == VT_I4 || V_VT(&varCur) == VT_I2) )
  1819. vt = VT_I4;
  1820. else
  1821. {
  1822. vt = VT_BSTR;
  1823. break;
  1824. }
  1825. }
  1826. }
  1827. }
  1828. SAFEARRAYBOUND aBounds[1];
  1829. aBounds[0].lLbound = 0;
  1830. aBounds[0].cElements = aValues.GetSize();
  1831. //SAFEARRAY* pArray = SafeArrayCreateVector(vt, 0, aValues.GetSize());
  1832. #ifdef _WIN64
  1833. VARTYPE vtTemp = (vt == VT_EMBEDDED_OBJECT) ? VT_I8 : vt;
  1834. #else
  1835. VARTYPE vtTemp = (vt == VT_EMBEDDED_OBJECT) ? VT_I4 : vt;
  1836. #endif
  1837. SAFEARRAY* pArray = SafeArrayCreate(vtTemp, 1, aBounds);
  1838. // Stuff the individual data pieces
  1839. // ================================
  1840. for(int nIndex = 0; nIndex < aValues.GetSize(); nIndex++)
  1841. {
  1842. CMoValue* pSimpleValue = (CMoValue*)aValues[nIndex];
  1843. VARIANT& varItem = pSimpleValue->AccessVariant();
  1844. // Cast it to the array type, just in case
  1845. // =======================================
  1846. if((vt & ~VT_ARRAY) != VT_EMBEDDED_OBJECT)
  1847. {
  1848. hres = WbemVariantChangeType(&varItem, &varItem, vt);
  1849. if(FAILED(hres)) return FALSE;
  1850. if(varItem.vt == VT_NULL)
  1851. varItem.llVal = 0;
  1852. }
  1853. if(vt == VT_BSTR)
  1854. {
  1855. hres = SafeArrayPutElement(pArray, (long*)&nIndex, varItem.bstrVal);
  1856. }
  1857. else if (vt == VT_EMBEDDED_OBJECT)
  1858. {
  1859. if(varItem.vt == VT_NULL)
  1860. {
  1861. m_nErrorContext = WBEMMOF_E_NULL_ARRAY_ELEM;
  1862. return FALSE;
  1863. }
  1864. hres = SafeArrayPutElement(pArray, (long*)&nIndex, &varItem.punkVal);
  1865. if(FAILED(hres))
  1866. return FALSE;
  1867. }
  1868. else
  1869. {
  1870. hres = SafeArrayPutElement(pArray, (long*)&nIndex, &V_I1(&varItem));
  1871. if(FAILED(hres))
  1872. return FALSE;
  1873. }
  1874. // Transfer any aliases to the containing value
  1875. // ============================================
  1876. for(int i = 0; i < pSimpleValue->GetNumAliases(); i++)
  1877. {
  1878. LPWSTR wszAlias;
  1879. wszAlias=NULL;
  1880. int nDummy; // SimpleValue cannot contain an array!
  1881. if(pSimpleValue->GetAlias(i, wszAlias, nDummy))
  1882. {
  1883. hres = Value.AddAlias(wszAlias, nIndex);
  1884. if(FAILED(hres))
  1885. {
  1886. m_nErrorContext = hres;
  1887. return FALSE;
  1888. }
  1889. }
  1890. }
  1891. // Since VT_EMBEDDED_OBJECT is actually a pointer to a CMObject, dont
  1892. // delete that since it will be needed later on.
  1893. if((vt & ~VT_ARRAY) == VT_EMBEDDED_OBJECT)
  1894. {
  1895. VARIANT & Var = pSimpleValue->AccessVariant();
  1896. Var.vt = VT_I4;
  1897. }
  1898. delete pSimpleValue;
  1899. }
  1900. // Store that array in the VARIANT
  1901. // ===============================
  1902. V_VT(&Value.AccessVariant()) = VT_ARRAY | vt;
  1903. V_ARRAY(&Value.AccessVariant()) = pArray;
  1904. return TRUE;
  1905. }
  1906. //***************************************************************************
  1907. //
  1908. // Instances.
  1909. //
  1910. //***************************************************************************
  1911. //***************************************************************************
  1912. //
  1913. // <instance_decl> ::=
  1914. // TOK_INSTANCE TOK_OF
  1915. // <type>
  1916. // <as_alias>
  1917. // TOK_OPEN_BRACE
  1918. // <prop_init_list>
  1919. // TOK_CLOSE_BRACE;
  1920. //
  1921. // This can be called for both top level instances and embedded instances.
  1922. // In the top level case, the pVar will be set to null and the object will
  1923. // be added to the ouput. In the embedded case, the pVar will be used to
  1924. // point to the object.
  1925. //***************************************************************************
  1926. BOOL CMofParser::instance_decl(ACQUIRE CMoQualifierArray* paQualifiers, VARIANT * pVar, ParseState * pQualPosition)
  1927. {
  1928. BOOL bRetVal = FALSE; // Default
  1929. BSTR strClassName;
  1930. // Begin syntax check.
  1931. // ===================
  1932. m_nErrorContext = WBEMMOF_E_INVALID_INSTANCE_DECLARATION;
  1933. int nFirstLine = m_Lexer.GetLineNumber();
  1934. if (m_nToken != TOK_INSTANCE)
  1935. {
  1936. delete paQualifiers;
  1937. return FALSE;
  1938. }
  1939. NextToken();
  1940. if(m_nToken != TOK_OF)
  1941. {
  1942. delete paQualifiers;
  1943. return FALSE;
  1944. }
  1945. NextToken();
  1946. // Get the class name.
  1947. // ====================
  1948. if (!sys_or_regular())
  1949. {
  1950. m_nErrorContext = WBEMMOF_E_EXPECTED_CLASS_NAME;
  1951. delete paQualifiers;
  1952. return FALSE;
  1953. }
  1954. strClassName = SysAllocString((LPWSTR)m_Lexer.GetText());
  1955. if(strClassName == NULL)
  1956. {
  1957. m_nErrorContext = WBEM_E_OUT_OF_MEMORY;
  1958. return FALSE;
  1959. }
  1960. NextToken();
  1961. // Create an instance of this class
  1962. // ================================
  1963. CMoInstance* pObject = new CMoInstance(strClassName, m_pDbg);
  1964. if(pObject == NULL)
  1965. {
  1966. m_nErrorContext = WBEM_E_OUT_OF_MEMORY;
  1967. return FALSE;
  1968. }
  1969. if(pObject->IsOK() == false)
  1970. goto Exit;
  1971. HRESULT hr2 = pObject->SetNamespace(m_wszNamespace);
  1972. if(FAILED(hr2))
  1973. {
  1974. m_nErrorContext = hr2;
  1975. goto Exit;
  1976. }
  1977. pObject->SetOtherDefaults(GetClassFlags(), GetInstanceFlags());
  1978. SysFreeString(strClassName);
  1979. // Apply qualifiers (already parsed)
  1980. // =================================
  1981. pObject->SetQualifiers(paQualifiers);
  1982. // Check for an alias. Aliases are only allowed for top level instances.
  1983. // ======================================================================
  1984. if(m_nToken == TOK_AS && pVar)
  1985. {
  1986. m_nErrorContext = WBEMMOF_E_ALIASES_IN_EMBEDDED;
  1987. delete paQualifiers;
  1988. return FALSE;
  1989. }
  1990. LPWSTR wszAlias = NULL;
  1991. if (!as_alias(wszAlias))
  1992. goto Exit;
  1993. if(wszAlias)
  1994. {
  1995. HRESULT hr2 = pObject->SetAlias(wszAlias);
  1996. delete [] wszAlias;
  1997. if(FAILED(hr2))
  1998. {
  1999. m_nErrorContext = hr2;
  2000. goto Exit;
  2001. }
  2002. }
  2003. // Check for the open brace.
  2004. // =========================
  2005. m_nErrorContext = WBEMMOF_E_EXPECTED_OPEN_BRACE;
  2006. if (m_nToken != TOK_OPEN_BRACE)
  2007. goto Exit;
  2008. // Now get the list properties.
  2009. // ============================
  2010. GetParserPosition(pObject->GetDataState());
  2011. if(pQualPosition)
  2012. {
  2013. pObject->SetQualState(pQualPosition);
  2014. }
  2015. NextToken();
  2016. if (!prop_init_list(pObject))
  2017. goto Exit;
  2018. // Final close brace.
  2019. // ==================
  2020. m_nErrorContext = WBEMMOF_E_EXPECTED_CLOSE_BRACE;
  2021. if (m_nToken != TOK_CLOSE_BRACE)
  2022. goto Exit;
  2023. hr2 = pObject->SetLineRange(nFirstLine, m_Lexer.GetLineNumber(), m_Lexer.GetErrorFile());
  2024. if(FAILED(hr2))
  2025. {
  2026. m_nErrorContext = hr2;
  2027. goto Exit;
  2028. }
  2029. NextToken();
  2030. // We have now syntactially recognized an instance
  2031. // but done no context-sensitive verification. This is
  2032. // deferred to whatever module is using the parser output.
  2033. // =======================================================
  2034. if(pVar)
  2035. {
  2036. pVar->vt = VT_EMBEDDED_OBJECT;
  2037. pVar->punkVal = (IUnknown *)pObject;
  2038. }
  2039. else
  2040. {
  2041. pObject->Deflate(false);
  2042. m_Output.AddObject(pObject);
  2043. }
  2044. return TRUE;
  2045. Exit:
  2046. delete pObject;
  2047. return FALSE;
  2048. }
  2049. //***************************************************************************
  2050. //
  2051. // <as_alias> ::= TOK_AS <alias>;
  2052. // <as_alias> ::= <>;
  2053. //
  2054. //***************************************************************************
  2055. BOOL CMofParser::as_alias(OUT LPWSTR& wszAlias)
  2056. {
  2057. if (m_nToken == TOK_AS)
  2058. {
  2059. NextToken();
  2060. return alias(wszAlias);
  2061. }
  2062. wszAlias = NULL;
  2063. return TRUE;
  2064. }
  2065. //***************************************************************************
  2066. //
  2067. // <alias> ::= TOK_DOLLAR_SIGN TOK_SIMPLE_IDENT;
  2068. //
  2069. //
  2070. //***************************************************************************
  2071. BOOL CMofParser::alias(OUT LPWSTR& wszAlias)
  2072. {
  2073. if (m_nToken != TOK_DOLLAR_SIGN)
  2074. {
  2075. m_nErrorContext = WBEMMOF_E_EXPECTED_DOLLAR;
  2076. return FALSE;
  2077. }
  2078. NextToken(true);
  2079. if (m_nToken != TOK_SIMPLE_IDENT)
  2080. {
  2081. m_nErrorContext = WBEMMOF_E_EXPECTED_ALIAS_NAME;
  2082. return FALSE;
  2083. }
  2084. // Set the alias in the object
  2085. // ===========================
  2086. wszAlias = Macro_CloneStr(m_Lexer.GetText());
  2087. if(wszAlias == NULL)
  2088. {
  2089. m_nErrorContext = WBEM_E_OUT_OF_MEMORY;
  2090. return FALSE;
  2091. }
  2092. if(m_Output.IsAliasInUse(wszAlias))
  2093. {
  2094. m_nErrorContext = WBEMMOF_E_MULTIPLE_ALIASES;
  2095. return FALSE;
  2096. }
  2097. NextToken();
  2098. return TRUE;
  2099. }
  2100. //***************************************************************************
  2101. //
  2102. // <prop_init_list> ::= <prop_init><prop_init_list>;
  2103. // <prop_init_list> ::= <>;
  2104. //
  2105. //***************************************************************************
  2106. // v1.10
  2107. BOOL CMofParser::prop_init_list(MODIFY CMObject* pObject)
  2108. {
  2109. while (m_nToken == TOK_OPEN_BRACKET ||
  2110. m_nToken == TOK_SIMPLE_IDENT )
  2111. {
  2112. CValueProperty* pProp = new CValueProperty(NULL, m_pDbg);
  2113. if (pProp == NULL || !prop_init(*pProp))
  2114. return FALSE;
  2115. if(!pObject->AddProperty(pProp))
  2116. {
  2117. // Duplicate property
  2118. // ==================
  2119. m_nErrorContext = WBEMMOF_E_DUPLICATE_PROPERTY;
  2120. return FALSE;
  2121. }
  2122. }
  2123. return TRUE;
  2124. }
  2125. //***************************************************************************
  2126. //
  2127. // <prop_init> ::= <qualifier_decl> <ident> TOK_EQUALS <initializer> TOK_SEMI;
  2128. //
  2129. //***************************************************************************
  2130. BOOL CMofParser::prop_init(OUT CMoProperty& Prop)
  2131. {
  2132. // Get the qualifiers
  2133. // ==================
  2134. CMoQualifierArray* paQualifiers = new CMoQualifierArray(m_pDbg);
  2135. if (paQualifiers == NULL || !qualifier_decl(*paQualifiers,false, PROPMETH_SCOPE))
  2136. return FALSE;
  2137. Prop.SetQualifiers(paQualifiers); // acquired
  2138. // Now get the property name.
  2139. // ==========================
  2140. if (m_nToken != TOK_SIMPLE_IDENT)
  2141. {
  2142. m_nErrorContext = WBEMMOF_E_EXPECTED_PROPERTY_NAME;
  2143. return FALSE;
  2144. }
  2145. if(FAILED(Prop.SetPropName((wchar_t *) m_Lexer.GetText())))
  2146. return FALSE;
  2147. NextToken();
  2148. // Get the default value and assign it to the property.
  2149. // ====================================================
  2150. CMoType Type(m_pDbg);
  2151. if (!default_value(Type, Prop.AccessValue()))
  2152. return FALSE;
  2153. // Check closing semicolon.
  2154. // ========================
  2155. m_nErrorContext = WBEMMOF_E_EXPECTED_SEMI;
  2156. if (m_nToken != TOK_SEMI)
  2157. return FALSE;
  2158. NextToken();
  2159. if(m_bDoScopeCheck && (FALSE == CheckScopes(IN_PROPERTY, paQualifiers, &Prop)))
  2160. return FALSE;
  2161. return TRUE;
  2162. }
  2163. //***************************************************************************
  2164. //
  2165. // <flavor_param> ::= TOK_COLON TOK_OPEN_PAREN <flavor_list> TOK_CLOSE_PAREN;
  2166. // <flavor_param> ::= <>;
  2167. //
  2168. //***************************************************************************
  2169. BOOL CMofParser::flavor_param(OUT CMoQualifier& Qual, bool bDefaultQual)
  2170. {
  2171. if(m_nToken == TOK_COLON)
  2172. {
  2173. NextToken();
  2174. if(!flavor_list(Qual))
  2175. return FALSE;
  2176. }
  2177. return TRUE;
  2178. }
  2179. //***************************************************************************
  2180. //
  2181. // <flavor_list> ::= <flavor_value> <flavor_list_rest>;
  2182. //
  2183. //***************************************************************************
  2184. BOOL CMofParser::flavor_list(OUT CMoQualifier& Qual)
  2185. {
  2186. if(!flavor_value(Qual))
  2187. return FALSE;
  2188. else
  2189. return flavor_list_rest(Qual);
  2190. }
  2191. //***************************************************************************
  2192. //
  2193. // <flavor_list_rest> ::= <FLAVOR_VALUE> <flavor_list_rest>;
  2194. // <flavor_list_rest> ::= <>;
  2195. //
  2196. //***************************************************************************
  2197. BOOL CMofParser::flavor_list_rest(CMoQualifier& Qual)
  2198. {
  2199. if(m_nToken == TOK_COMMA || m_nToken == TOK_CLOSE_BRACKET || m_nToken == TOK_SEMI)
  2200. return TRUE;
  2201. else
  2202. {
  2203. if(!flavor_value(Qual))
  2204. return FALSE;
  2205. return flavor_list_rest(Qual);
  2206. }
  2207. return TRUE;
  2208. }
  2209. //***************************************************************************
  2210. //
  2211. // <def_flavor_list> ::= <flavor_value> <flavor_list_rest>;
  2212. //
  2213. //***************************************************************************
  2214. BOOL CMofParser::def_flavor_list(OUT CMoQualifier& Qual)
  2215. {
  2216. if(!flavor_value(Qual))
  2217. return FALSE;
  2218. else
  2219. return def_flavor_list_rest(Qual);
  2220. }
  2221. //***************************************************************************
  2222. //
  2223. // <def_flavor_list_rest> ::= <FLAVOR_VALUE> <def_flavor_list_rest>;
  2224. // <def_flavor_list_rest> ::= <>;
  2225. //
  2226. //***************************************************************************
  2227. BOOL CMofParser::def_flavor_list_rest(CMoQualifier& Qual)
  2228. {
  2229. if(m_nToken == TOK_CLOSE_PAREN)
  2230. return TRUE;
  2231. else
  2232. {
  2233. if(m_nToken != TOK_COMMA)
  2234. return FALSE;
  2235. NextToken();
  2236. if(!flavor_value(Qual))
  2237. return FALSE;
  2238. return def_flavor_list_rest(Qual);
  2239. }
  2240. return TRUE;
  2241. }
  2242. //***************************************************************************
  2243. //
  2244. // <flavor_value> ::= TOK_TOINSTANCE;
  2245. // <flavor_value> ::= TOK_TOSUBCLASS;
  2246. // <flavor_value> ::= TOK_ENABLEOVERRIDE;
  2247. // <flavor_value> ::= TOK_DISABLEOVERRIDE;
  2248. // <flavor_value> ::= TOK_NOTTOINSTANCE;
  2249. // <flavor_value> ::= TOK_AMENDED;
  2250. // <flavor_value> ::= TOK_NOTTOSUBCLASS;
  2251. // <flavor_value> ::= TOK_RESTRICTED;
  2252. //
  2253. //***************************************************************************
  2254. BOOL CMofParser::flavor_value(CMoQualifier& Qual)
  2255. {
  2256. SCODE sc = Qual.SetFlag(m_nToken, m_Lexer.GetText());
  2257. if(sc != S_OK)
  2258. {
  2259. m_nErrorContext = sc;
  2260. return FALSE;
  2261. }
  2262. NextToken();
  2263. return TRUE;
  2264. }
  2265. //***************************************************************************
  2266. //
  2267. // <qualifier_default> ::= TOK_QUALIFIER TOK_SIMPLE_IDENT TOK_COLON <finish_qualifier_default>;
  2268. //
  2269. //***************************************************************************
  2270. BOOL CMofParser::qualifier_default()
  2271. {
  2272. // Verify header
  2273. // =============
  2274. CHECK(TOK_QUALIFIER);
  2275. m_nErrorContext = WBEMMOF_E_EXPECTED_QUALIFIER_NAME;
  2276. if(m_nToken != TOK_SIMPLE_IDENT)
  2277. return FALSE;
  2278. // Store qualifier name
  2279. // ====================
  2280. CMoQualifier* pDefault = new CMoQualifier(m_pDbg);
  2281. if(pDefault == NULL)
  2282. return FALSE;
  2283. if(FAILED(pDefault->SetQualName(m_Lexer.GetText())))
  2284. {
  2285. delete pDefault;
  2286. return FALSE;
  2287. }
  2288. NextToken();
  2289. // check for chase where its just Qualifier Name ;
  2290. if(m_nToken == TOK_SEMI)
  2291. {
  2292. m_Output.SetQualifierDefault(pDefault);
  2293. NextToken();
  2294. return TRUE;
  2295. }
  2296. // Make sure there is a colon
  2297. if(m_nToken != TOK_COLON)
  2298. {
  2299. m_nErrorContext = WBEMMOF_E_EXPECTED_SEMI;
  2300. delete pDefault;
  2301. return FALSE;
  2302. }
  2303. // Get the flavor
  2304. // ==============
  2305. if(!finish_qualifier_default(*pDefault))
  2306. {
  2307. delete pDefault;
  2308. return FALSE;
  2309. }
  2310. m_nErrorContext = WBEMMOF_E_EXPECTED_SEMI;
  2311. if(m_nToken != TOK_SEMI)
  2312. {
  2313. delete pDefault;
  2314. return FALSE;
  2315. }
  2316. NextToken();
  2317. return TRUE;
  2318. }
  2319. //***************************************************************************
  2320. //
  2321. // <finish_qualifier_default> ::= <flavor_list>;
  2322. // <finish_qualifier_default> ::= <type> TOK_EQUALS <default_value> TOK_COMMA TOK_SCOPE TOK_OPEN_PAREN <scope_list> TOK_CLOSE_PAREN <finish_qualifier_end>
  2323. //
  2324. //***************************************************************************
  2325. BOOL CMofParser::finish_qualifier_default(CMoQualifier& Qual)
  2326. {
  2327. // Determine if it is of the simple (flavor only type) or the more complex
  2328. NextToken();
  2329. SCODE sc = Qual.SetFlag(m_nToken, m_Lexer.GetText());
  2330. if(sc == S_OK)
  2331. {
  2332. BOOL bRet = flavor_list(Qual);
  2333. if(bRet)
  2334. m_Output.SetQualifierDefault(&Qual);
  2335. return bRet;
  2336. }
  2337. m_nErrorContext = WBEMMOF_E_INVALID_QUALIFIER_SYNTAX;
  2338. Qual.SetCimDefault(true);
  2339. // assume that we have the long (cim version)
  2340. // Get the type
  2341. CMoType Type(m_pDbg);
  2342. if (!type(Type))
  2343. {
  2344. return FALSE;
  2345. }
  2346. // optional array indication
  2347. if(m_nToken == TOK_OPEN_BRACKET)
  2348. {
  2349. NextToken();
  2350. if(m_nToken != TOK_CLOSE_BRACKET)
  2351. return FALSE;
  2352. Type.SetIsArray(TRUE);
  2353. NextToken();
  2354. }
  2355. else
  2356. Type.SetIsArray(FALSE);
  2357. VARTYPE vt = Type.GetCIMType();
  2358. if(vt == VT_ERROR)
  2359. return FALSE;
  2360. Qual.SetType(vt);
  2361. // optional TOK_EQUALS
  2362. if(m_nToken == TOK_EQUALS)
  2363. {
  2364. // TOK_SIMPLE_VALUE
  2365. NextToken();
  2366. CMoValue & Value = Qual.AccessValue();
  2367. if (!simple_initializer(Type, Value, true))
  2368. return FALSE;
  2369. }
  2370. // look for comma
  2371. if(m_nToken != TOK_COMMA)
  2372. return FALSE;
  2373. // TOK_SCOPE
  2374. NextToken();
  2375. if(m_nToken != TOK_SIMPLE_IDENT || wbem_wcsicmp(L"SCOPE", m_Lexer.GetText()))
  2376. return FALSE;
  2377. // TOK_OPEN_PAREN
  2378. NextToken();
  2379. if(m_nToken != TOK_OPEN_PAREN)
  2380. return FALSE;
  2381. // <scope_list> and close paren
  2382. if(!scope_list(Qual))
  2383. return FALSE;
  2384. return finish_qualifier_end(Qual);
  2385. }
  2386. //***************************************************************************
  2387. //
  2388. // <finish_qualifier_end> ::= TOK_COMMA TOK_FLAVOR OK_OPEN_PAREN <flavor_list> TOK_CLOSE_PAREN;
  2389. // <finish_qualifier_end> ::= <>;
  2390. //
  2391. //***************************************************************************
  2392. BOOL CMofParser::finish_qualifier_end(CMoQualifier& Qual)
  2393. {
  2394. // TOK_COMMA
  2395. NextToken();
  2396. if(m_nToken == TOK_SEMI)
  2397. return TRUE;
  2398. if(m_nToken != TOK_COMMA)
  2399. return FALSE;
  2400. // TOK_FLAVOR
  2401. NextToken();
  2402. if(m_nToken != TOK_SIMPLE_IDENT || wbem_wcsicmp(L"FLAVOR", m_Lexer.GetText()))
  2403. return FALSE;
  2404. // TOK_OPEN_PAREN
  2405. NextToken();
  2406. if(m_nToken != TOK_OPEN_PAREN)
  2407. return FALSE;
  2408. // <flavor_list>
  2409. NextToken();
  2410. if(!def_flavor_list(Qual))
  2411. return FALSE;
  2412. // TOK_CLOSE_PAREN
  2413. if(m_nToken != TOK_CLOSE_PAREN)
  2414. return FALSE;
  2415. m_Output.SetQualifierDefault(&Qual);
  2416. NextToken();
  2417. return TRUE;
  2418. }
  2419. //***************************************************************************
  2420. //
  2421. // <scope_list> ::= <scope_value> <scope_list_rest>;
  2422. //
  2423. //***************************************************************************
  2424. BOOL CMofParser::scope_list(OUT CMoQualifier& Qual)
  2425. {
  2426. NextToken();
  2427. if(!scope_value(Qual))
  2428. return FALSE;
  2429. else
  2430. return scope_list_rest(Qual);
  2431. }
  2432. //***************************************************************************
  2433. //
  2434. // <scope_list_rest> ::= <SCOPE_VALUE> <scope_list_rest>;
  2435. // <scope_list_rest> ::= <>;
  2436. //
  2437. //***************************************************************************
  2438. BOOL CMofParser::scope_list_rest(CMoQualifier& Qual)
  2439. {
  2440. if(m_nToken == TOK_CLOSE_PAREN)
  2441. return TRUE;
  2442. else
  2443. {
  2444. if(m_nToken != TOK_COMMA)
  2445. return FALSE;
  2446. NextToken();
  2447. if(!scope_value(Qual))
  2448. return FALSE;
  2449. return scope_list_rest(Qual);
  2450. }
  2451. return TRUE;
  2452. }
  2453. //***************************************************************************
  2454. //
  2455. // <scope_value> ::= TOK_CLASS;
  2456. // <scope_value> ::= TOK_INSTANCE;
  2457. //
  2458. //***************************************************************************
  2459. BOOL CMofParser::scope_value(CMoQualifier& Qual)
  2460. {
  2461. BOOL bRet = Qual.SetScope(m_nToken, m_Lexer.GetText());
  2462. if(!bRet)
  2463. return FALSE;
  2464. NextToken();
  2465. return TRUE;
  2466. }
  2467. BOOL CMofParser::CheckScopes(SCOPE_CHECK scope_check, CMoQualifierArray* paQualifiers,
  2468. CMoProperty * pProperty)
  2469. {
  2470. m_nErrorContext = WBEMMOF_E_QUALIFIER_USED_OUTSIDE_SCOPE;
  2471. bool bAssociation = false;
  2472. bool bReference = false;
  2473. int iDef;
  2474. // if this is a class, check determine if it is an association
  2475. if(scope_check == IN_CLASS)
  2476. {
  2477. CMoValue * pValue = paQualifiers->Find(L"ASSOCIATION");
  2478. if(pValue)
  2479. {
  2480. VARIANT& var = pValue->AccessVariant();
  2481. if(var.vt == VT_BOOL && var.boolVal == VARIANT_TRUE)
  2482. bAssociation=true;
  2483. }
  2484. }
  2485. // if it is a property, determine if it is a reference
  2486. if((scope_check == IN_PROPERTY || scope_check == IN_PARAM) &&
  2487. pProperty && (pProperty->GetType() == CIM_REFERENCE))
  2488. bReference = true;
  2489. // For each qualifier in my list, look at the globals look for a match
  2490. int iNumTest = paQualifiers->GetSize();
  2491. int iNumDef = m_Output.GetNumDefaultQuals();
  2492. for(int iTest = 0; iTest < iNumTest; iTest++)
  2493. {
  2494. // Get the qualifier to test
  2495. CMoQualifier* pTest = paQualifiers->GetAt(iTest);
  2496. // look for the qualifier in the default list
  2497. CMoQualifier* pDefault = NULL;
  2498. for(iDef = 0; iDef < iNumDef; iDef++)
  2499. {
  2500. CMoQualifier* pDefault = m_Output.GetDefaultQual(iDef);
  2501. if(wbem_wcsicmp(pDefault->GetName(), pTest->GetName()) == 0)
  2502. {
  2503. bool bInScope = false;
  2504. DWORD dwScope = pDefault->GetScope();
  2505. if(dwScope == 0)
  2506. bInScope = true;
  2507. if((dwScope & SCOPE_ASSOCIATION) && bAssociation)
  2508. bInScope = true;
  2509. if((dwScope & SCOPE_REFERENCE) && bReference)
  2510. bInScope = true;
  2511. // got a match
  2512. switch (scope_check)
  2513. {
  2514. case IN_CLASS:
  2515. if(dwScope & SCOPE_CLASS)
  2516. bInScope = true;
  2517. break;
  2518. case IN_INSTANCE:
  2519. if(dwScope & SCOPE_INSTANCE)
  2520. bInScope = true;
  2521. break;
  2522. case IN_PROPERTY:
  2523. if(dwScope & SCOPE_PROPERTY)
  2524. bInScope = true;
  2525. break;
  2526. case IN_PARAM:
  2527. if(dwScope & SCOPE_PARAMETER)
  2528. bInScope = true;
  2529. break;
  2530. case IN_METHOD:
  2531. if(dwScope & SCOPE_METHOD)
  2532. bInScope = true;
  2533. break;
  2534. }
  2535. if(!bInScope)
  2536. return false;
  2537. break;
  2538. }
  2539. }
  2540. }
  2541. return TRUE;
  2542. }