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.

1382 lines
33 KiB

  1. /*++
  2. Copyright (c) 1999-2001 Microsoft Corporation, All Rights Reserved
  3. Module Name:
  4. OBJPATH.CPP
  5. Abstract:
  6. Object path parser.
  7. History:
  8. --*/
  9. #include "precomp.h"
  10. #include <genlex.h>
  11. #include <opathlex.h>
  12. #include <objpath.h>
  13. #define Macro_CloneLPWSTR(x) \
  14. (x ? wcscpy(new wchar_t[wcslen(x) + 1], x) : 0)
  15. ParsedObjectPath::ParsedObjectPath()
  16. {
  17. m_pServer = 0; // NULL if no server
  18. m_dwNumNamespaces = 0; // 0 if no namespaces
  19. m_dwAllocNamespaces = 2;
  20. m_paNamespaces = new LPWSTR[m_dwAllocNamespaces];
  21. for (unsigned i = 0; i < m_dwAllocNamespaces; i++)
  22. m_paNamespaces[i] = 0;
  23. m_pClass = 0; // Class name
  24. m_dwNumKeys = 0; // 0 if no keys (just a class name)
  25. m_bSingletonObj = FALSE;
  26. m_dwAllocKeys = 2;
  27. m_paKeys = new KeyRef *[m_dwAllocKeys];
  28. }
  29. ParsedObjectPath::~ParsedObjectPath()
  30. {
  31. delete m_pServer;
  32. for (DWORD dwIx = 0; dwIx < m_dwNumNamespaces; dwIx++)
  33. delete m_paNamespaces[dwIx];
  34. delete m_paNamespaces;
  35. delete m_pClass;
  36. for (dwIx = 0; dwIx < m_dwNumKeys; dwIx++)
  37. delete m_paKeys[dwIx];
  38. delete m_paKeys;
  39. }
  40. BOOL ParsedObjectPath::SetClassName(LPCWSTR wszClassName)
  41. {
  42. delete [] m_pClass;
  43. if(wszClassName == NULL)
  44. {
  45. m_pClass = NULL;
  46. }
  47. else
  48. {
  49. m_pClass = Macro_CloneLPWSTR(wszClassName);
  50. }
  51. return TRUE;
  52. }
  53. BOOL ParsedObjectPath::IsClass()
  54. {
  55. if(!IsObject())
  56. return FALSE;
  57. return (m_dwNumKeys == 0 && !m_bSingletonObj);
  58. }
  59. BOOL ParsedObjectPath::IsInstance()
  60. {
  61. return IsObject() && !IsClass();
  62. }
  63. BOOL ParsedObjectPath::IsObject()
  64. {
  65. if(m_pClass == NULL)
  66. return FALSE;
  67. if(m_pServer)
  68. {
  69. return (m_dwNumNamespaces > 0);
  70. }
  71. else
  72. {
  73. return (m_dwNumNamespaces == 0);
  74. }
  75. }
  76. BOOL ParsedObjectPath::AddNamespace(LPCWSTR wszNamespace)
  77. {
  78. if(m_dwNumNamespaces == m_dwAllocNamespaces)
  79. {
  80. DWORD dwNewAllocNamespaces = m_dwAllocNamespaces * 2;
  81. LPWSTR* paNewNamespaces = new LPWSTR[dwNewAllocNamespaces];
  82. memcpy(paNewNamespaces, m_paNamespaces,
  83. sizeof(LPWSTR) * m_dwAllocNamespaces);
  84. delete [] m_paNamespaces;
  85. m_paNamespaces = paNewNamespaces;
  86. m_dwAllocNamespaces = dwNewAllocNamespaces;
  87. }
  88. m_paNamespaces[m_dwNumNamespaces++] = Macro_CloneLPWSTR(wszNamespace);
  89. return TRUE;
  90. }
  91. BOOL ParsedObjectPath::AddKeyRefEx(LPCWSTR wszKeyName, const VARIANT* pvValue )
  92. {
  93. BOOL bStatus = TRUE ;
  94. BOOL bFound = FALSE ;
  95. BOOL bUnNamed = FALSE ;
  96. for ( ULONG dwIndex = 0 ; dwIndex < m_dwNumKeys ; dwIndex ++ )
  97. {
  98. if ( ( m_paKeys [ dwIndex ]->m_pName ) && wszKeyName )
  99. {
  100. if ( _wcsicmp ( m_paKeys [ dwIndex ]->m_pName , wszKeyName )
  101. == 0 )
  102. {
  103. bFound = TRUE ;
  104. break ;
  105. }
  106. }
  107. else
  108. {
  109. if ( ( ( m_paKeys [ dwIndex ]->m_pName ) == 0 ) )
  110. {
  111. bUnNamed = TRUE ;
  112. if ( ( wszKeyName == 0 ) )
  113. {
  114. bFound = TRUE ;
  115. break ;
  116. }
  117. }
  118. }
  119. }
  120. if ( ! wszKeyName )
  121. {
  122. /* Remove all existing keys */
  123. for ( ULONG dwDeleteIndex = 0 ; dwDeleteIndex < m_dwNumKeys ;
  124. dwDeleteIndex ++ )
  125. {
  126. delete ( m_paKeys [ dwDeleteIndex ]->m_pName ) ;
  127. m_paKeys [ dwDeleteIndex ]->m_pName = NULL ;
  128. VariantClear ( & ( m_paKeys [ dwDeleteIndex ]->m_vValue ) ) ;
  129. }
  130. VariantCopy ( & ( m_paKeys [ 0 ]->m_vValue ) , ( VARIANT * ) pvValue );
  131. m_dwNumKeys = 1 ;
  132. }
  133. else
  134. {
  135. if ( bFound )
  136. {
  137. /*
  138. * If key already exists then just replace the value
  139. */
  140. if ( wszKeyName )
  141. {
  142. m_paKeys [ dwIndex ]->m_pName =
  143. new wchar_t [ wcslen ( wszKeyName ) + 1 ] ;
  144. wcscpy ( m_paKeys [ dwIndex ]->m_pName , wszKeyName ) ;
  145. }
  146. VariantClear ( & ( m_paKeys [ dwIndex ]->m_vValue ) ) ;
  147. VariantCopy ( & ( m_paKeys [ dwIndex ]->m_vValue ) ,
  148. ( VARIANT * ) pvValue ) ;
  149. }
  150. else
  151. {
  152. if ( bUnNamed )
  153. {
  154. /* Add an un named key */
  155. for ( ULONG dwDeleteIndex = 0 ; dwDeleteIndex < m_dwNumKeys ;
  156. dwDeleteIndex ++ )
  157. {
  158. delete ( m_paKeys [ dwDeleteIndex ]->m_pName ) ;
  159. m_paKeys [ dwDeleteIndex ]->m_pName = NULL ;
  160. VariantClear (& ( m_paKeys [ dwDeleteIndex ]->m_vValue ) );
  161. }
  162. m_paKeys [ 0 ]->m_pName =
  163. new wchar_t [ wcslen ( wszKeyName ) + 1 ] ;
  164. wcscpy ( m_paKeys [ 0 ]->m_pName , wszKeyName ) ;
  165. VariantCopy ( & ( m_paKeys [ 0 ]->m_vValue ) ,
  166. ( VARIANT * ) pvValue ) ;
  167. m_dwNumKeys = 1 ;
  168. }
  169. else
  170. {
  171. /* Add a Named Key */
  172. AddKeyRef(wszKeyName, pvValue);
  173. }
  174. }
  175. }
  176. return bStatus;
  177. }
  178. void ParsedObjectPath::ClearKeys ()
  179. {
  180. for ( ULONG dwDeleteIndex = 0 ; dwDeleteIndex < m_dwNumKeys ;
  181. dwDeleteIndex ++ )
  182. {
  183. delete m_paKeys [ dwDeleteIndex ] ;
  184. m_paKeys [ dwDeleteIndex ] = NULL ;
  185. }
  186. delete [] m_paKeys ;
  187. m_paKeys = NULL ;
  188. m_dwNumKeys = 0; // 0 if no keys (just a class name)
  189. m_dwAllocKeys = 2;
  190. m_paKeys = new KeyRef *[m_dwAllocKeys];
  191. }
  192. BOOL ParsedObjectPath::AddKeyRef(LPCWSTR wszKeyName, const VARIANT* pvValue)
  193. {
  194. if(m_dwNumKeys == m_dwAllocKeys)
  195. {
  196. DWORD dwNewAllocKeys = m_dwAllocKeys * 2;
  197. KeyRef** paNewKeys = new KeyRef*[dwNewAllocKeys];
  198. memcpy(paNewKeys, m_paKeys, sizeof(KeyRef*) * m_dwAllocKeys);
  199. delete [] m_paKeys;
  200. m_paKeys = paNewKeys;
  201. m_dwAllocKeys = dwNewAllocKeys;
  202. }
  203. m_paKeys[m_dwNumKeys] = new KeyRef(wszKeyName, pvValue);
  204. m_dwNumKeys++;
  205. return TRUE;
  206. }
  207. BOOL ParsedObjectPath::AddKeyRef(KeyRef* pAcquireRef)
  208. {
  209. if(m_dwNumKeys == m_dwAllocKeys)
  210. {
  211. DWORD dwNewAllocKeys = m_dwAllocKeys * 2;
  212. KeyRef** paNewKeys = new KeyRef*[dwNewAllocKeys];
  213. memcpy(paNewKeys, m_paKeys, sizeof(KeyRef*) * m_dwAllocKeys);
  214. delete [] m_paKeys;
  215. m_paKeys = paNewKeys;
  216. m_dwAllocKeys = dwNewAllocKeys;
  217. }
  218. m_paKeys[m_dwNumKeys] = pAcquireRef;
  219. m_dwNumKeys++;
  220. return TRUE;
  221. }
  222. KeyRef::KeyRef()
  223. {
  224. m_pName = 0;
  225. VariantInit(&m_vValue);
  226. }
  227. KeyRef::KeyRef(LPCWSTR wszKeyName, const VARIANT* pvValue)
  228. {
  229. m_pName = Macro_CloneLPWSTR(wszKeyName);
  230. VariantInit(&m_vValue);
  231. VariantCopy(&m_vValue, (VARIANT*)pvValue);
  232. }
  233. KeyRef::~KeyRef()
  234. {
  235. delete m_pName;
  236. VariantClear(&m_vValue);
  237. }
  238. int WINAPI CObjectPathParser::Unparse(
  239. ParsedObjectPath* pInput,
  240. DELETE_ME LPWSTR* pwszPath)
  241. {
  242. if(pInput->m_pClass == NULL)
  243. {
  244. return CObjectPathParser::InvalidParameter;
  245. }
  246. // Allocate enough space
  247. // =====================
  248. int nSpace = wcslen(pInput->m_pClass);
  249. nSpace += 10;
  250. DWORD dwIx;
  251. for (dwIx = 0; dwIx < pInput->m_dwNumKeys; dwIx++)
  252. {
  253. KeyRef* pKey = pInput->m_paKeys[dwIx];
  254. if(pKey->m_pName)
  255. nSpace += wcslen(pKey->m_pName);
  256. if(V_VT(&pKey->m_vValue) == VT_BSTR)
  257. {
  258. nSpace += wcslen(V_BSTR(&pKey->m_vValue))*2 + 10;
  259. }
  260. else if( V_VT(&pKey->m_vValue) == VT_I4
  261. || V_VT(&pKey->m_vValue) == VT_UI4 )
  262. {
  263. nSpace += 30;
  264. }
  265. else if ( V_VT(&pKey->m_vValue) == VT_I2
  266. || V_VT(&pKey->m_vValue) == VT_UI2 )
  267. {
  268. nSpace += 15;
  269. }
  270. else if ( V_VT(&pKey->m_vValue) == VT_I1
  271. || V_VT(&pKey->m_vValue) == VT_UI1 )
  272. {
  273. nSpace += 8;
  274. }
  275. }
  276. if(pInput->m_bSingletonObj)
  277. nSpace +=2;
  278. WCHAR wszTemp[30];
  279. LPWSTR wszPath = new WCHAR[nSpace];
  280. wcscpy(wszPath, pInput->m_pClass);
  281. for (dwIx = 0; dwIx < pInput->m_dwNumKeys; dwIx++)
  282. {
  283. KeyRef* pKey = pInput->m_paKeys[dwIx];
  284. // We dont want to put a '.' if there isnt a key name,
  285. // for example, Myclass="value"
  286. if(dwIx == 0)
  287. {
  288. if((pKey->m_pName && (0 < wcslen(pKey->m_pName))) || pInput->m_dwNumKeys > 1)
  289. wcscat(wszPath, L".");
  290. }
  291. else
  292. {
  293. wcscat(wszPath, L",");
  294. }
  295. if(pKey->m_pName)
  296. wcscat(wszPath, pKey->m_pName);
  297. wcscat(wszPath, L"=");
  298. if(V_VT(&pKey->m_vValue) == VT_BSTR)
  299. {
  300. wcscat(wszPath, L"\"");
  301. WCHAR* pwc = V_BSTR(&pKey->m_vValue);
  302. WCHAR str[2];
  303. str[1] = 0;
  304. while(*pwc)
  305. {
  306. if(*pwc == '\\' || *pwc == '"')
  307. {
  308. wcscat(wszPath, L"\\");
  309. }
  310. str[0] = *pwc;
  311. wcscat(wszPath, str);
  312. pwc++;
  313. }
  314. wcscat(wszPath, L"\"");
  315. }
  316. else if( V_VT(&pKey->m_vValue) == VT_I4 )
  317. {
  318. swprintf(wszTemp, L"%d", V_I4(&pKey->m_vValue));
  319. wcscat(wszPath, wszTemp);
  320. }
  321. else if( V_VT(&pKey->m_vValue) == VT_UI4 )
  322. {
  323. swprintf(wszTemp, L"%u", V_UI4(&pKey->m_vValue));
  324. wcscat(wszPath, wszTemp);
  325. }
  326. else if( V_VT(&pKey->m_vValue) == VT_I2 )
  327. {
  328. swprintf(wszTemp, L"%hd", V_I2(&pKey->m_vValue));
  329. wcscat(wszPath, wszTemp);
  330. }
  331. else if( V_VT(&pKey->m_vValue) == VT_UI2 )
  332. {
  333. swprintf(wszTemp, L"%hu", V_UI2(&pKey->m_vValue));
  334. wcscat(wszPath, wszTemp);
  335. }
  336. else if( V_VT(&pKey->m_vValue) == VT_I1 )
  337. {
  338. swprintf(wszTemp, L"%d", V_I1(&pKey->m_vValue));
  339. wcscat(wszPath, wszTemp);
  340. }
  341. else if( V_VT(&pKey->m_vValue) == VT_UI1 )
  342. {
  343. swprintf(wszTemp, L"%u", V_UI1(&pKey->m_vValue));
  344. wcscat(wszPath, wszTemp);
  345. }
  346. }
  347. // Take care of the singleton case. This is a path of the form
  348. // MyClass=@ and represents a single instance of a class with no
  349. // keys.
  350. if(pInput->m_bSingletonObj && pInput->m_dwNumKeys == 0)
  351. wcscat(wszPath, L"=@");
  352. *pwszPath = wszPath;
  353. return NoError;
  354. }
  355. LPWSTR WINAPI CObjectPathParser::GetRelativePath(LPWSTR wszFullPath)
  356. {
  357. LPWSTR wsz = wcschr(wszFullPath, L':');
  358. if(wsz)
  359. return wsz + 1;
  360. else
  361. return NULL;
  362. }
  363. void CObjectPathParser::Zero()
  364. {
  365. m_nCurrentToken = 0;
  366. m_pLexer = 0;
  367. m_pInitialIdent = 0;
  368. m_pOutput = 0;
  369. m_pTmpKeyRef = 0;
  370. }
  371. CObjectPathParser::CObjectPathParser(ObjectParserFlags eFlags)
  372. : m_eFlags(eFlags)
  373. {
  374. Zero();
  375. }
  376. void CObjectPathParser::Empty()
  377. {
  378. delete m_pLexer;
  379. delete m_pInitialIdent;
  380. delete m_pTmpKeyRef;
  381. // m_pOutput is intentionally left alone,
  382. // since all code paths delete this already on error, or
  383. // else the user acquired the pointer.
  384. }
  385. CObjectPathParser::~CObjectPathParser()
  386. {
  387. Empty();
  388. }
  389. int CObjectPathParser::Parse(
  390. LPCWSTR pRawPath,
  391. ParsedObjectPath **pOutput
  392. )
  393. {
  394. if (pOutput == 0 || pRawPath == 0 || wcslen(pRawPath) == 0)
  395. return CObjectPathParser::InvalidParameter;
  396. // Check for leading / trailing ws.
  397. // ================================
  398. if (iswspace(pRawPath[wcslen(pRawPath)-1]) || iswspace(pRawPath[0]))
  399. return InvalidParameter;
  400. // These are required for multiple calls to Parse().
  401. // ==================================================
  402. Empty();
  403. Zero();
  404. // Set default return to NULL initially until we have some output.
  405. // ===============================================================
  406. *pOutput = 0;
  407. m_pOutput = new ParsedObjectPath;
  408. // Parse the server name (if there is one) manually
  409. // ================================================
  410. if ( (pRawPath[0] == '\\' && pRawPath[1] == '\\') ||
  411. (pRawPath[0] == '/' && pRawPath[1] == '/'))
  412. {
  413. const WCHAR* pwcStart = pRawPath + 2;
  414. // Find the next backslash --- it's the end of the server name
  415. // ===========================================================
  416. const WCHAR* pwcEnd = pwcStart;
  417. while (*pwcEnd != L'\0' && *pwcEnd != L'\\' && *pwcEnd != L'/')
  418. {
  419. pwcEnd++;
  420. }
  421. if (*pwcEnd == L'\0')
  422. {
  423. // If we have already exhausted the object path string,
  424. // a lone server name was all there was.
  425. // ====================================================
  426. if (m_eFlags != e_ParserAcceptAll)
  427. {
  428. delete m_pOutput;
  429. return SyntaxError;
  430. }
  431. else // A lone server name is legal.
  432. {
  433. m_pOutput->m_pServer = new WCHAR[wcslen(pwcStart)+1];
  434. wcscpy(m_pOutput->m_pServer, pwcStart);
  435. *pOutput = m_pOutput;
  436. m_pOutput = 0;
  437. return NoError;
  438. }
  439. }
  440. if (pwcEnd == pwcStart)
  441. {
  442. // No name at all.
  443. // ===============
  444. delete m_pOutput;
  445. return SyntaxError;
  446. }
  447. m_pOutput->m_pServer = new WCHAR[pwcEnd-pwcStart+1];
  448. wcsncpy(m_pOutput->m_pServer, pwcStart, pwcEnd-pwcStart);
  449. m_pOutput->m_pServer[pwcEnd-pwcStart] = 0;
  450. pRawPath = pwcEnd;
  451. }
  452. // Point the lexer at the source.
  453. // ==============================
  454. CTextLexSource src(pRawPath);
  455. m_pLexer = new CGenLexer(OPath_LexTable, &src);
  456. // Go.
  457. // ===
  458. int nRes = begin_parse();
  459. if (nRes)
  460. {
  461. delete m_pOutput;
  462. return nRes;
  463. }
  464. if (m_nCurrentToken != OPATH_TOK_EOF)
  465. {
  466. delete m_pOutput;
  467. return SyntaxError;
  468. }
  469. if (m_pOutput->m_dwNumNamespaces > 0 && m_pOutput->m_pServer == NULL)
  470. {
  471. if (m_eFlags != e_ParserAcceptRelativeNamespace && m_eFlags != e_ParserAcceptAll)
  472. {
  473. delete m_pOutput;
  474. return SyntaxError;
  475. }
  476. else
  477. {
  478. // Local namespace --- set server to "."
  479. // =====================================
  480. m_pOutput->m_pServer = new WCHAR[2];
  481. wcscpy(m_pOutput->m_pServer, L".");
  482. }
  483. }
  484. // Sort the key refs lexically. If there is only
  485. // one key, there is nothing to sort anyway.
  486. // =============================================
  487. if (m_pOutput->m_dwNumKeys > 1)
  488. {
  489. BOOL bChanges = TRUE;
  490. while (bChanges)
  491. {
  492. bChanges = FALSE;
  493. for (DWORD dwIx = 0; dwIx < m_pOutput->m_dwNumKeys - 1; dwIx++)
  494. {
  495. if (_wcsicmp(m_pOutput->m_paKeys[dwIx]->m_pName,
  496. m_pOutput->m_paKeys[dwIx+1]->m_pName) > 0)
  497. {
  498. KeyRef *pTmp = m_pOutput->m_paKeys[dwIx];
  499. m_pOutput->m_paKeys[dwIx] = m_pOutput->m_paKeys[dwIx + 1];
  500. m_pOutput->m_paKeys[dwIx + 1] = pTmp;
  501. bChanges = TRUE;
  502. }
  503. }
  504. }
  505. }
  506. // Add in key refs.
  507. // ================
  508. *pOutput = m_pOutput;
  509. m_pOutput = 0;
  510. return NoError;
  511. }
  512. BOOL CObjectPathParser::NextToken()
  513. {
  514. m_nCurrentToken = m_pLexer->NextToken();
  515. if (m_nCurrentToken == OPATH_TOK_ERROR)
  516. return FALSE;
  517. return TRUE;
  518. }
  519. void CObjectPathParser::Free(ParsedObjectPath *pOutput)
  520. {
  521. delete pOutput;
  522. }
  523. //
  524. // <Parse> ::= BACKSLASH <ns_or_server>;
  525. // <Parse> ::= IDENT <ns_or_class>;
  526. // <Parse> ::= COLON <objref>;
  527. //
  528. int CObjectPathParser::begin_parse()
  529. {
  530. if (!NextToken())
  531. return SyntaxError;
  532. if (m_nCurrentToken == OPATH_TOK_BACKSLASH)
  533. {
  534. if (!NextToken())
  535. return SyntaxError;
  536. return ns_or_server();
  537. }
  538. else if (m_nCurrentToken == OPATH_TOK_IDENT)
  539. {
  540. m_pInitialIdent = Macro_CloneLPWSTR(m_pLexer->GetTokenText());
  541. if (!NextToken())
  542. return SyntaxError;
  543. // Copy the token and put it in a temporary holding place
  544. // until we figure out whether it is a namespace or a class name.
  545. // ==============================================================
  546. return ns_or_class();
  547. }
  548. else if (m_nCurrentToken == OPATH_TOK_COLON)
  549. {
  550. if (!NextToken())
  551. return SyntaxError;
  552. return objref();
  553. }
  554. // If here, we had a bad starter token.
  555. // ====================================
  556. return SyntaxError;
  557. }
  558. //
  559. // <ns_or_server> ::= BACKSLASH <dot_or_ident> BACKSLASH <ns_list> <optional_objref>;
  560. // <ns_or_server> ::= <ns_list> <optional_objref>;
  561. //
  562. // <dot_or_ident> is embedded.
  563. //
  564. int CObjectPathParser::ns_or_server()
  565. {
  566. if (m_nCurrentToken == OPATH_TOK_BACKSLASH)
  567. {
  568. // Actually, server names have been take care of, so this is a failure
  569. // ===================================================================
  570. return SyntaxError;
  571. }
  572. else if (m_nCurrentToken == OPATH_TOK_IDENT)
  573. {
  574. int nRes = ns_list();
  575. if (nRes)
  576. return nRes;
  577. return optional_objref();
  578. }
  579. else
  580. if (m_nCurrentToken == OPATH_TOK_EOF)
  581. return NoError;
  582. return SyntaxError;
  583. }
  584. //
  585. // <optional_objref> ::= COLON <objref>;
  586. // <optional_objref> ::= <>;
  587. //
  588. int CObjectPathParser::optional_objref()
  589. {
  590. if (m_nCurrentToken == OPATH_TOK_EOF)
  591. return NoError;
  592. if (m_nCurrentToken != OPATH_TOK_COLON)
  593. return SyntaxError;
  594. if (!NextToken())
  595. return SyntaxError;
  596. return objref();
  597. }
  598. //
  599. // <ns_or_class> ::= COLON <ident_becomes_ns> <objref>;
  600. // <ns_or_class> ::= BACKSLASH <ident_becomes_ns> <ns_list> COLON <objref>;
  601. // <ns_or_class> ::= BACKSLASH <ident_becomes_ns> <ns_list>;
  602. //
  603. int CObjectPathParser::ns_or_class()
  604. {
  605. if (m_nCurrentToken == OPATH_TOK_COLON)
  606. {
  607. ident_becomes_ns();
  608. if (!NextToken())
  609. return SyntaxError;
  610. return objref();
  611. }
  612. else if (m_nCurrentToken == OPATH_TOK_BACKSLASH)
  613. {
  614. ident_becomes_ns();
  615. if (!NextToken())
  616. return SyntaxError;
  617. int nRes = ns_list();
  618. if (nRes)
  619. return nRes;
  620. if (m_nCurrentToken == OPATH_TOK_EOF) // ns only
  621. return NoError;
  622. if (m_nCurrentToken != OPATH_TOK_COLON)
  623. return SyntaxError;
  624. if (!NextToken())
  625. return SyntaxError;
  626. return objref();
  627. }
  628. // Else
  629. // ====
  630. ident_becomes_class();
  631. return objref_rest();
  632. }
  633. //
  634. // <objref> ::= IDENT <objref_rest>; // IDENT is classname
  635. //
  636. int CObjectPathParser::objref()
  637. {
  638. if (m_nCurrentToken != OPATH_TOK_IDENT)
  639. return SyntaxError;
  640. m_pOutput->m_pClass = Macro_CloneLPWSTR(m_pLexer->GetTokenText());
  641. if (!NextToken())
  642. return SyntaxError;
  643. return objref_rest();
  644. }
  645. //
  646. // <ns_list> ::= IDENT <ns_list_rest>;
  647. //
  648. int CObjectPathParser::ns_list()
  649. {
  650. if (m_nCurrentToken == OPATH_TOK_IDENT)
  651. {
  652. m_pOutput->AddNamespace(m_pLexer->GetTokenText());
  653. if (!NextToken())
  654. return SyntaxError;
  655. return ns_list_rest();
  656. }
  657. return SyntaxError;
  658. }
  659. //
  660. // <ident_becomes_ns> ::= <>; // <initial_ident> becomes a namespace
  661. //
  662. int CObjectPathParser::ident_becomes_ns()
  663. {
  664. m_pOutput->AddNamespace(m_pInitialIdent);
  665. delete m_pInitialIdent;
  666. m_pInitialIdent = 0;
  667. return NoError;
  668. }
  669. //
  670. // <ident_becomes_class> ::= <>; // <initial_ident> becomes the class
  671. //
  672. int CObjectPathParser::ident_becomes_class()
  673. {
  674. m_pOutput->m_pClass = Macro_CloneLPWSTR(m_pInitialIdent);
  675. delete m_pInitialIdent;
  676. m_pInitialIdent = 0;
  677. return NoError;
  678. }
  679. //
  680. // <objref_rest> ::= EQUALS <key_const>;
  681. // <objref_rest> ::= EQUALS *;
  682. // <objref_rest> ::= DOT <keyref_list>;
  683. // <objref_rest> ::= <>;
  684. //
  685. int CObjectPathParser::objref_rest()
  686. {
  687. if (m_nCurrentToken == OPATH_TOK_EQ)
  688. {
  689. if (!NextToken())
  690. return SyntaxError;
  691. // Take care of the singleton case. This is a path of the form
  692. // MyClass=@ and represents a singleton instance of a class with no
  693. // keys.
  694. if(m_nCurrentToken == OPATH_TOK_SINGLETON_SYM)
  695. {
  696. if(NextToken() && m_nCurrentToken != OPATH_TOK_EOF)
  697. return SyntaxError;
  698. m_pOutput->m_bSingletonObj = TRUE;
  699. return NoError;
  700. }
  701. m_pTmpKeyRef = new KeyRef;
  702. int nRes = key_const();
  703. if (nRes)
  704. {
  705. delete m_pTmpKeyRef;
  706. m_pTmpKeyRef = 0;
  707. return nRes;
  708. }
  709. m_pOutput->AddKeyRef(m_pTmpKeyRef);
  710. m_pTmpKeyRef = 0;
  711. }
  712. else if (m_nCurrentToken == OPATH_TOK_DOT)
  713. {
  714. if (!NextToken())
  715. return SyntaxError;
  716. return keyref_list();
  717. }
  718. return NoError;
  719. }
  720. //
  721. // <ns_list_rest> ::= BACKSLASH <ns_list>;
  722. // <ns_list_rest> ::= <>;
  723. //
  724. int CObjectPathParser::ns_list_rest()
  725. {
  726. if (m_nCurrentToken == OPATH_TOK_BACKSLASH)
  727. {
  728. if (!NextToken())
  729. return SyntaxError;
  730. return ns_list();
  731. }
  732. return NoError;
  733. }
  734. //
  735. // <key_const> ::= STRING_CONST;
  736. // <key_const> ::= INTEGRAL_CONST;
  737. // <key_const> ::= REAL_CONST;
  738. // <key_const> ::= IDENT; // Where IDENT is "OBJECT" for singleton classes
  739. //
  740. int CObjectPathParser::key_const()
  741. {
  742. // If here, we have a key constant.
  743. // We may or may not have the property name
  744. // associated with it.
  745. // ========================================
  746. if (m_nCurrentToken == OPATH_TOK_QSTRING)
  747. {
  748. V_VT(&m_pTmpKeyRef->m_vValue) = VT_BSTR;
  749. V_BSTR(&m_pTmpKeyRef->m_vValue) = SysAllocString(m_pLexer->GetTokenText());
  750. }
  751. else if (m_nCurrentToken == OPATH_TOK_INT)
  752. {
  753. V_VT(&m_pTmpKeyRef->m_vValue) = VT_I4;
  754. char buf[32];
  755. if(m_pLexer->GetTokenText() == NULL || wcslen(m_pLexer->GetTokenText()) > 31)
  756. return SyntaxError;
  757. sprintf(buf, "%S", m_pLexer->GetTokenText());
  758. V_I4(&m_pTmpKeyRef->m_vValue) = atol(buf);
  759. }
  760. else if (m_nCurrentToken == OPATH_TOK_HEXINT)
  761. {
  762. V_VT(&m_pTmpKeyRef->m_vValue) = VT_I4;
  763. char buf[32];
  764. if(m_pLexer->GetTokenText() == NULL || wcslen(m_pLexer->GetTokenText()) > 31)
  765. return SyntaxError;
  766. sprintf(buf, "%S", m_pLexer->GetTokenText());
  767. long l;
  768. sscanf(buf, "%x", &l);
  769. V_I4(&m_pTmpKeyRef->m_vValue) = l;
  770. }
  771. else if (m_nCurrentToken == OPATH_TOK_IDENT)
  772. {
  773. if (_wcsicmp(m_pLexer->GetTokenText(), L"TRUE") == 0)
  774. {
  775. V_VT(&m_pTmpKeyRef->m_vValue) = VT_I4;
  776. V_I4(&m_pTmpKeyRef->m_vValue) = 1;
  777. }
  778. else if (_wcsicmp(m_pLexer->GetTokenText(), L"FALSE") == 0)
  779. {
  780. V_VT(&m_pTmpKeyRef->m_vValue) = VT_I4;
  781. V_I4(&m_pTmpKeyRef->m_vValue) = 0;
  782. }
  783. else
  784. return SyntaxError;
  785. }
  786. else return SyntaxError;
  787. if (!NextToken())
  788. return SyntaxError;
  789. return NoError;
  790. }
  791. //
  792. // <keyref_list> ::= <keyref> <keyref_term>;
  793. //
  794. int CObjectPathParser::keyref_list()
  795. {
  796. int nRes = keyref();
  797. if (nRes)
  798. return nRes;
  799. return keyref_term();
  800. }
  801. //
  802. // <keyref> ::= <propname> EQUALS <key_const>;
  803. //
  804. int CObjectPathParser::keyref()
  805. {
  806. m_pTmpKeyRef = new KeyRef;
  807. int nRes = propname();
  808. if (nRes)
  809. {
  810. delete m_pTmpKeyRef;
  811. m_pTmpKeyRef = 0;
  812. return nRes;
  813. }
  814. if (m_nCurrentToken != OPATH_TOK_EQ)
  815. {
  816. delete m_pTmpKeyRef;
  817. m_pTmpKeyRef = 0;
  818. return SyntaxError;
  819. }
  820. if (!NextToken())
  821. {
  822. delete m_pTmpKeyRef;
  823. m_pTmpKeyRef = 0;
  824. return SyntaxError;
  825. }
  826. nRes = key_const();
  827. if (nRes)
  828. {
  829. delete m_pTmpKeyRef;
  830. m_pTmpKeyRef = 0;
  831. return nRes;
  832. }
  833. m_pOutput->AddKeyRef(m_pTmpKeyRef);
  834. m_pTmpKeyRef = 0;
  835. return NoError;
  836. }
  837. //
  838. // <keyref_term> ::= COMMA <keyref_list>; // Used for compound keys
  839. // <keyref_term> ::= <>;
  840. //
  841. int CObjectPathParser::keyref_term()
  842. {
  843. if (m_nCurrentToken == OPATH_TOK_COMMA)
  844. {
  845. if (!NextToken())
  846. return SyntaxError;
  847. return keyref_list();
  848. }
  849. return NoError;
  850. }
  851. //
  852. // <propname> ::= IDENT;
  853. //
  854. int CObjectPathParser::propname()
  855. {
  856. if (m_nCurrentToken != OPATH_TOK_IDENT)
  857. return SyntaxError;
  858. m_pTmpKeyRef->m_pName = Macro_CloneLPWSTR(m_pLexer->GetTokenText());
  859. if (!NextToken())
  860. {
  861. delete m_pTmpKeyRef;
  862. m_pTmpKeyRef = 0;
  863. return SyntaxError;
  864. }
  865. return NoError;
  866. }
  867. //***************************************************************************
  868. //
  869. // ParsedObjectPath::GetKeyString
  870. //
  871. // Returns the db-engine compatible key string for the object.
  872. // The format will likely change after the Alpha PDK Release.
  873. //
  874. // Return value:
  875. // NULL on error or for pure classes. Otherwise returns a pointer to
  876. // a newly allocated string which must be deallocated with operator
  877. // delete.
  878. //
  879. //***************************************************************************
  880. LPWSTR ParsedObjectPath::GetKeyString()
  881. {
  882. if (m_dwNumKeys == 0 && !m_bSingletonObj)
  883. {
  884. if (m_pClass == 0 || wcslen(m_pClass) == 0)
  885. return 0;
  886. LPWSTR pTmp = new wchar_t[wcslen(m_pClass) + 1];
  887. wcscpy(pTmp, m_pClass);
  888. return pTmp;
  889. }
  890. // Allocate enough space
  891. // =====================
  892. int nSpace = 10;
  893. DWORD dwIx;
  894. for (dwIx = 0; dwIx < m_dwNumKeys; dwIx++)
  895. {
  896. KeyRef* pKey = m_paKeys[dwIx];
  897. nSpace += 2; // for the |
  898. if(V_VT(&pKey->m_vValue) == VT_BSTR)
  899. {
  900. nSpace += wcslen(V_BSTR(&pKey->m_vValue))*2 + 10;
  901. }
  902. else if(V_VT(&pKey->m_vValue) == VT_I4)
  903. {
  904. nSpace += 30;
  905. }
  906. }
  907. if(m_bSingletonObj)
  908. nSpace +=20;
  909. LPWSTR pRetVal = new wchar_t[nSpace];
  910. wchar_t Tmp[32];
  911. long nVal;
  912. *pRetVal = 0;
  913. BOOL bFirst = TRUE;
  914. // The key are already sorted lexically.
  915. // =====================================
  916. WCHAR wszSeparator[2];
  917. wszSeparator[0] = 0xFFFF;
  918. wszSeparator[1] = 0;
  919. for (DWORD i = 0; i < m_dwNumKeys; i++)
  920. {
  921. if (!bFirst)
  922. wcscat(pRetVal, wszSeparator);
  923. bFirst = FALSE;
  924. KeyRef *pKeyRef = m_paKeys[i];
  925. VARIANT *pv = &pKeyRef->m_vValue;
  926. int nType = V_VT(pv);
  927. switch (nType)
  928. {
  929. case VT_LPWSTR:
  930. case VT_BSTR:
  931. wcscat(pRetVal, V_BSTR(pv));
  932. break;
  933. case VT_I4:
  934. nVal = V_I4(pv);
  935. swprintf(Tmp, L"%d", nVal);
  936. wcscat(pRetVal, Tmp);
  937. break;
  938. case VT_I2:
  939. nVal = V_I2(pv);
  940. swprintf(Tmp, L"%d", nVal);
  941. wcscat(pRetVal, Tmp);
  942. break;
  943. case VT_UI1:
  944. nVal = V_UI1(pv);
  945. swprintf(Tmp, L"%d", nVal);
  946. wcscat(pRetVal, Tmp);
  947. break;
  948. case VT_BOOL:
  949. nVal = V_BOOL(pv);
  950. swprintf(Tmp, L"%d", (nVal?1:0));
  951. wcscat(pRetVal, Tmp);
  952. break;
  953. default:
  954. wcscat(pRetVal, L"NULL");
  955. }
  956. }
  957. if (wcslen(pRetVal) == 0)
  958. {
  959. if(m_bSingletonObj)
  960. {
  961. wcscpy(pRetVal, L"@");
  962. }
  963. }
  964. return pRetVal; // This may not be NULL
  965. }
  966. LPWSTR ParsedObjectPath::GetNamespacePart()
  967. {
  968. if (m_dwNumNamespaces == 0)
  969. return NULL;
  970. // Compute necessary space
  971. // =======================
  972. int nSpace = 0;
  973. for(DWORD i = 0; i < m_dwNumNamespaces; i++)
  974. nSpace += 1 + wcslen(m_paNamespaces[i]);
  975. nSpace--;
  976. // Allocate buffer
  977. // ===============
  978. LPWSTR wszOut = new wchar_t[nSpace + 1];
  979. *wszOut = 0;
  980. // Output
  981. // ======
  982. for(i = 0; i < m_dwNumNamespaces; i++)
  983. {
  984. if(i != 0) wcscat(wszOut, L"\\");
  985. wcscat(wszOut, m_paNamespaces[i]);
  986. }
  987. return wszOut;
  988. }
  989. LPWSTR ParsedObjectPath::GetParentNamespacePart()
  990. {
  991. if(m_dwNumNamespaces < 2)
  992. return NULL;
  993. // Compute necessary space
  994. // =======================
  995. int nSpace = 0;
  996. for(DWORD i = 0; i < m_dwNumNamespaces - 1; i++)
  997. nSpace += 1 + wcslen(m_paNamespaces[i]);
  998. nSpace--;
  999. // Allocate buffer
  1000. // ===============
  1001. LPWSTR wszOut = new wchar_t[nSpace + 1];
  1002. *wszOut = 0;
  1003. // Output
  1004. // ======
  1005. for(i = 0; i < m_dwNumNamespaces - 1; i++)
  1006. {
  1007. if(i != 0) wcscat(wszOut, L"\\");
  1008. wcscat(wszOut, m_paNamespaces[i]);
  1009. }
  1010. return wszOut;
  1011. }
  1012. BOOL ParsedObjectPath::IsRelative(LPCWSTR wszMachine, LPCWSTR wszNamespace)
  1013. {
  1014. if(!IsLocal(wszMachine))
  1015. return FALSE;
  1016. if(m_dwNumNamespaces == 0)
  1017. return TRUE;
  1018. LPWSTR wszCopy = new wchar_t[wcslen(wszNamespace) + 1];
  1019. wcscpy(wszCopy, wszNamespace);
  1020. LPWSTR wszLeft = wszCopy;
  1021. BOOL bFailed = FALSE;
  1022. for(DWORD i = 0; i < m_dwNumNamespaces; i++)
  1023. {
  1024. unsigned int nLen = wcslen(m_paNamespaces[i]);
  1025. if(nLen > wcslen(wszLeft))
  1026. {
  1027. bFailed = TRUE;
  1028. break;
  1029. }
  1030. if(i == m_dwNumNamespaces - 1 && wszLeft[nLen] != 0)
  1031. {
  1032. bFailed = TRUE;
  1033. break;
  1034. }
  1035. if(i != m_dwNumNamespaces - 1 && wszLeft[nLen] != L'\\')
  1036. {
  1037. bFailed = TRUE;
  1038. break;
  1039. }
  1040. wszLeft[nLen] = 0;
  1041. if(_wcsicmp(wszLeft, m_paNamespaces[i]))
  1042. {
  1043. bFailed = TRUE;
  1044. break;
  1045. }
  1046. wszLeft += nLen+1;
  1047. }
  1048. delete [] wszCopy;
  1049. return !bFailed;
  1050. }
  1051. BOOL ParsedObjectPath::IsLocal(LPCWSTR wszMachine)
  1052. {
  1053. return (m_pServer == NULL || !_wcsicmp(m_pServer, L".") ||
  1054. !_wcsicmp(m_pServer, wszMachine));
  1055. }
  1056. ////////////////////////////////////////////////////////
  1057. //
  1058. // Test object path parser by parsing all objects
  1059. // in the input file (one object path per line).
  1060. //
  1061. ////////////////////////////////////////////////////////
  1062. #ifdef TEST
  1063. void xmain(int argc, char **argv)
  1064. {
  1065. printf("Object Path Test\n");
  1066. if (argc < 2 || strchr(argv[1], '?') != NULL)
  1067. {
  1068. printf("Usage: objpath input-file\n");
  1069. return;
  1070. }
  1071. int nLine = 1;
  1072. char buf[2048];
  1073. FILE *f = fopen(argv[1], "rt");
  1074. if (f == NULL)
  1075. {
  1076. printf("Usage: objpath input-file\nError: cannot open file %s!\n", argv[1]);
  1077. return;
  1078. }
  1079. while (fgets(buf, 2048, f) != NULL)
  1080. {
  1081. // Get rid of newline and trailing spaces.
  1082. // =======================================
  1083. char* ptr = strchr(buf, '\n');
  1084. if (ptr != NULL)
  1085. {
  1086. *ptr = ' ';
  1087. while (ptr >= buf && *ptr == ' ')
  1088. {
  1089. *ptr = '\0';
  1090. ptr--;
  1091. }
  1092. }
  1093. // Get rid of leading spaces.
  1094. // ==========================
  1095. ptr = buf;
  1096. while (*ptr == ' ')
  1097. {
  1098. ptr++;
  1099. }
  1100. // Convert to wide char and parse. Ignore blank lines.
  1101. // ====================================================
  1102. if (*ptr != '\0')
  1103. {
  1104. wchar_t buf2[2048];
  1105. MultiByteToWideChar(CP_ACP, 0, ptr, -1, buf2, 2048);
  1106. printf("----Object path----\n");
  1107. printf("%S\n", buf2);
  1108. ParsedObjectPath* pOutput = 0;
  1109. CObjectPathParser p(e_ParserAcceptAll);
  1110. int nStatus = p.Parse(buf2, &pOutput);
  1111. if (nStatus != 0)
  1112. {
  1113. printf("ERROR: return code is %d\n", nStatus);
  1114. continue;
  1115. }
  1116. printf("No errors.\n");
  1117. printf("------Output------\n");
  1118. LPWSTR pKey = pOutput->GetKeyString();
  1119. printf("Key String = <%S>\n", pKey);
  1120. delete pKey;
  1121. printf("Server = %S\n", pOutput->m_pServer);
  1122. printf("Namespace Part = %S\n", pOutput->GetNamespacePart());
  1123. printf("Parent Part = %S\n", pOutput->GetParentNamespacePart());
  1124. for (DWORD dwIx = 0; dwIx < pOutput->m_dwNumNamespaces; dwIx++)
  1125. {
  1126. printf("Namespace = <%S>\n", pOutput->m_paNamespaces[dwIx]);
  1127. }
  1128. printf("Class = <%S>\n", pOutput->m_pClass);
  1129. // If here, the key ref is complete.
  1130. // =================================
  1131. for (dwIx = 0; dwIx < pOutput->m_dwNumKeys; dwIx++)
  1132. {
  1133. KeyRef *pTmp = pOutput->m_paKeys[dwIx];
  1134. printf("*** KeyRef contents:\n");
  1135. printf(" Name = %S Value=", pTmp->m_pName);
  1136. switch (V_VT(&pTmp->m_vValue))
  1137. {
  1138. case VT_I4: printf("%d", V_I4(&pTmp->m_vValue)); break;
  1139. case VT_R8: printf("%f", V_R8(&pTmp->m_vValue)); break;
  1140. case VT_BSTR: printf("<%S>", V_BSTR(&pTmp->m_vValue)); break;
  1141. default:
  1142. printf("BAD KEY REF\n");
  1143. }
  1144. printf("\n");
  1145. }
  1146. p.Free(pOutput);
  1147. }
  1148. }
  1149. }
  1150. void main(int argc, char **argv)
  1151. {
  1152. xmain(argc, argv);
  1153. }
  1154. #endif