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.

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