Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

760 lines
17 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1997.
  5. //
  6. // File: parse.cxx
  7. //
  8. // Contents: IIS Pathname Parser
  9. //
  10. // The Pathname Parser is a key component in ADs providers. It checks for
  11. // syntactic validity of an ADs pathname that has been passed to this
  12. // provider. If the syntax is valid, then an OBJECTINFO structure is
  13. // constructed. This OBJECTINFO structure contains a componentized version
  14. // of the ADs pathname for this object.
  15. //
  16. // Note all that is being done is a syntax check. Rather than special-case
  17. // every single new nuance to pathnames, all path checking must conform to
  18. // the grammar rules laid out by the parser.
  19. //
  20. //
  21. //
  22. // History:
  23. //----------------------------------------------------------------------------
  24. #include "iis.hxx"
  25. #pragma hdrstop
  26. KWDLIST KeywordList[MAX_KEYWORDS] =
  27. {
  28. { TOKEN_SCHEMA, SCHEMA_CLASS_NAME},
  29. { TOKEN_CLASS, CLASS_CLASS_NAME },
  30. { TOKEN_PROPERTY, PROPERTY_CLASS_NAME },
  31. { TOKEN_SYNTAX, SYNTAX_CLASS_NAME },
  32. };
  33. // Object -> PathName, Type, eos
  34. // Object -> PathName, eos
  35. //+---------------------------------------------------------------------------
  36. // Function: ADsObject
  37. //
  38. // Synopsis: parses an ADs pathname passed to this provider. This function
  39. // parses the following grammar rules
  40. //
  41. // <ADsObject> -> <ProviderName> <IISObject>
  42. //
  43. //
  44. // Arguments: [CLexer * pTokenizer] - a lexical analyzer object
  45. // [POBJECTINFO pObjectInfo] - a pointer to an OBJECTINFO structure
  46. //
  47. // Returns: [HRESULT] 0 if successful, error HRESULT if not
  48. //
  49. // Modifies: pTokenizer (consumes the input buffer)
  50. //
  51. //----------------------------------------------------------------------------
  52. HRESULT
  53. ADsObject(CLexer * pTokenizer, POBJECTINFO pObjectInfo)
  54. {
  55. WCHAR szToken[MAX_TOKEN_LENGTH];
  56. DWORD dwToken;
  57. HRESULT hr;
  58. hr = ProviderName(pTokenizer, pObjectInfo);
  59. BAIL_IF_ERROR(hr);
  60. pObjectInfo->ObjectType = TOKEN_IISOBJECT;
  61. pObjectInfo->ComponentArray = NULL;
  62. hr = pTokenizer->GetNextToken(szToken, &dwToken);
  63. BAIL_IF_ERROR(hr);
  64. switch (dwToken) {
  65. case TOKEN_END:
  66. RRETURN(S_OK);
  67. case TOKEN_COMMA:
  68. hr = Type(pTokenizer, pObjectInfo);
  69. BAIL_IF_ERROR(hr);
  70. hr = pTokenizer->GetNextToken(szToken, &dwToken);
  71. BAIL_IF_ERROR(hr);
  72. if (dwToken == TOKEN_END) {
  73. RRETURN(S_OK);
  74. }else {
  75. RRETURN(E_ADS_BAD_PATHNAME);
  76. }
  77. default:
  78. hr = pTokenizer->PushBackToken();
  79. hr = IISObject(pTokenizer, pObjectInfo);
  80. BAIL_IF_ERROR(hr);
  81. hr = pTokenizer->GetNextToken(szToken, &dwToken);
  82. BAIL_IF_ERROR(hr);
  83. switch (dwToken) {
  84. case TOKEN_END:
  85. RRETURN(S_OK);
  86. case TOKEN_COMMA:
  87. hr = Type(pTokenizer, pObjectInfo);
  88. BAIL_IF_ERROR(hr);
  89. hr = pTokenizer->GetNextToken(szToken, &dwToken);
  90. BAIL_IF_ERROR(hr);
  91. if (dwToken == TOKEN_END) {
  92. RRETURN(S_OK);
  93. }else {
  94. RRETURN(E_ADS_BAD_PATHNAME);
  95. }
  96. default:
  97. RRETURN(E_FAIL);
  98. }
  99. }
  100. cleanup:
  101. RRETURN(hr);
  102. }
  103. //+---------------------------------------------------------------------------
  104. // Function: IISObject
  105. //
  106. // Synopsis: parses an ADs pathname passed to this provider. This function
  107. // parses the following grammar rules
  108. //
  109. // <IISObject> -> "\\""identifier""\" <IISObject>
  110. //
  111. //
  112. // Arguments: [CLexer * pTokenizer] - a lexical analyzer object
  113. // [POBJECTINFO pObjectInfo] - a pointer to an OBJECTINFO structure
  114. //
  115. // Returns: [HRESULT] 0 if successful, error HRESULT if not
  116. //
  117. // Modifies: pTokenizer (consumes the input buffer)
  118. //
  119. //----------------------------------------------------------------------------
  120. HRESULT
  121. IISObject(CLexer * pTokenizer, POBJECTINFO pObjectInfo)
  122. {
  123. WCHAR szToken[MAX_TOKEN_LENGTH];
  124. DWORD dwToken;
  125. HRESULT hr;
  126. hr = pTokenizer->GetNextToken(szToken, &dwToken);
  127. BAIL_IF_ERROR(hr);
  128. if ((dwToken != TOKEN_FSLASH) && (dwToken != TOKEN_BSLASH)) {
  129. RRETURN(E_ADS_BAD_PATHNAME);
  130. }
  131. hr = pTokenizer->GetNextToken(szToken, &dwToken);
  132. BAIL_IF_ERROR(hr);
  133. if ((dwToken != TOKEN_FSLASH) && (dwToken != TOKEN_BSLASH)) {
  134. RRETURN(E_ADS_BAD_PATHNAME);
  135. }
  136. hr = pTokenizer->GetNextToken(szToken, &dwToken);
  137. BAIL_IF_ERROR(hr);
  138. if (dwToken != TOKEN_IDENTIFIER) {
  139. RRETURN(E_ADS_BAD_PATHNAME);
  140. }
  141. hr = AddTreeName(pObjectInfo, szToken);
  142. BAIL_IF_ERROR(hr);
  143. hr = pTokenizer->GetNextToken(szToken, &dwToken);
  144. BAIL_IF_ERROR(hr);
  145. //
  146. // If we get an TOKEN_END, then we have a tree name only \\<tree_name>
  147. //
  148. if (dwToken == TOKEN_END || dwToken == TOKEN_COMMA) {
  149. hr = pTokenizer->PushBackToken();
  150. RRETURN(S_OK);
  151. }
  152. if ((dwToken != TOKEN_BSLASH) && (dwToken != TOKEN_FSLASH)) {
  153. RRETURN(E_ADS_BAD_PATHNAME);
  154. }
  155. hr = PathName(pTokenizer, pObjectInfo);
  156. BAIL_IF_ERROR(hr);
  157. cleanup:
  158. RRETURN(hr);
  159. }
  160. HRESULT
  161. ProviderName(CLexer * pTokenizer, POBJECTINFO pObjectInfo)
  162. {
  163. WCHAR szToken[MAX_TOKEN_LENGTH];
  164. DWORD dwToken;
  165. HRESULT hr;
  166. hr = pTokenizer->GetNextToken(szToken, &dwToken);
  167. BAIL_IF_ERROR(hr);
  168. if (dwToken == TOKEN_ATSIGN) {
  169. hr = pTokenizer->GetNextToken(szToken, &dwToken);
  170. BAIL_IF_ERROR(hr);
  171. if (dwToken != TOKEN_IDENTIFIER) {
  172. RRETURN(E_ADS_BAD_PATHNAME);
  173. }
  174. hr = AddProviderName(pObjectInfo, szToken);
  175. hr = pTokenizer->GetNextToken(szToken, &dwToken);
  176. BAIL_IF_ERROR(hr);
  177. if (dwToken != TOKEN_EXCLAMATION) {
  178. RRETURN(E_ADS_BAD_PATHNAME);
  179. }
  180. }else if (dwToken == TOKEN_IDENTIFIER) {
  181. hr = AddProviderName(pObjectInfo, szToken);
  182. hr = pTokenizer->GetNextToken(szToken, &dwToken);
  183. BAIL_IF_ERROR(hr);
  184. if (dwToken != TOKEN_COLON) {
  185. RRETURN(E_ADS_BAD_PATHNAME);
  186. }
  187. }else {
  188. RRETURN(E_ADS_BAD_PATHNAME);
  189. }
  190. //
  191. // You can now disable the processing for "@" and "!" treat them
  192. // as ordinary characters.
  193. //
  194. pTokenizer->SetAtDisabler(TRUE);
  195. RRETURN(S_OK);
  196. cleanup:
  197. RRETURN(hr);
  198. }
  199. //+---------------------------------------------------------------------------
  200. // Function:
  201. //
  202. // Synopsis:
  203. //
  204. // Arguments:
  205. //
  206. // Returns:
  207. //
  208. // Modifies:
  209. //
  210. //----------------------------------------------------------------------------
  211. HRESULT
  212. PathName(CLexer * pTokenizer, POBJECTINFO pObjectInfo)
  213. {
  214. HRESULT hr;
  215. WCHAR szToken[MAX_TOKEN_LENGTH];
  216. DWORD dwToken;
  217. do
  218. {
  219. hr = Component(pTokenizer, pObjectInfo);
  220. BAIL_IF_ERROR(hr);
  221. hr = pTokenizer->GetNextToken(szToken, &dwToken);
  222. BAIL_IF_ERROR(hr);
  223. }
  224. while( (dwToken == TOKEN_BSLASH) || (dwToken == TOKEN_FSLASH) );
  225. hr = pTokenizer->PushBackToken();
  226. BAIL_IF_ERROR(hr);
  227. cleanup:
  228. RRETURN(hr);
  229. }
  230. //+---------------------------------------------------------------------------
  231. // Function:
  232. //
  233. // Synopsis: Component -> <identifier>
  234. //
  235. // Arguments:
  236. //
  237. // Returns:
  238. //
  239. // Modifies:
  240. //
  241. //----------------------------------------------------------------------------
  242. HRESULT
  243. Component(CLexer * pTokenizer, POBJECTINFO pObjectInfo)
  244. {
  245. WCHAR szValue[MAX_TOKEN_LENGTH];
  246. WCHAR szComponent[MAX_TOKEN_LENGTH];
  247. DWORD dwToken;
  248. HRESULT hr;
  249. hr = pTokenizer->GetNextToken(szComponent, &dwToken);
  250. BAIL_IF_ERROR(hr);
  251. if (dwToken != TOKEN_IDENTIFIER) {
  252. RRETURN(E_ADS_BAD_PATHNAME);
  253. }
  254. hr = AddComponent(pObjectInfo, szComponent, NULL);
  255. BAIL_IF_ERROR(hr);
  256. cleanup:
  257. RRETURN(hr);
  258. }
  259. //+---------------------------------------------------------------------------
  260. // Function:
  261. //
  262. // Synopsis:
  263. //
  264. // Arguments:
  265. //
  266. // Returns:
  267. //
  268. // Modifies:
  269. //
  270. //----------------------------------------------------------------------------
  271. CLexer::CLexer(LPWSTR szBuffer):
  272. _ptr(NULL),
  273. _Buffer(NULL),
  274. _dwLastTokenLength(0),
  275. _dwLastToken(0),
  276. _dwEndofString(0),
  277. _bAtDisabled(FALSE)
  278. {
  279. if (!szBuffer || !*szBuffer) {
  280. return;
  281. }
  282. _Buffer = AllocADsStr(szBuffer);
  283. _ptr = _Buffer;
  284. }
  285. //+---------------------------------------------------------------------------
  286. // Function:
  287. //
  288. // Synopsis:
  289. //
  290. // Arguments:
  291. //
  292. // Returns:
  293. //
  294. // Modifies:
  295. //
  296. // History: 08-12-96 t-danal Created.
  297. //
  298. //----------------------------------------------------------------------------
  299. CLexer::~CLexer()
  300. {
  301. FreeADsStr(_Buffer);
  302. }
  303. /*++
  304. This routine assumes that szToken is a buffer of at least MAX_TOKEN_LENGTH
  305. --*/
  306. HRESULT
  307. CLexer::GetNextToken(LPWSTR szToken, LPDWORD pdwToken)
  308. {
  309. WCHAR c;
  310. DWORD state = 0;
  311. LPWSTR pch = szToken;
  312. memset(szToken, 0, sizeof(WCHAR) * MAX_TOKEN_LENGTH);
  313. _dwLastTokenLength = 0;
  314. while (1) {
  315. c = NextChar();
  316. switch (state) {
  317. case 0:
  318. if (_dwLastTokenLength++ >= MAX_TOKEN_LENGTH) {
  319. RRETURN(RETURNCODETOHRESULT(ERROR_INVALID_NAME));
  320. }
  321. *pch++ = c;
  322. if (c == L'\\') {
  323. *pdwToken = TOKEN_BSLASH;
  324. _dwLastToken = *pdwToken;
  325. RRETURN(S_OK);
  326. }else if (c == L'/') {
  327. *pdwToken = TOKEN_FSLASH;
  328. _dwLastToken = *pdwToken;
  329. RRETURN(S_OK);
  330. }else if (c == L',') {
  331. *pdwToken = TOKEN_COMMA;
  332. _dwLastToken = *pdwToken;
  333. RRETURN(S_OK);
  334. }else if (c == L'='){
  335. *pdwToken = TOKEN_EQUAL;
  336. _dwLastToken = *pdwToken;
  337. RRETURN(S_OK);
  338. }
  339. else if (c == L':'){
  340. *pdwToken = TOKEN_COLON;
  341. _dwLastToken = *pdwToken;
  342. RRETURN(S_OK);
  343. }else if (c == L'\0'){
  344. *pdwToken = TOKEN_END;
  345. _dwLastToken = *pdwToken;
  346. RRETURN(S_OK);
  347. }else if (c == L'@') {
  348. if (!_bAtDisabled) {
  349. *pdwToken = TOKEN_ATSIGN;
  350. _dwLastToken = *pdwToken;
  351. RRETURN(S_OK);
  352. }else {
  353. state = 1;
  354. }
  355. }else if (c == L'!'){
  356. if (!_bAtDisabled) {
  357. *pdwToken = TOKEN_EXCLAMATION;
  358. _dwLastToken = *pdwToken;
  359. RRETURN(S_OK);
  360. }else {
  361. state = 1;
  362. }
  363. }else {
  364. state = 1;
  365. }
  366. break;
  367. case 1:
  368. if (c == L'\\' || c == L'\0' || c == L',' ||
  369. c == L'=' ||
  370. c == L':' || c == L'/') {
  371. PushbackChar();
  372. *pdwToken = TOKEN_IDENTIFIER;
  373. _dwLastToken = *pdwToken;
  374. RRETURN (S_OK);
  375. }else if (c == L'@' || c == L'!') {
  376. if (!_bAtDisabled) {
  377. PushbackChar();
  378. *pdwToken = TOKEN_IDENTIFIER;
  379. _dwLastToken = *pdwToken;
  380. RRETURN(S_OK);
  381. }else {
  382. if (_dwLastTokenLength++ >= MAX_TOKEN_LENGTH) {
  383. RRETURN(RETURNCODETOHRESULT(ERROR_INVALID_NAME));
  384. }
  385. *pch++ = c;
  386. state = 1;
  387. break;
  388. }
  389. }else {
  390. if (_dwLastTokenLength++ >= MAX_TOKEN_LENGTH) {
  391. RRETURN(RETURNCODETOHRESULT(ERROR_INVALID_NAME));
  392. }
  393. *pch++ = c;
  394. state = 1;
  395. break;
  396. }
  397. default:
  398. RRETURN(RETURNCODETOHRESULT(ERROR_INVALID_NAME));
  399. }
  400. }
  401. }
  402. //+---------------------------------------------------------------------------
  403. // Function:
  404. //
  405. // Synopsis:
  406. //
  407. // Arguments:
  408. //
  409. // Returns:
  410. //
  411. // Modifies:
  412. //
  413. //----------------------------------------------------------------------------
  414. WCHAR
  415. CLexer::NextChar()
  416. {
  417. if (_ptr == NULL || *_ptr == L'\0') {
  418. _dwEndofString = TRUE;
  419. return(L'\0');
  420. }
  421. return(*_ptr++);
  422. }
  423. //+---------------------------------------------------------------------------
  424. // Function:
  425. //
  426. // Synopsis:
  427. //
  428. // Arguments:
  429. //
  430. // Returns:
  431. //
  432. // Modifies:
  433. //
  434. //----------------------------------------------------------------------------
  435. HRESULT
  436. CLexer::PushBackToken()
  437. {
  438. if (_dwLastToken == TOKEN_END) {
  439. RRETURN(S_OK);
  440. }
  441. _ptr -= _dwLastTokenLength;
  442. RRETURN(S_OK);
  443. }
  444. //+---------------------------------------------------------------------------
  445. // Function:
  446. //
  447. // Synopsis:
  448. //
  449. // Arguments:
  450. //
  451. // Returns:
  452. //
  453. // Modifies:
  454. //
  455. //----------------------------------------------------------------------------
  456. void
  457. CLexer::PushbackChar()
  458. {
  459. if (_dwEndofString) {
  460. return;
  461. }
  462. _ptr--;
  463. }
  464. //+---------------------------------------------------------------------------
  465. // Function:
  466. //
  467. // Synopsis:
  468. //
  469. // Arguments:
  470. //
  471. // Returns:
  472. //
  473. // Modifies:
  474. //
  475. //----------------------------------------------------------------------------
  476. BOOL
  477. CLexer::IsKeyword(LPWSTR szToken, LPDWORD pdwToken)
  478. {
  479. DWORD i = 0;
  480. for (i = 0; i < MAX_KEYWORDS; i++) {
  481. if (!_wcsicmp(szToken, KeywordList[i].Keyword)) {
  482. *pdwToken = KeywordList[i].dwTokenId;
  483. return(TRUE);
  484. }
  485. }
  486. *pdwToken = 0;
  487. return(FALSE);
  488. }
  489. //+---------------------------------------------------------------------------
  490. //Function:
  491. //
  492. //Synopsis:
  493. //
  494. //Arguments:
  495. //
  496. //Returns:
  497. //
  498. //Modifies:
  499. //
  500. //History: 11-3-95 krishnag Created.
  501. //
  502. //----------------------------------------------------------------------------
  503. HRESULT
  504. AddComponent(POBJECTINFO pObjectInfo, LPWSTR szComponent, LPWSTR szValue)
  505. {
  506. if (!szComponent || !*szComponent) {
  507. RRETURN(E_FAIL);
  508. }
  509. if (pObjectInfo->ComponentArray == NULL) {
  510. pObjectInfo->ComponentArray =
  511. (PCOMPONENT) AllocADsMem(sizeof(COMPONENT)*MAXCOMPONENTS);
  512. pObjectInfo->MaxComponents = MAXCOMPONENTS;
  513. }
  514. else if (pObjectInfo->NumComponents == pObjectInfo->MaxComponents) {
  515. pObjectInfo->ComponentArray =
  516. (PCOMPONENT) ReallocADsMem(
  517. pObjectInfo->ComponentArray,
  518. sizeof(COMPONENT)*pObjectInfo->MaxComponents,
  519. sizeof(COMPONENT)*(
  520. pObjectInfo->MaxComponents+MAXCOMPONENTS)
  521. );
  522. pObjectInfo->MaxComponents += MAXCOMPONENTS;
  523. }
  524. pObjectInfo->ComponentArray[pObjectInfo->NumComponents].szComponent =
  525. AllocADsStr(szComponent);
  526. if (szValue && *szValue) {
  527. pObjectInfo->ComponentArray[pObjectInfo->NumComponents].szValue =
  528. AllocADsStr(szValue);
  529. }
  530. else {
  531. pObjectInfo->ComponentArray[pObjectInfo->NumComponents].szValue = NULL;
  532. }
  533. pObjectInfo->NumComponents++;
  534. RRETURN(S_OK);
  535. }
  536. HRESULT
  537. AddProviderName(POBJECTINFO pObjectInfo, LPWSTR szToken)
  538. {
  539. if (!szToken || !*szToken) {
  540. RRETURN(E_FAIL);
  541. }
  542. pObjectInfo->ProviderName = AllocADsStr(szToken);
  543. RRETURN(S_OK);
  544. }
  545. HRESULT
  546. AddTreeName(POBJECTINFO pObjectInfo, LPWSTR szToken)
  547. {
  548. if (!szToken || !*szToken) {
  549. RRETURN(E_FAIL);
  550. }
  551. pObjectInfo->TreeName = AllocADsStr(szToken);
  552. RRETURN(S_OK);
  553. }
  554. HRESULT
  555. AddClassName(POBJECTINFO pObjectInfo, LPWSTR szToken)
  556. {
  557. if (!szToken || !*szToken) {
  558. RRETURN(E_FAIL);
  559. }
  560. wcscpy(pObjectInfo->ClassName, szToken);
  561. RRETURN(S_OK);
  562. }
  563. //+---------------------------------------------------------------------------
  564. // Function:
  565. //
  566. // Synopsis:
  567. //
  568. // Arguments:
  569. //
  570. // Returns:
  571. //
  572. // Modifies:
  573. //
  574. // History: 11-3-95 krishnag Created.
  575. //
  576. //----------------------------------------------------------------------------
  577. HRESULT
  578. SetType(POBJECTINFO pObjectInfo, DWORD dwToken)
  579. {
  580. pObjectInfo->ObjectType = dwToken;
  581. RRETURN(S_OK);
  582. }
  583. //+---------------------------------------------------------------------------
  584. // Function: Type
  585. //
  586. // Synopsis: Parses Type-> "user" | "group" etc
  587. //
  588. // Arguments: [CLexer * pTokenizer]
  589. // [POBJECTINFo pObjectInfo]
  590. //
  591. // Returns: HRESULT
  592. //
  593. // Modifies: -
  594. //
  595. // History: 11-3-95 krishnag Created.
  596. //
  597. //----------------------------------------------------------------------------
  598. HRESULT
  599. Type(CLexer * pTokenizer, POBJECTINFO pObjectInfo)
  600. {
  601. WCHAR szToken[MAX_PATH];
  602. DWORD dwToken;
  603. HRESULT hr;
  604. hr = pTokenizer->GetNextToken(szToken, &dwToken);
  605. BAIL_IF_ERROR(hr);
  606. if (dwToken == TOKEN_IDENTIFIER ) {
  607. if (pTokenizer->IsKeyword(szToken, &dwToken)) {
  608. hr = SetType(pObjectInfo, dwToken);
  609. RRETURN(hr);
  610. }
  611. hr = AddClassName(pObjectInfo, szToken);
  612. RRETURN(hr);
  613. }
  614. RRETURN(E_FAIL);
  615. cleanup:
  616. RRETURN(hr);
  617. }
  618. void
  619. CLexer::SetAtDisabler(
  620. BOOL bFlag
  621. )
  622. {
  623. _bAtDisabled = bFlag;
  624. }
  625. BOOL
  626. CLexer::GetAtDisabler()
  627. {
  628. return(_bAtDisabled);
  629. }