Source code of Windows XP (NT5)
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.

674 lines
15 KiB

  1. /*++
  2. // Copyright (c) 1998-2001 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. ActualParse.CPP
  5. Abstract:
  6. Implements the object path parser engine
  7. History:
  8. a-davj 11-feb-00 Created.
  9. --*/
  10. #include "precomp.h"
  11. #include <genlex.h>
  12. #include "opathlex2.h"
  13. #include "PathParse.h"
  14. #include "ActualParse.h"
  15. #include "commain.h"
  16. //#include "resource.h"
  17. #include "wbemcli.h"
  18. #include <stdio.h>
  19. #include "helpers.h"
  20. //***************************************************************************
  21. //
  22. // CActualPathParser
  23. //
  24. //***************************************************************************
  25. LPWSTR CActualPathParser::GetRelativePath(LPWSTR wszFullPath)
  26. {
  27. // We need the last colon, if any
  28. LPWSTR wszTemp = wcschr(wszFullPath, L':');
  29. while (wszTemp != NULL)
  30. {
  31. LPWSTR wszSave = wszTemp;
  32. wszTemp++;
  33. wszTemp = wcschr(wszTemp, L':');
  34. if (!wszTemp)
  35. {
  36. wszTemp = wszSave;
  37. break;
  38. }
  39. }
  40. if (wszTemp)
  41. return wszTemp + 1;
  42. else
  43. return NULL;
  44. }
  45. void CActualPathParser::Zero()
  46. {
  47. m_nCurrentToken = 0;
  48. m_pLexer = 0;
  49. m_pInitialIdent = 0;
  50. m_pOutput = 0;
  51. m_pTmpKeyRef = 0;
  52. }
  53. CActualPathParser::CActualPathParser(DWORD eFlags)
  54. : m_eFlags(eFlags)
  55. {
  56. Zero();
  57. }
  58. void CActualPathParser::Empty()
  59. {
  60. delete m_pLexer;
  61. delete m_pInitialIdent;
  62. delete m_pTmpKeyRef;
  63. // m_pOutput is intentionally left alone,
  64. // since all code paths delete this already on error, or
  65. // else the user acquired the pointer.
  66. }
  67. CActualPathParser::~CActualPathParser()
  68. {
  69. Empty();
  70. }
  71. int CActualPathParser::Parse(
  72. LPCWSTR pRawPath,
  73. CDefPathParser & Output
  74. )
  75. {
  76. DWORD dwTest = m_eFlags & ~WBEMPATH_TREAT_SINGLE_IDENT_AS_NS;
  77. if(dwTest != WBEMPATH_CREATE_ACCEPT_RELATIVE &&
  78. dwTest != WBEMPATH_CREATE_ACCEPT_ABSOLUTE &&
  79. dwTest != WBEMPATH_CREATE_ACCEPT_ALL)
  80. return CActualPathParser::InvalidParameter;
  81. if (pRawPath == 0 || wcslen(pRawPath) == 0)
  82. return CActualPathParser::InvalidParameter;
  83. // Check for leading / trailing ws.
  84. // ================================
  85. if (iswspace(pRawPath[wcslen(pRawPath)-1]) || iswspace(pRawPath[0]))
  86. return InvalidParameter;
  87. // These are required for multiple calls to Parse().
  88. // ==================================================
  89. Empty();
  90. Zero();
  91. m_pOutput = &Output;
  92. // Parse the server name (if there is one) manually
  93. // ================================================
  94. if ( (pRawPath[0] == '\\' && pRawPath[1] == '\\') ||
  95. (pRawPath[0] == '/' && pRawPath[1] == '/'))
  96. {
  97. const WCHAR* pwcStart = pRawPath + 2;
  98. // Find the next backslash --- it's the end of the server name
  99. // Since the next slash can be either, search for both and take
  100. // the first one. If the first character is a '[', then then
  101. // end is indicated by a ']'
  102. // ============================================================
  103. WCHAR* pwcEnd = NULL;
  104. if(*pwcStart == L'[')
  105. {
  106. // look for the ']'
  107. WCHAR * pCloseBrace = wcschr(pwcStart, L']');
  108. if(pCloseBrace == NULL)
  109. return SyntaxError;
  110. pwcEnd = pCloseBrace+1;
  111. }
  112. else
  113. {
  114. WCHAR* pwcNextBack = wcschr(pwcStart, L'\\');
  115. WCHAR* pwcNextForward = wcschr(pwcStart, L'/');
  116. pwcEnd = pwcNextBack;
  117. if(pwcEnd == NULL)
  118. pwcEnd = pwcNextForward;
  119. else if(pwcNextForward && (pwcNextForward < pwcNextBack))
  120. pwcEnd = pwcNextForward;
  121. }
  122. if (pwcEnd == NULL)
  123. {
  124. // If we have already exhausted the object path string,
  125. // a lone server name was all there was.
  126. // ====================================================
  127. if ((m_eFlags & WBEMPATH_CREATE_ACCEPT_ALL) == 0)
  128. {
  129. return SyntaxError;
  130. }
  131. else // A lone server name is legal.
  132. {
  133. m_pOutput->SetServer(pwcStart);
  134. return NoError;
  135. }
  136. }
  137. if(pwcEnd == pwcStart)
  138. {
  139. // No name at all.
  140. // ===============
  141. return SyntaxError;
  142. }
  143. WCHAR * wTemp = new WCHAR[pwcEnd-pwcStart+1];
  144. if(wTemp == NULL)
  145. return NoMemory;
  146. wcsncpy(wTemp, pwcStart, pwcEnd-pwcStart);
  147. wTemp[pwcEnd-pwcStart] = 0;
  148. m_pOutput->SetServer(wTemp, false, true);
  149. pRawPath = pwcEnd;
  150. }
  151. // Point the lexer at the source.
  152. // ==============================
  153. CTextLexSource src((LPWSTR)pRawPath);
  154. {
  155. AutoClear ac(this);
  156. m_pLexer = new CGenLexer(OPath_LexTable2, &src);
  157. if(m_pLexer == NULL)
  158. return NoMemory;
  159. Output.m_pGenLex = m_pLexer; // TEST CODE
  160. // Go.
  161. // ===
  162. int nRes = begin_parse();
  163. if (nRes)
  164. {
  165. return nRes;
  166. }
  167. if (m_nCurrentToken != OPATH_TOK_EOF)
  168. {
  169. return SyntaxError;
  170. }
  171. if (m_pOutput->GetNumComponents() > 0 && !m_pOutput->HasServer())
  172. {
  173. if ( ! ( m_eFlags & WBEMPATH_CREATE_ACCEPT_RELATIVE ) && ! ( m_eFlags & WBEMPATH_CREATE_ACCEPT_ALL ) )
  174. {
  175. return SyntaxError;
  176. }
  177. else
  178. {
  179. // Local namespace --- set server to "."
  180. // =====================================
  181. m_pOutput->SetServer(L".", true, false);
  182. }
  183. }
  184. }
  185. Output.SortKeys();
  186. // Add in key refs.
  187. // ================
  188. return NoError;
  189. }
  190. BOOL CActualPathParser::NextToken()
  191. {
  192. m_nCurrentToken = m_pLexer->NextToken();
  193. if (m_nCurrentToken == OPATH_TOK_ERROR)
  194. return FALSE;
  195. return TRUE;
  196. }
  197. //
  198. // <Parse> ::= BACKSLASH <ns_or_server>;
  199. // <Parse> ::= IDENT <ns_or_class>;
  200. // <Parse> ::= COLON <ns_or_class>;
  201. //
  202. int CActualPathParser::begin_parse()
  203. {
  204. if (!NextToken())
  205. return SyntaxError;
  206. if (m_nCurrentToken == OPATH_TOK_BACKSLASH)
  207. {
  208. if (!NextToken())
  209. return SyntaxError;
  210. return ns_or_server();
  211. }
  212. else if (m_nCurrentToken == OPATH_TOK_IDENT)
  213. {
  214. m_pInitialIdent = Macro_CloneLPWSTR(m_pLexer->GetTokenText());
  215. if(m_pInitialIdent == NULL)
  216. return NoMemory;
  217. if (!NextToken())
  218. return SyntaxError;
  219. // Copy the token and put it in a temporary holding place
  220. // until we figure out whether it is a namespace or a class name.
  221. // ==============================================================
  222. return ns_or_class();
  223. }
  224. else if (m_nCurrentToken == OPATH_TOK_COLON)
  225. {
  226. // A colon may indicate a namespace now...
  227. if (!NextToken())
  228. return SyntaxError;
  229. return ns_or_class();
  230. }
  231. // If here, we had a bad starter token.
  232. // ====================================
  233. return SyntaxError;
  234. }
  235. //
  236. // <ns_or_server> ::= IDENT <ns_list>;
  237. //
  238. int CActualPathParser::ns_or_server()
  239. {
  240. if (m_nCurrentToken == OPATH_TOK_BACKSLASH)
  241. {
  242. // Actually, server names have been take care of, so this is a failure
  243. // ===================================================================
  244. return SyntaxError;
  245. }
  246. else if (m_nCurrentToken == OPATH_TOK_IDENT)
  247. {
  248. return ns_list();
  249. }
  250. else
  251. if (m_nCurrentToken == OPATH_TOK_EOF)
  252. return NoError;
  253. return SyntaxError;
  254. }
  255. // <ns_or_class> ::= COLON <ident_becomes_ns> <objref> <optional_scope_class_list>;
  256. // <ns_or_class> ::= BACKSLASH <ident_becomes_ns> <ns_list>;
  257. // <ns_or_class> ::= <ident_becomes_ns> <objref_rest>;
  258. // <ns_or_class> ::= <ident_becomes_class> <objref_rest>;
  259. int CActualPathParser::ns_or_class()
  260. {
  261. if (m_nCurrentToken == OPATH_TOK_COLON)
  262. {
  263. ident_becomes_ns();
  264. if (!NextToken())
  265. return SyntaxError;
  266. int nRes = objref();
  267. if (nRes)
  268. return nRes;
  269. if ((m_nCurrentToken != OPATH_TOK_EOF))
  270. return optional_scope_class_list();
  271. return NoError;
  272. }
  273. else if (m_nCurrentToken == OPATH_TOK_BACKSLASH)
  274. {
  275. ident_becomes_ns();
  276. if (!NextToken())
  277. return SyntaxError;
  278. return ns_list();
  279. }
  280. else if ((m_nCurrentToken == OPATH_TOK_EOF) &&
  281. (m_eFlags & WBEMPATH_TREAT_SINGLE_IDENT_AS_NS))
  282. {
  283. return ident_becomes_ns();
  284. }
  285. // Else
  286. // ====
  287. ident_becomes_class();
  288. if(objref_rest())
  289. return SyntaxError;
  290. else
  291. return optional_scope_class_list();
  292. }
  293. // <optional_scope_class_list> ::= COLON <objref> <optional_scope_class_list>
  294. // <optional_scope_class_list> ::= <>
  295. int CActualPathParser::optional_scope_class_list()
  296. {
  297. if (m_nCurrentToken == OPATH_TOK_EOF)
  298. return NoError;
  299. else if (m_nCurrentToken == OPATH_TOK_COLON)
  300. {
  301. if (!NextToken())
  302. return SyntaxError;
  303. if (objref() == NoError)
  304. return optional_scope_class_list();
  305. return SyntaxError;
  306. }
  307. return NoError;
  308. }
  309. //
  310. // <objref> ::= IDENT <objref_rest>; // IDENT is classname
  311. //
  312. int CActualPathParser::objref()
  313. {
  314. if (m_nCurrentToken != OPATH_TOK_IDENT)
  315. return SyntaxError;
  316. m_pOutput->AddClass(m_pLexer->GetTokenText());
  317. if (!NextToken())
  318. return SyntaxError;
  319. return objref_rest();
  320. }
  321. //
  322. // <ns_list> ::= IDENT <ns_list_rest>;
  323. //
  324. int CActualPathParser::ns_list()
  325. {
  326. if (m_nCurrentToken == OPATH_TOK_IDENT)
  327. {
  328. m_pOutput->AddNamespace(m_pLexer->GetTokenText());
  329. if (!NextToken())
  330. return SyntaxError;
  331. return ns_list_rest();
  332. }
  333. return SyntaxError;
  334. }
  335. //
  336. // <ident_becomes_ns> ::= <>; // <initial_ident> becomes a namespace
  337. //
  338. int CActualPathParser::ident_becomes_ns()
  339. {
  340. m_pOutput->AddNamespace(m_pInitialIdent);
  341. delete m_pInitialIdent;
  342. m_pInitialIdent = 0;
  343. return NoError;
  344. }
  345. //
  346. // <ident_becomes_class> ::= <>; // <initial_ident> becomes the class
  347. //
  348. int CActualPathParser::ident_becomes_class()
  349. {
  350. m_pOutput->AddClass(m_pInitialIdent);
  351. delete m_pInitialIdent;
  352. m_pInitialIdent = 0;
  353. return NoError;
  354. }
  355. //
  356. // <objref_rest> ::= EQUALS <key_const>;
  357. // <objref_rest> ::= EQUALS @;
  358. // <objref_rest> ::= DOT <keyref_list>;
  359. // <objref_rest> ::= <>;
  360. //
  361. int CActualPathParser::objref_rest()
  362. {
  363. if (m_nCurrentToken == OPATH_TOK_EQ)
  364. {
  365. if (!NextToken())
  366. return SyntaxError;
  367. // Take care of the singleton case. This is a path of the form
  368. // MyClass=@ and represents a singleton instance of a class with no
  369. // keys.
  370. if(m_nCurrentToken == OPATH_TOK_SINGLETON_SYM)
  371. {
  372. NextToken();
  373. m_pOutput->SetSingletonObj();
  374. return NoError;
  375. }
  376. m_pTmpKeyRef = new CKeyRef;
  377. if(m_pTmpKeyRef == NULL)
  378. return NoMemory;
  379. int nRes = key_const();
  380. if (nRes)
  381. {
  382. delete m_pTmpKeyRef;
  383. m_pTmpKeyRef = 0;
  384. return nRes;
  385. }
  386. m_pOutput->AddKeyRef(m_pTmpKeyRef);
  387. m_pTmpKeyRef = 0;
  388. }
  389. else if (m_nCurrentToken == OPATH_TOK_DOT)
  390. {
  391. if (!NextToken())
  392. return SyntaxError;
  393. return keyref_list();
  394. }
  395. return NoError;
  396. }
  397. //
  398. // <ns_list_rest> ::= BACKSLASH <ns_list>;
  399. // <ns_list_rest> ::= COLON <objref> <optional_scope_class_list>;
  400. // <ns_list_rest> ::= <>;
  401. int CActualPathParser::ns_list_rest()
  402. {
  403. if (m_nCurrentToken == OPATH_TOK_BACKSLASH)
  404. {
  405. if (!NextToken())
  406. return SyntaxError;
  407. return ns_list();
  408. }
  409. else if (m_nCurrentToken == OPATH_TOK_COLON)
  410. {
  411. if (!NextToken())
  412. return SyntaxError;
  413. if (objref() == NoError)
  414. return optional_scope_class_list();
  415. return SyntaxError;
  416. }
  417. return NoError;
  418. }
  419. //
  420. // <key_const> ::= STRING_CONST;
  421. // <key_const> ::= INTEGRAL_CONST;
  422. // <key_const> ::= REAL_CONST;
  423. // <key_const> ::= IDENT; // Where IDENT is "OBJECT" for singleton classes
  424. //
  425. int CActualPathParser::key_const()
  426. {
  427. // If here, we have a key constant.
  428. // We may or may not have the property name
  429. // associated with it.
  430. // ========================================
  431. if (m_nCurrentToken == OPATH_TOK_QSTRING)
  432. {
  433. int iNumByte = 2*(wcslen(m_pLexer->GetTokenText()) +1);
  434. m_pTmpKeyRef->SetData(CIM_STRING, iNumByte, m_pLexer->GetTokenText());
  435. }
  436. else if (m_nCurrentToken == OPATH_TOK_REFERENCE)
  437. {
  438. int iNumByte = 2*(wcslen(m_pLexer->GetTokenText()) +1);
  439. m_pTmpKeyRef->SetData(CIM_REFERENCE, iNumByte, m_pLexer->GetTokenText());
  440. }
  441. else if (m_nCurrentToken == OPATH_TOK_INT)
  442. {
  443. if(*(m_pLexer->GetTokenText()) == L'-')
  444. {
  445. __int64 llVal = _wtoi64(m_pLexer->GetTokenText());
  446. if(llVal > 2147483647 || llVal < -(__int64)2147483648)
  447. m_pTmpKeyRef->SetData(CIM_SINT64, 8, &llVal);
  448. else
  449. m_pTmpKeyRef->SetData(CIM_SINT32, 4, &llVal);
  450. }
  451. else
  452. {
  453. unsigned __int64 ullVal;
  454. if(0 == swscanf(m_pLexer->GetTokenText(), L"%I64u", &ullVal))
  455. return SyntaxError;
  456. if(ullVal < 2147483648)
  457. m_pTmpKeyRef->SetData(CIM_SINT32, 4, &ullVal);
  458. else if(ullVal > 0xffffffff)
  459. m_pTmpKeyRef->SetData(CIM_UINT64, 8, &ullVal);
  460. else
  461. m_pTmpKeyRef->SetData(CIM_UINT32, 4, &ullVal);
  462. }
  463. }
  464. else if (m_nCurrentToken == OPATH_TOK_HEXINT)
  465. {
  466. unsigned __int64 ullVal;
  467. if(0 ==swscanf(m_pLexer->GetTokenText(),L"%I64x", &ullVal))
  468. return SyntaxError;
  469. m_pTmpKeyRef->SetData(CIM_UINT64, 8, &ullVal);
  470. }
  471. else if (m_nCurrentToken == OPATH_TOK_IDENT)
  472. {
  473. if (_wcsicmp(m_pLexer->GetTokenText(), L"TRUE") == 0)
  474. {
  475. long lVal = 1;
  476. m_pTmpKeyRef->SetData(CIM_BOOLEAN, 4, &lVal);
  477. }
  478. else if (_wcsicmp(m_pLexer->GetTokenText(), L"FALSE") == 0)
  479. {
  480. long lVal = 0;
  481. m_pTmpKeyRef->SetData(CIM_BOOLEAN, 4, &lVal);
  482. }
  483. else
  484. return SyntaxError;
  485. }
  486. else return SyntaxError;
  487. if (!NextToken())
  488. return SyntaxError;
  489. return NoError;
  490. }
  491. //
  492. // <keyref_list> ::= <keyref> <keyref_term>;
  493. //
  494. int CActualPathParser::keyref_list()
  495. {
  496. int nRes = keyref();
  497. if (nRes)
  498. return nRes;
  499. return keyref_term();
  500. }
  501. //
  502. // <keyref> ::= <propname> EQUALS <key_const>;
  503. //
  504. int CActualPathParser::keyref()
  505. {
  506. m_pTmpKeyRef = new CKeyRef;
  507. if(m_pTmpKeyRef == NULL)
  508. return NoMemory;
  509. int nRes = propname();
  510. if (nRes)
  511. {
  512. delete m_pTmpKeyRef;
  513. m_pTmpKeyRef = 0;
  514. return nRes;
  515. }
  516. if (m_nCurrentToken != OPATH_TOK_EQ)
  517. {
  518. delete m_pTmpKeyRef;
  519. m_pTmpKeyRef = 0;
  520. return SyntaxError;
  521. }
  522. if (!NextToken())
  523. {
  524. delete m_pTmpKeyRef;
  525. m_pTmpKeyRef = 0;
  526. return SyntaxError;
  527. }
  528. nRes = key_const();
  529. if (nRes)
  530. {
  531. delete m_pTmpKeyRef;
  532. m_pTmpKeyRef = 0;
  533. return nRes;
  534. }
  535. m_pOutput->AddKeyRef(m_pTmpKeyRef);
  536. m_pTmpKeyRef = 0;
  537. return NoError;
  538. }
  539. //
  540. // <keyref_term> ::= COMMA <keyref_list>; // Used for compound keys
  541. // <keyref_term> ::= <>;
  542. //
  543. int CActualPathParser::keyref_term()
  544. {
  545. if (m_nCurrentToken == OPATH_TOK_COMMA)
  546. {
  547. if (!NextToken())
  548. return SyntaxError;
  549. return keyref_list();
  550. }
  551. return NoError;
  552. }
  553. //
  554. // <propname> ::= IDENT;
  555. //
  556. int CActualPathParser::propname()
  557. {
  558. if (m_nCurrentToken != OPATH_TOK_IDENT)
  559. return SyntaxError;
  560. m_pTmpKeyRef->m_pName = Macro_CloneLPWSTR(m_pLexer->GetTokenText());
  561. if (!m_pTmpKeyRef->m_pName)
  562. return NoMemory;
  563. if (!NextToken())
  564. {
  565. delete m_pTmpKeyRef;
  566. m_pTmpKeyRef = 0;
  567. return SyntaxError;
  568. }
  569. return NoError;
  570. }