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.

1324 lines
33 KiB

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