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.

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