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.

759 lines
18 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 szComponent[MAX_TOKEN_LENGTH];
  246. DWORD dwToken;
  247. HRESULT hr;
  248. hr = pTokenizer->GetNextToken(szComponent, &dwToken);
  249. BAIL_IF_ERROR(hr);
  250. if (dwToken != TOKEN_IDENTIFIER) {
  251. RRETURN(E_ADS_BAD_PATHNAME);
  252. }
  253. hr = AddComponent(pObjectInfo, szComponent, NULL);
  254. BAIL_IF_ERROR(hr);
  255. cleanup:
  256. RRETURN(hr);
  257. }
  258. //+---------------------------------------------------------------------------
  259. // Function:
  260. //
  261. // Synopsis:
  262. //
  263. // Arguments:
  264. //
  265. // Returns:
  266. //
  267. // Modifies:
  268. //
  269. //----------------------------------------------------------------------------
  270. CLexer::CLexer(LPWSTR szBuffer):
  271. _ptr(NULL),
  272. _Buffer(NULL),
  273. _dwLastTokenLength(0),
  274. _dwLastToken(0),
  275. _dwEndofString(0),
  276. _bAtDisabled(FALSE)
  277. {
  278. if (!szBuffer || !*szBuffer) {
  279. return;
  280. }
  281. _Buffer = AllocADsStr(szBuffer);
  282. _ptr = _Buffer;
  283. }
  284. //+---------------------------------------------------------------------------
  285. // Function:
  286. //
  287. // Synopsis:
  288. //
  289. // Arguments:
  290. //
  291. // Returns:
  292. //
  293. // Modifies:
  294. //
  295. // History: 08-12-96 t-danal Created.
  296. //
  297. //----------------------------------------------------------------------------
  298. CLexer::~CLexer()
  299. {
  300. FreeADsStr(_Buffer);
  301. }
  302. /*++
  303. This routine assumes that szToken is a buffer of at least MAX_TOKEN_LENGTH
  304. --*/
  305. HRESULT
  306. CLexer::GetNextToken(LPWSTR szToken, LPDWORD pdwToken)
  307. {
  308. WCHAR c;
  309. DWORD state = 0;
  310. LPWSTR pch = szToken;
  311. memset(szToken, 0, sizeof(WCHAR) * MAX_TOKEN_LENGTH);
  312. _dwLastTokenLength = 0;
  313. while (1) {
  314. c = NextChar();
  315. switch (state) {
  316. case 0:
  317. if (_dwLastTokenLength++ >= MAX_TOKEN_LENGTH) {
  318. RRETURN(RETURNCODETOHRESULT(ERROR_INVALID_NAME));
  319. }
  320. *pch++ = c;
  321. if (c == L'\\') {
  322. *pdwToken = TOKEN_BSLASH;
  323. _dwLastToken = *pdwToken;
  324. RRETURN(S_OK);
  325. }else if (c == L'/') {
  326. *pdwToken = TOKEN_FSLASH;
  327. _dwLastToken = *pdwToken;
  328. RRETURN(S_OK);
  329. }else if (c == L',') {
  330. *pdwToken = TOKEN_COMMA;
  331. _dwLastToken = *pdwToken;
  332. RRETURN(S_OK);
  333. }else if (c == L'='){
  334. *pdwToken = TOKEN_EQUAL;
  335. _dwLastToken = *pdwToken;
  336. RRETURN(S_OK);
  337. }
  338. else if (c == L':'){
  339. *pdwToken = TOKEN_COLON;
  340. _dwLastToken = *pdwToken;
  341. RRETURN(S_OK);
  342. }else if (c == L'\0'){
  343. *pdwToken = TOKEN_END;
  344. _dwLastToken = *pdwToken;
  345. RRETURN(S_OK);
  346. }else if (c == L'@') {
  347. if (!_bAtDisabled) {
  348. *pdwToken = TOKEN_ATSIGN;
  349. _dwLastToken = *pdwToken;
  350. RRETURN(S_OK);
  351. }else {
  352. state = 1;
  353. }
  354. }else if (c == L'!'){
  355. if (!_bAtDisabled) {
  356. *pdwToken = TOKEN_EXCLAMATION;
  357. _dwLastToken = *pdwToken;
  358. RRETURN(S_OK);
  359. }else {
  360. state = 1;
  361. }
  362. }else {
  363. state = 1;
  364. }
  365. break;
  366. case 1:
  367. if (c == L'\\' || c == L'\0' || c == L',' ||
  368. c == L'=' ||
  369. c == L':' || c == L'/') {
  370. PushbackChar();
  371. *pdwToken = TOKEN_IDENTIFIER;
  372. _dwLastToken = *pdwToken;
  373. RRETURN (S_OK);
  374. }else if (c == L'@' || c == L'!') {
  375. if (!_bAtDisabled) {
  376. PushbackChar();
  377. *pdwToken = TOKEN_IDENTIFIER;
  378. _dwLastToken = *pdwToken;
  379. RRETURN(S_OK);
  380. }else {
  381. if (_dwLastTokenLength++ >= MAX_TOKEN_LENGTH) {
  382. RRETURN(RETURNCODETOHRESULT(ERROR_INVALID_NAME));
  383. }
  384. *pch++ = c;
  385. state = 1;
  386. break;
  387. }
  388. }else {
  389. if (_dwLastTokenLength++ >= MAX_TOKEN_LENGTH) {
  390. RRETURN(RETURNCODETOHRESULT(ERROR_INVALID_NAME));
  391. }
  392. *pch++ = c;
  393. state = 1;
  394. break;
  395. }
  396. default:
  397. RRETURN(RETURNCODETOHRESULT(ERROR_INVALID_NAME));
  398. }
  399. }
  400. }
  401. //+---------------------------------------------------------------------------
  402. // Function:
  403. //
  404. // Synopsis:
  405. //
  406. // Arguments:
  407. //
  408. // Returns:
  409. //
  410. // Modifies:
  411. //
  412. //----------------------------------------------------------------------------
  413. WCHAR
  414. CLexer::NextChar()
  415. {
  416. if (_ptr == NULL || *_ptr == L'\0') {
  417. _dwEndofString = TRUE;
  418. return(L'\0');
  419. }
  420. return(*_ptr++);
  421. }
  422. //+---------------------------------------------------------------------------
  423. // Function:
  424. //
  425. // Synopsis:
  426. //
  427. // Arguments:
  428. //
  429. // Returns:
  430. //
  431. // Modifies:
  432. //
  433. //----------------------------------------------------------------------------
  434. HRESULT
  435. CLexer::PushBackToken()
  436. {
  437. if (_dwLastToken == TOKEN_END) {
  438. RRETURN(S_OK);
  439. }
  440. _ptr -= _dwLastTokenLength;
  441. RRETURN(S_OK);
  442. }
  443. //+---------------------------------------------------------------------------
  444. // Function:
  445. //
  446. // Synopsis:
  447. //
  448. // Arguments:
  449. //
  450. // Returns:
  451. //
  452. // Modifies:
  453. //
  454. //----------------------------------------------------------------------------
  455. void
  456. CLexer::PushbackChar()
  457. {
  458. if (_dwEndofString) {
  459. return;
  460. }
  461. _ptr--;
  462. }
  463. //+---------------------------------------------------------------------------
  464. // Function:
  465. //
  466. // Synopsis:
  467. //
  468. // Arguments:
  469. //
  470. // Returns:
  471. //
  472. // Modifies:
  473. //
  474. //----------------------------------------------------------------------------
  475. BOOL
  476. CLexer::IsKeyword(LPWSTR szToken, LPDWORD pdwToken)
  477. {
  478. DWORD i = 0;
  479. for (i = 0; i < MAX_KEYWORDS; i++) {
  480. if (!_wcsicmp(szToken, KeywordList[i].Keyword)) {
  481. *pdwToken = KeywordList[i].dwTokenId;
  482. return(TRUE);
  483. }
  484. }
  485. *pdwToken = 0;
  486. return(FALSE);
  487. }
  488. //+---------------------------------------------------------------------------
  489. //Function:
  490. //
  491. //Synopsis:
  492. //
  493. //Arguments:
  494. //
  495. //Returns:
  496. //
  497. //Modifies:
  498. //
  499. //History: 11-3-95 krishnag Created.
  500. //
  501. //----------------------------------------------------------------------------
  502. HRESULT
  503. AddComponent(POBJECTINFO pObjectInfo, LPWSTR szComponent, LPWSTR szValue)
  504. {
  505. if (!szComponent || !*szComponent) {
  506. RRETURN(E_FAIL);
  507. }
  508. if (pObjectInfo->ComponentArray == NULL) {
  509. pObjectInfo->ComponentArray =
  510. (PCOMPONENT) AllocADsMem(sizeof(COMPONENT)*MAXCOMPONENTS);
  511. pObjectInfo->MaxComponents = MAXCOMPONENTS;
  512. }
  513. else if (pObjectInfo->NumComponents == pObjectInfo->MaxComponents) {
  514. pObjectInfo->ComponentArray =
  515. (PCOMPONENT) ReallocADsMem(
  516. pObjectInfo->ComponentArray,
  517. sizeof(COMPONENT)*pObjectInfo->MaxComponents,
  518. sizeof(COMPONENT)*(
  519. pObjectInfo->MaxComponents+MAXCOMPONENTS)
  520. );
  521. pObjectInfo->MaxComponents += MAXCOMPONENTS;
  522. }
  523. pObjectInfo->ComponentArray[pObjectInfo->NumComponents].szComponent =
  524. AllocADsStr(szComponent);
  525. if (szValue && *szValue) {
  526. pObjectInfo->ComponentArray[pObjectInfo->NumComponents].szValue =
  527. AllocADsStr(szValue);
  528. }
  529. else {
  530. pObjectInfo->ComponentArray[pObjectInfo->NumComponents].szValue = NULL;
  531. }
  532. pObjectInfo->NumComponents++;
  533. RRETURN(S_OK);
  534. }
  535. HRESULT
  536. AddProviderName(POBJECTINFO pObjectInfo, LPWSTR szToken)
  537. {
  538. if (!szToken || !*szToken) {
  539. RRETURN(E_FAIL);
  540. }
  541. pObjectInfo->ProviderName = AllocADsStr(szToken);
  542. RRETURN(S_OK);
  543. }
  544. HRESULT
  545. AddTreeName(POBJECTINFO pObjectInfo, LPWSTR szToken)
  546. {
  547. if (!szToken || !*szToken) {
  548. RRETURN(E_FAIL);
  549. }
  550. pObjectInfo->TreeName = AllocADsStr(szToken);
  551. RRETURN(S_OK);
  552. }
  553. HRESULT
  554. AddClassName(POBJECTINFO pObjectInfo, LPWSTR szToken)
  555. {
  556. if (!szToken || !*szToken) {
  557. RRETURN(E_FAIL);
  558. }
  559. wcscpy(pObjectInfo->ClassName, szToken);
  560. RRETURN(S_OK);
  561. }
  562. //+---------------------------------------------------------------------------
  563. // Function:
  564. //
  565. // Synopsis:
  566. //
  567. // Arguments:
  568. //
  569. // Returns:
  570. //
  571. // Modifies:
  572. //
  573. // History: 11-3-95 krishnag Created.
  574. //
  575. //----------------------------------------------------------------------------
  576. HRESULT
  577. SetType(POBJECTINFO pObjectInfo, DWORD dwToken)
  578. {
  579. pObjectInfo->ObjectType = dwToken;
  580. RRETURN(S_OK);
  581. }
  582. //+---------------------------------------------------------------------------
  583. // Function: Type
  584. //
  585. // Synopsis: Parses Type-> "user" | "group" etc
  586. //
  587. // Arguments: [CLexer * pTokenizer]
  588. // [POBJECTINFo pObjectInfo]
  589. //
  590. // Returns: HRESULT
  591. //
  592. // Modifies: -
  593. //
  594. // History: 11-3-95 krishnag Created.
  595. //
  596. //----------------------------------------------------------------------------
  597. HRESULT
  598. Type(CLexer * pTokenizer, POBJECTINFO pObjectInfo)
  599. {
  600. WCHAR szToken[MAX_TOKEN_LENGTH];
  601. DWORD dwToken;
  602. HRESULT hr;
  603. hr = pTokenizer->GetNextToken(szToken, &dwToken);
  604. BAIL_IF_ERROR(hr);
  605. if (dwToken == TOKEN_IDENTIFIER ) {
  606. if (pTokenizer->IsKeyword(szToken, &dwToken)) {
  607. hr = SetType(pObjectInfo, dwToken);
  608. RRETURN(hr);
  609. }
  610. hr = AddClassName(pObjectInfo, szToken);
  611. RRETURN(hr);
  612. }
  613. RRETURN(E_FAIL);
  614. cleanup:
  615. RRETURN(hr);
  616. }
  617. void
  618. CLexer::SetAtDisabler(
  619. BOOL bFlag
  620. )
  621. {
  622. _bAtDisabled = bFlag;
  623. }
  624. BOOL
  625. CLexer::GetAtDisabler()
  626. {
  627. return(_bAtDisabled);
  628. }