|
|
//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1997.
//
// File: parse.cxx
//
// Contents: IIS Pathname Parser
//
// The Pathname Parser is a key component in ADs providers. It checks for
// syntactic validity of an ADs pathname that has been passed to this
// provider. If the syntax is valid, then an OBJECTINFO structure is
// constructed. This OBJECTINFO structure contains a componentized version
// of the ADs pathname for this object.
//
// Note all that is being done is a syntax check. Rather than special-case
// every single new nuance to pathnames, all path checking must conform to
// the grammar rules laid out by the parser.
//
//
//
// History:
//----------------------------------------------------------------------------
#include "iis.hxx"
#pragma hdrstop
KWDLIST KeywordList[MAX_KEYWORDS] = { { TOKEN_SCHEMA, SCHEMA_CLASS_NAME}, { TOKEN_CLASS, CLASS_CLASS_NAME }, { TOKEN_PROPERTY, PROPERTY_CLASS_NAME }, { TOKEN_SYNTAX, SYNTAX_CLASS_NAME }, };
// Object -> PathName, Type, eos
// Object -> PathName, eos
//+---------------------------------------------------------------------------
// Function: ADsObject
//
// Synopsis: parses an ADs pathname passed to this provider. This function
// parses the following grammar rules
//
// <ADsObject> -> <ProviderName> <IISObject>
//
//
// Arguments: [CLexer * pTokenizer] - a lexical analyzer object
// [POBJECTINFO pObjectInfo] - a pointer to an OBJECTINFO structure
//
// Returns: [HRESULT] 0 if successful, error HRESULT if not
//
// Modifies: pTokenizer (consumes the input buffer)
//
//----------------------------------------------------------------------------
HRESULT ADsObject(CLexer * pTokenizer, POBJECTINFO pObjectInfo) { WCHAR szToken[MAX_TOKEN_LENGTH]; DWORD dwToken; HRESULT hr;
hr = ProviderName(pTokenizer, pObjectInfo); BAIL_IF_ERROR(hr);
pObjectInfo->ObjectType = TOKEN_IISOBJECT; pObjectInfo->ComponentArray = NULL;
hr = pTokenizer->GetNextToken(szToken, &dwToken); BAIL_IF_ERROR(hr);
switch (dwToken) {
case TOKEN_END: RRETURN(S_OK);
case TOKEN_COMMA: hr = Type(pTokenizer, pObjectInfo); BAIL_IF_ERROR(hr); hr = pTokenizer->GetNextToken(szToken, &dwToken); BAIL_IF_ERROR(hr); if (dwToken == TOKEN_END) { RRETURN(S_OK); }else { RRETURN(E_ADS_BAD_PATHNAME); }
default: hr = pTokenizer->PushBackToken();
hr = IISObject(pTokenizer, pObjectInfo); BAIL_IF_ERROR(hr);
hr = pTokenizer->GetNextToken(szToken, &dwToken); BAIL_IF_ERROR(hr);
switch (dwToken) { case TOKEN_END: RRETURN(S_OK);
case TOKEN_COMMA: hr = Type(pTokenizer, pObjectInfo); BAIL_IF_ERROR(hr); hr = pTokenizer->GetNextToken(szToken, &dwToken); BAIL_IF_ERROR(hr); if (dwToken == TOKEN_END) { RRETURN(S_OK); }else { RRETURN(E_ADS_BAD_PATHNAME); }
default: RRETURN(E_FAIL);
} }
cleanup: RRETURN(hr);
}
//+---------------------------------------------------------------------------
// Function: IISObject
//
// Synopsis: parses an ADs pathname passed to this provider. This function
// parses the following grammar rules
//
// <IISObject> -> "\\""identifier""\" <IISObject>
//
//
// Arguments: [CLexer * pTokenizer] - a lexical analyzer object
// [POBJECTINFO pObjectInfo] - a pointer to an OBJECTINFO structure
//
// Returns: [HRESULT] 0 if successful, error HRESULT if not
//
// Modifies: pTokenizer (consumes the input buffer)
//
//----------------------------------------------------------------------------
HRESULT IISObject(CLexer * pTokenizer, POBJECTINFO pObjectInfo) { WCHAR szToken[MAX_TOKEN_LENGTH]; DWORD dwToken; HRESULT hr;
hr = pTokenizer->GetNextToken(szToken, &dwToken); BAIL_IF_ERROR(hr); if ((dwToken != TOKEN_FSLASH) && (dwToken != TOKEN_BSLASH)) { RRETURN(E_ADS_BAD_PATHNAME); }
hr = pTokenizer->GetNextToken(szToken, &dwToken); BAIL_IF_ERROR(hr); if ((dwToken != TOKEN_FSLASH) && (dwToken != TOKEN_BSLASH)) { RRETURN(E_ADS_BAD_PATHNAME); }
hr = pTokenizer->GetNextToken(szToken, &dwToken); BAIL_IF_ERROR(hr); if (dwToken != TOKEN_IDENTIFIER) { RRETURN(E_ADS_BAD_PATHNAME); }
hr = AddTreeName(pObjectInfo, szToken); BAIL_IF_ERROR(hr);
hr = pTokenizer->GetNextToken(szToken, &dwToken); BAIL_IF_ERROR(hr);
//
// If we get an TOKEN_END, then we have a tree name only \\<tree_name>
//
if (dwToken == TOKEN_END || dwToken == TOKEN_COMMA) { hr = pTokenizer->PushBackToken(); RRETURN(S_OK); }
if ((dwToken != TOKEN_BSLASH) && (dwToken != TOKEN_FSLASH)) { RRETURN(E_ADS_BAD_PATHNAME); }
hr = PathName(pTokenizer, pObjectInfo); BAIL_IF_ERROR(hr);
cleanup: RRETURN(hr); }
HRESULT ProviderName(CLexer * pTokenizer, POBJECTINFO pObjectInfo) { WCHAR szToken[MAX_TOKEN_LENGTH]; DWORD dwToken; HRESULT hr;
hr = pTokenizer->GetNextToken(szToken, &dwToken); BAIL_IF_ERROR(hr);
if (dwToken == TOKEN_ATSIGN) {
hr = pTokenizer->GetNextToken(szToken, &dwToken); BAIL_IF_ERROR(hr);
if (dwToken != TOKEN_IDENTIFIER) { RRETURN(E_ADS_BAD_PATHNAME); }
hr = AddProviderName(pObjectInfo, szToken);
hr = pTokenizer->GetNextToken(szToken, &dwToken); BAIL_IF_ERROR(hr);
if (dwToken != TOKEN_EXCLAMATION) { RRETURN(E_ADS_BAD_PATHNAME); }
}else if (dwToken == TOKEN_IDENTIFIER) {
hr = AddProviderName(pObjectInfo, szToken);
hr = pTokenizer->GetNextToken(szToken, &dwToken); BAIL_IF_ERROR(hr);
if (dwToken != TOKEN_COLON) { RRETURN(E_ADS_BAD_PATHNAME); }
}else { RRETURN(E_ADS_BAD_PATHNAME); }
//
// You can now disable the processing for "@" and "!" treat them
// as ordinary characters.
//
pTokenizer->SetAtDisabler(TRUE);
RRETURN(S_OK);
cleanup:
RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function:
//
// Synopsis:
//
// Arguments:
//
// Returns:
//
// Modifies:
//
//----------------------------------------------------------------------------
HRESULT PathName(CLexer * pTokenizer, POBJECTINFO pObjectInfo) { HRESULT hr; WCHAR szToken[MAX_TOKEN_LENGTH]; DWORD dwToken;
do { hr = Component(pTokenizer, pObjectInfo); BAIL_IF_ERROR(hr);
hr = pTokenizer->GetNextToken(szToken, &dwToken); BAIL_IF_ERROR(hr); } while( (dwToken == TOKEN_BSLASH) || (dwToken == TOKEN_FSLASH) );
hr = pTokenizer->PushBackToken(); BAIL_IF_ERROR(hr);
cleanup: RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function:
//
// Synopsis: Component -> <identifier>
//
// Arguments:
//
// Returns:
//
// Modifies:
//
//----------------------------------------------------------------------------
HRESULT Component(CLexer * pTokenizer, POBJECTINFO pObjectInfo) { WCHAR szComponent[MAX_TOKEN_LENGTH]; DWORD dwToken; HRESULT hr;
hr = pTokenizer->GetNextToken(szComponent, &dwToken); BAIL_IF_ERROR(hr);
if (dwToken != TOKEN_IDENTIFIER) { RRETURN(E_ADS_BAD_PATHNAME); }
hr = AddComponent(pObjectInfo, szComponent, NULL); BAIL_IF_ERROR(hr);
cleanup: RRETURN(hr); }
//+---------------------------------------------------------------------------
// Function:
//
// Synopsis:
//
// Arguments:
//
// Returns:
//
// Modifies:
//
//----------------------------------------------------------------------------
CLexer::CLexer(LPWSTR szBuffer): _ptr(NULL), _Buffer(NULL), _dwLastTokenLength(0), _dwLastToken(0), _dwEndofString(0), _bAtDisabled(FALSE) { if (!szBuffer || !*szBuffer) { return; } _Buffer = AllocADsStr(szBuffer); _ptr = _Buffer; }
//+---------------------------------------------------------------------------
// Function:
//
// Synopsis:
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 08-12-96 t-danal Created.
//
//----------------------------------------------------------------------------
CLexer::~CLexer() { FreeADsStr(_Buffer); }
/*++
This routine assumes that szToken is a buffer of at least MAX_TOKEN_LENGTH --*/ HRESULT CLexer::GetNextToken(LPWSTR szToken, LPDWORD pdwToken) { WCHAR c; DWORD state = 0; LPWSTR pch = szToken;
memset(szToken, 0, sizeof(WCHAR) * MAX_TOKEN_LENGTH); _dwLastTokenLength = 0; while (1) { c = NextChar(); switch (state) { case 0: if (_dwLastTokenLength++ >= MAX_TOKEN_LENGTH) { RRETURN(RETURNCODETOHRESULT(ERROR_INVALID_NAME)); } *pch++ = c;
if (c == L'\\') { *pdwToken = TOKEN_BSLASH; _dwLastToken = *pdwToken; RRETURN(S_OK); }else if (c == L'/') { *pdwToken = TOKEN_FSLASH; _dwLastToken = *pdwToken; RRETURN(S_OK); }else if (c == L',') { *pdwToken = TOKEN_COMMA; _dwLastToken = *pdwToken; RRETURN(S_OK); }else if (c == L'='){ *pdwToken = TOKEN_EQUAL; _dwLastToken = *pdwToken; RRETURN(S_OK); } else if (c == L':'){ *pdwToken = TOKEN_COLON; _dwLastToken = *pdwToken; RRETURN(S_OK); }else if (c == L'\0'){ *pdwToken = TOKEN_END; _dwLastToken = *pdwToken; RRETURN(S_OK); }else if (c == L'@') {
if (!_bAtDisabled) {
*pdwToken = TOKEN_ATSIGN; _dwLastToken = *pdwToken; RRETURN(S_OK);
}else { state = 1; }
}else if (c == L'!'){
if (!_bAtDisabled) {
*pdwToken = TOKEN_EXCLAMATION; _dwLastToken = *pdwToken; RRETURN(S_OK);
}else { state = 1; }
}else {
state = 1; } break;
case 1: if (c == L'\\' || c == L'\0' || c == L',' || c == L'=' || c == L':' || c == L'/') { PushbackChar();
*pdwToken = TOKEN_IDENTIFIER; _dwLastToken = *pdwToken; RRETURN (S_OK);
}else if (c == L'@' || c == L'!') {
if (!_bAtDisabled) {
PushbackChar();
*pdwToken = TOKEN_IDENTIFIER; _dwLastToken = *pdwToken; RRETURN(S_OK);
}else {
if (_dwLastTokenLength++ >= MAX_TOKEN_LENGTH) { RRETURN(RETURNCODETOHRESULT(ERROR_INVALID_NAME)); } *pch++ = c; state = 1; break;
}
}else { if (_dwLastTokenLength++ >= MAX_TOKEN_LENGTH) { RRETURN(RETURNCODETOHRESULT(ERROR_INVALID_NAME)); } *pch++ = c; state = 1; break; }
default: RRETURN(RETURNCODETOHRESULT(ERROR_INVALID_NAME)); } } }
//+---------------------------------------------------------------------------
// Function:
//
// Synopsis:
//
// Arguments:
//
// Returns:
//
// Modifies:
//
//----------------------------------------------------------------------------
WCHAR CLexer::NextChar() { if (_ptr == NULL || *_ptr == L'\0') { _dwEndofString = TRUE; return(L'\0'); } return(*_ptr++); }
//+---------------------------------------------------------------------------
// Function:
//
// Synopsis:
//
// Arguments:
//
// Returns:
//
// Modifies:
//
//----------------------------------------------------------------------------
HRESULT CLexer::PushBackToken() { if (_dwLastToken == TOKEN_END) { RRETURN(S_OK); } _ptr -= _dwLastTokenLength;
RRETURN(S_OK); }
//+---------------------------------------------------------------------------
// Function:
//
// Synopsis:
//
// Arguments:
//
// Returns:
//
// Modifies:
//
//----------------------------------------------------------------------------
void CLexer::PushbackChar() { if (_dwEndofString) { return; } _ptr--;
}
//+---------------------------------------------------------------------------
// Function:
//
// Synopsis:
//
// Arguments:
//
// Returns:
//
// Modifies:
//
//----------------------------------------------------------------------------
BOOL CLexer::IsKeyword(LPWSTR szToken, LPDWORD pdwToken) { DWORD i = 0;
for (i = 0; i < MAX_KEYWORDS; i++) { if (!_wcsicmp(szToken, KeywordList[i].Keyword)) { *pdwToken = KeywordList[i].dwTokenId; return(TRUE); } } *pdwToken = 0; return(FALSE); }
//+---------------------------------------------------------------------------
//Function:
//
//Synopsis:
//
//Arguments:
//
//Returns:
//
//Modifies:
//
//History: 11-3-95 krishnag Created.
//
//----------------------------------------------------------------------------
HRESULT AddComponent(POBJECTINFO pObjectInfo, LPWSTR szComponent, LPWSTR szValue) { if (!szComponent || !*szComponent) { RRETURN(E_FAIL); }
if (pObjectInfo->ComponentArray == NULL) { pObjectInfo->ComponentArray = (PCOMPONENT) AllocADsMem(sizeof(COMPONENT)*MAXCOMPONENTS); pObjectInfo->MaxComponents = MAXCOMPONENTS; } else if (pObjectInfo->NumComponents == pObjectInfo->MaxComponents) { pObjectInfo->ComponentArray = (PCOMPONENT) ReallocADsMem( pObjectInfo->ComponentArray, sizeof(COMPONENT)*pObjectInfo->MaxComponents, sizeof(COMPONENT)*( pObjectInfo->MaxComponents+MAXCOMPONENTS) ); pObjectInfo->MaxComponents += MAXCOMPONENTS; }
pObjectInfo->ComponentArray[pObjectInfo->NumComponents].szComponent = AllocADsStr(szComponent);
if (szValue && *szValue) { pObjectInfo->ComponentArray[pObjectInfo->NumComponents].szValue = AllocADsStr(szValue); } else { pObjectInfo->ComponentArray[pObjectInfo->NumComponents].szValue = NULL; }
pObjectInfo->NumComponents++;
RRETURN(S_OK); }
HRESULT AddProviderName(POBJECTINFO pObjectInfo, LPWSTR szToken) { if (!szToken || !*szToken) { RRETURN(E_FAIL); }
pObjectInfo->ProviderName = AllocADsStr(szToken);
RRETURN(S_OK); }
HRESULT AddTreeName(POBJECTINFO pObjectInfo, LPWSTR szToken) { if (!szToken || !*szToken) { RRETURN(E_FAIL); }
pObjectInfo->TreeName = AllocADsStr(szToken);
RRETURN(S_OK); }
HRESULT AddClassName(POBJECTINFO pObjectInfo, LPWSTR szToken) { if (!szToken || !*szToken) { RRETURN(E_FAIL); }
wcscpy(pObjectInfo->ClassName, szToken);
RRETURN(S_OK); }
//+---------------------------------------------------------------------------
// Function:
//
// Synopsis:
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 11-3-95 krishnag Created.
//
//----------------------------------------------------------------------------
HRESULT SetType(POBJECTINFO pObjectInfo, DWORD dwToken) { pObjectInfo->ObjectType = dwToken; RRETURN(S_OK); }
//+---------------------------------------------------------------------------
// Function: Type
//
// Synopsis: Parses Type-> "user" | "group" etc
//
// Arguments: [CLexer * pTokenizer]
// [POBJECTINFo pObjectInfo]
//
// Returns: HRESULT
//
// Modifies: -
//
// History: 11-3-95 krishnag Created.
//
//----------------------------------------------------------------------------
HRESULT Type(CLexer * pTokenizer, POBJECTINFO pObjectInfo) { WCHAR szToken[MAX_TOKEN_LENGTH]; DWORD dwToken; HRESULT hr;
hr = pTokenizer->GetNextToken(szToken, &dwToken); BAIL_IF_ERROR(hr);
if (dwToken == TOKEN_IDENTIFIER ) { if (pTokenizer->IsKeyword(szToken, &dwToken)) { hr = SetType(pObjectInfo, dwToken); RRETURN(hr); } hr = AddClassName(pObjectInfo, szToken); RRETURN(hr); }
RRETURN(E_FAIL);
cleanup: RRETURN(hr); }
void CLexer::SetAtDisabler( BOOL bFlag ) { _bAtDisabled = bFlag; }
BOOL CLexer::GetAtDisabler() { return(_bAtDisabled); }
|