home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / netds / adsi / sampprov / parse.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-29  |  13.6 KB  |  583 lines

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