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.

1381 lines
35 KiB

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