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.
1556 lines
36 KiB
1556 lines
36 KiB
//--------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1996
|
|
//
|
|
// File: parse.cxx
|
|
//
|
|
// Contents: LDAP 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 <stdlib.h>
|
|
#include "ldapc.hxx"
|
|
|
|
#pragma hdrstop
|
|
|
|
// Object -> PathName, Type, eos
|
|
// Object -> PathName, eos
|
|
|
|
KWDLIST KeywordList[] =
|
|
{
|
|
{ TOKEN_DOMAIN, DOMAIN_CLASS_NAME },
|
|
{ TOKEN_USER, USER_CLASS_NAME },
|
|
{ TOKEN_GROUP, GROUP_CLASS_NAME },
|
|
{ TOKEN_COMPUTER, COMPUTER_CLASS_NAME },
|
|
{ TOKEN_PRINTER, PRINTER_CLASS_NAME },
|
|
{ TOKEN_SERVICE, SERVICE_CLASS_NAME },
|
|
{ TOKEN_FILESERVICE, FILESERVICE_CLASS_NAME },
|
|
{ TOKEN_FILESHARE, FILESHARE_CLASS_NAME },
|
|
{ TOKEN_SCHEMA, SCHEMA_CLASS_NAME },
|
|
{ TOKEN_CLASS, CLASS_CLASS_NAME },
|
|
{ TOKEN_PROPERTY, PROPERTY_CLASS_NAME },
|
|
{ TOKEN_SYNTAX, SYNTAX_CLASS_NAME },
|
|
{ TOKEN_LOCALITY, LOCALITY_CLASS_NAME },
|
|
{ TOKEN_ORGANIZATION, ORGANIZATION_CLASS_NAME },
|
|
{ TOKEN_ORGANIZATIONUNIT, ORGANIZATIONUNIT_CLASS_NAME },
|
|
{ TOKEN_COUNTRY, COUNTRY_CLASS_NAME },
|
|
{ TOKEN_ROOTDSE, ROOTDSE_CLASS_NAME}
|
|
};
|
|
|
|
|
|
DWORD gdwKeywordListSize = sizeof(KeywordList)/sizeof(KWDLIST);
|
|
|
|
HRESULT
|
|
InitObjectInfo(
|
|
LPWSTR pszADsPathName,
|
|
POBJECTINFO pObjectInfo
|
|
)
|
|
{
|
|
DWORD dwLen = 0;
|
|
HRESULT hr = S_OK;
|
|
|
|
ADsAssert(pObjectInfo);
|
|
ADsAssert(pszADsPathName);
|
|
|
|
memset(pObjectInfo, 0x0, sizeof(OBJECTINFO));
|
|
|
|
dwLen = wcslen(pszADsPathName) * sizeof(WCHAR) * 3;
|
|
if( dwLen ) {
|
|
pObjectInfo->szStrBuf = (LPWSTR) AllocADsMem(dwLen);
|
|
pObjectInfo->szDisplayStrBuf = (LPWSTR) AllocADsMem(dwLen);
|
|
|
|
if (!pObjectInfo->szStrBuf || !pObjectInfo->szDisplayStrBuf) {
|
|
RRETURN(E_OUTOFMEMORY);
|
|
}
|
|
|
|
pObjectInfo->szStrBufPtr = pObjectInfo->szStrBuf;
|
|
pObjectInfo->szDisplayStrBufPtr = pObjectInfo->szDisplayStrBuf;
|
|
}
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
VOID
|
|
FreeObjectInfo(
|
|
POBJECTINFO pObjectInfo
|
|
)
|
|
{
|
|
if ( !pObjectInfo )
|
|
return;
|
|
|
|
if (pObjectInfo->szStrBuf) {
|
|
FreeADsStr( pObjectInfo->szStrBuf );
|
|
}
|
|
if (pObjectInfo->szDisplayStrBuf) {
|
|
FreeADsStr( pObjectInfo->szDisplayStrBuf );
|
|
}
|
|
}
|
|
|
|
|
|
HRESULT
|
|
ADsObject(
|
|
LPWSTR pszADsPathName,
|
|
POBJECTINFO pObjectInfo
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CLexer Lexer;
|
|
hr = Lexer.InitializePath(pszADsPathName);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
hr = InitObjectInfo(pszADsPathName, pObjectInfo);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
pObjectInfo->ObjectType = TOKEN_LDAPOBJECT;
|
|
|
|
hr = ADsObjectParse(&Lexer, pObjectInfo);
|
|
|
|
error:
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
GetNextToken(
|
|
CLexer *pTokenizer,
|
|
POBJECTINFO pObjectInfo,
|
|
LPWSTR *ppszToken,
|
|
LPWSTR *ppszDisplayToken,
|
|
DWORD *pdwToken
|
|
)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
ADsAssert(ppszToken);
|
|
*ppszToken = NULL;
|
|
|
|
if (ppszDisplayToken) {
|
|
*ppszDisplayToken = NULL;
|
|
}
|
|
|
|
hr = pTokenizer->GetNextToken(
|
|
pObjectInfo->szStrBufPtr,
|
|
pObjectInfo->szDisplayStrBufPtr,
|
|
pdwToken
|
|
);
|
|
BAIL_ON_FAILURE(hr);
|
|
|
|
*ppszToken = pObjectInfo->szStrBufPtr;
|
|
|
|
if (ppszDisplayToken) {
|
|
*ppszDisplayToken = pObjectInfo->szDisplayStrBufPtr;
|
|
}
|
|
|
|
if(*pdwToken != TOKEN_END)
|
|
{
|
|
pObjectInfo->szStrBufPtr += wcslen(pObjectInfo->szStrBufPtr) + 1;
|
|
|
|
pObjectInfo->szDisplayStrBufPtr += wcslen(pObjectInfo->szDisplayStrBufPtr) + 1;
|
|
}
|
|
|
|
error:
|
|
|
|
RRETURN (hr);
|
|
|
|
|
|
}
|
|
|
|
|
|
HRESULT
|
|
GetNextToken(
|
|
CLexer *pTokenizer,
|
|
POBJECTINFO pObjectInfo,
|
|
LPWSTR *ppszToken,
|
|
DWORD *pdwToken
|
|
)
|
|
{
|
|
return (GetNextToken(
|
|
pTokenizer,
|
|
pObjectInfo,
|
|
ppszToken,
|
|
NULL,
|
|
pdwToken
|
|
));
|
|
|
|
}
|
|
//+---------------------------------------------------------------------------
|
|
// Function: ADsObject
|
|
//
|
|
// Synopsis: parses an ADs pathname passed to this provider. This function
|
|
// parses the following grammar rules
|
|
//
|
|
// <ADsObject> -> <ProviderName> <LDAPObject>
|
|
//
|
|
//
|
|
// 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)
|
|
//
|
|
// History: 11-3-95 krishnag Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
ADsObjectParse(CLexer * pTokenizer, POBJECTINFO pObjectInfo)
|
|
{
|
|
LPWSTR szToken = NULL;
|
|
DWORD dwToken;
|
|
HRESULT hr;
|
|
|
|
hr = ProviderName(pTokenizer, pObjectInfo);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szToken, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
switch ( dwToken ) {
|
|
case TOKEN_END:
|
|
RRETURN(S_OK);
|
|
|
|
default:
|
|
hr = pTokenizer->PushBackToken();
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
hr = LDAPObject(pTokenizer, pObjectInfo);
|
|
BAIL_IF_ERROR(hr);
|
|
break;
|
|
}
|
|
|
|
cleanup:
|
|
|
|
RRETURN(hr);
|
|
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Function: LDAPObject
|
|
//
|
|
// Synopsis: parses an ADs pathname passed to this provider. This function
|
|
// parses the following grammar rules
|
|
//
|
|
// <LDAPObject> -> "\\""identifier""\" <LDAPObject>
|
|
//
|
|
//
|
|
// 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)
|
|
//
|
|
// History: 11-3-95 krishnag Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT
|
|
LDAPObject(CLexer * pTokenizer, POBJECTINFO pObjectInfo)
|
|
{
|
|
LPWSTR szToken = NULL;
|
|
LPWSTR szDisplayToken;
|
|
DWORD dwToken, dwPort;
|
|
HRESULT hr;
|
|
WCHAR c = L'\0';
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szToken, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
if (dwToken != TOKEN_FSLASH) {
|
|
RRETURN(E_ADS_BAD_PATHNAME);
|
|
}
|
|
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szToken, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
if (dwToken != TOKEN_FSLASH) {
|
|
RRETURN(E_ADS_BAD_PATHNAME);
|
|
}
|
|
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szToken, &szDisplayToken, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
if (dwToken != TOKEN_IDENTIFIER) {
|
|
RRETURN(E_ADS_BAD_PATHNAME);
|
|
}
|
|
|
|
if (!_wcsicmp(szToken, L"schema")) {
|
|
|
|
hr = pTokenizer->PushBackToken(); // push back the identifier
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
pObjectInfo->dwServerPresent = FALSE;
|
|
|
|
hr = PathName(pTokenizer, pObjectInfo);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szToken, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
} else if (!_wcsicmp(szToken, L"rootdse")) {
|
|
|
|
hr = pTokenizer->PushBackToken(); // push back the identifier
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
pObjectInfo->dwServerPresent = FALSE;
|
|
|
|
hr = PathName(pTokenizer, pObjectInfo);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szToken, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
} else if (((c = (CHAR)pTokenizer->NextChar()) == TEXT('=')) || (c == TEXT(',')) || (c == TEXT(';')))
|
|
{
|
|
pTokenizer->PushbackChar(); // push back =
|
|
|
|
hr = pTokenizer->PushBackToken(); // push back the identifier
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
pObjectInfo->dwServerPresent = FALSE;
|
|
|
|
|
|
hr = PathName(pTokenizer, pObjectInfo);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szToken, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
}
|
|
else
|
|
{
|
|
pTokenizer->PushbackChar();
|
|
|
|
hr = AddTreeName(pObjectInfo, szToken, szDisplayToken);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
pObjectInfo->dwServerPresent = TRUE;
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szToken, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
//
|
|
// Check if we have an explicit port number
|
|
//
|
|
|
|
if ( dwToken == TOKEN_COLON) {
|
|
|
|
//
|
|
// Get the port number and set it in the ObjectInfo structure
|
|
//
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szToken, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
if (dwToken == TOKEN_END) {
|
|
RRETURN(E_ADS_BAD_PATHNAME);
|
|
}
|
|
|
|
dwPort = _wtoi(szToken);
|
|
if (dwPort == 0) {
|
|
RRETURN(E_ADS_BAD_PATHNAME);
|
|
}
|
|
|
|
AddPortNumber(pObjectInfo, dwPort);
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &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) {
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
if (dwToken == TOKEN_FSLASH) {
|
|
|
|
hr = PathName(pTokenizer, pObjectInfo);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szToken, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
} else if ( dwToken == TOKEN_COMMA || dwToken == TOKEN_SEMICOLON ) {
|
|
// do nothing here
|
|
} else {
|
|
RRETURN(E_ADS_BAD_PATHNAME);
|
|
}
|
|
}
|
|
|
|
switch (dwToken) {
|
|
case TOKEN_END:
|
|
RRETURN(S_OK);
|
|
|
|
default:
|
|
RRETURN(E_ADS_BAD_PATHNAME);
|
|
|
|
}
|
|
cleanup:
|
|
RRETURN(hr);
|
|
}
|
|
|
|
HRESULT
|
|
ProviderName(CLexer * pTokenizer, POBJECTINFO pObjectInfo)
|
|
{
|
|
LPWSTR szToken = NULL;
|
|
DWORD dwToken;
|
|
HRESULT hr;
|
|
DWORD dwPort;
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szToken, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
if (dwToken == TOKEN_ATSIGN) {
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szToken, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
if (dwToken != TOKEN_IDENTIFIER) {
|
|
RRETURN(E_ADS_BAD_PATHNAME);
|
|
}
|
|
|
|
hr = AddProviderName(pObjectInfo, szToken);
|
|
hr = AddNamespaceName(pObjectInfo, szToken);
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &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 = AddNamespaceName(pObjectInfo, szToken);
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szToken, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
|
|
if (dwToken != TOKEN_COLON) {
|
|
RRETURN(E_ADS_BAD_PATHNAME);
|
|
}
|
|
|
|
}else {
|
|
RRETURN(E_ADS_BAD_PATHNAME);
|
|
}
|
|
|
|
//
|
|
// Add the default port number depending on the namespace.
|
|
// If an explicit port number is specified, that will override
|
|
//
|
|
|
|
if ( _wcsicmp( pObjectInfo->NamespaceName, szGCNamespaceName) == 0 ) {
|
|
dwPort = (DWORD) USE_DEFAULT_GC_PORT;
|
|
}
|
|
else {
|
|
dwPort = (DWORD) USE_DEFAULT_LDAP_PORT;
|
|
}
|
|
|
|
AddPortNumber(pObjectInfo, dwPort);
|
|
|
|
//
|
|
// You can now disable the processing for "@" and "!" treat them
|
|
// as ordinary characters.
|
|
//
|
|
|
|
pTokenizer->SetAtDisabler(TRUE);
|
|
|
|
|
|
RRETURN(S_OK);
|
|
|
|
cleanup:
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
|
|
// PathName -> Component \\ PathName
|
|
// PathName -> Component
|
|
HRESULT
|
|
DsPathName(CLexer * pTokenizer, POBJECTINFO pObjectInfo)
|
|
{
|
|
LPWSTR szToken = NULL;
|
|
DWORD dwToken;
|
|
HRESULT hr;
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szToken, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
if (dwToken != TOKEN_FSLASH) {
|
|
RRETURN(E_ADS_BAD_PATHNAME);
|
|
}
|
|
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szToken, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
if (dwToken != TOKEN_FSLASH) {
|
|
RRETURN(E_ADS_BAD_PATHNAME);
|
|
}
|
|
|
|
hr = PathName(pTokenizer, pObjectInfo);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
RRETURN(S_OK);
|
|
|
|
cleanup:
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Function:
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 11-3-95 krishnag Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
PathName(CLexer * pTokenizer, POBJECTINFO pObjectInfo)
|
|
{
|
|
HRESULT hr;
|
|
LPWSTR szToken = NULL;
|
|
DWORD dwToken;
|
|
|
|
hr = Component(pTokenizer, pObjectInfo);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szToken, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
if (!pObjectInfo->dwPathType) {
|
|
|
|
if (dwToken == TOKEN_FSLASH) {
|
|
|
|
pObjectInfo->dwPathType = PATHTYPE_WINDOWS;
|
|
RRETURN (PathName(pTokenizer, pObjectInfo));
|
|
}else if (dwToken == TOKEN_COMMA || dwToken == TOKEN_SEMICOLON){
|
|
|
|
pObjectInfo->dwPathType = PATHTYPE_X500;
|
|
RRETURN (PathName(pTokenizer, pObjectInfo));
|
|
}else{
|
|
hr = pTokenizer->PushBackToken();
|
|
RRETURN (S_OK);
|
|
}
|
|
}else if (pObjectInfo->dwPathType == PATHTYPE_WINDOWS){
|
|
|
|
if (dwToken == TOKEN_FSLASH) {
|
|
RRETURN (PathName(pTokenizer, pObjectInfo));
|
|
}else{
|
|
hr = pTokenizer->PushBackToken();
|
|
RRETURN (S_OK);
|
|
}
|
|
}else if (pObjectInfo->dwPathType == PATHTYPE_X500){
|
|
|
|
if (dwToken == TOKEN_COMMA || dwToken == TOKEN_SEMICOLON) {
|
|
RRETURN (PathName(pTokenizer, pObjectInfo));
|
|
}else{
|
|
hr = pTokenizer->PushBackToken();
|
|
RRETURN (S_OK);
|
|
}
|
|
}else {
|
|
|
|
//
|
|
// We should never hit this point
|
|
//
|
|
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
cleanup:
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Function:
|
|
//
|
|
// Synopsis: Component -> <identifier>
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 11-3-95 krishnag Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
Component(CLexer * pTokenizer, POBJECTINFO pObjectInfo)
|
|
{
|
|
LPWSTR szValue = NULL;
|
|
LPWSTR szDisplayValue = NULL;
|
|
LPWSTR szEqual = NULL;
|
|
LPWSTR szComponent = NULL;
|
|
LPWSTR szDisplayComponent = NULL;
|
|
DWORD dwToken;
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szComponent, &szDisplayComponent, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
if (dwToken != TOKEN_IDENTIFIER) {
|
|
BAIL_IF_ERROR( hr = E_ADS_BAD_PATHNAME);
|
|
}
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szEqual, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
if (dwToken == TOKEN_EQUAL) {
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szValue, &szDisplayValue, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
if (dwToken != TOKEN_IDENTIFIER) {
|
|
BAIL_IF_ERROR(hr = E_ADS_BAD_PATHNAME);
|
|
}
|
|
|
|
hr = AddComponent(pObjectInfo, szComponent, szValue, szDisplayComponent, szDisplayValue);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
}else {
|
|
|
|
hr = AddComponent(pObjectInfo, szComponent, NULL, szDisplayComponent, NULL);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
hr = pTokenizer->PushBackToken();
|
|
BAIL_IF_ERROR(hr);
|
|
}
|
|
|
|
cleanup:
|
|
|
|
RRETURN(hr);
|
|
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// 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)
|
|
{
|
|
LPWSTR szToken = NULL;
|
|
DWORD dwToken;
|
|
HRESULT hr;
|
|
|
|
hr = GetNextToken(pTokenizer, pObjectInfo, &szToken, &dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
|
|
if (dwToken == TOKEN_IDENTIFIER ) {
|
|
if (pTokenizer->IsKeyword(szToken, &dwToken)) {
|
|
hr = SetType(pObjectInfo, dwToken);
|
|
BAIL_IF_ERROR(hr);
|
|
}
|
|
pObjectInfo->ObjectClass = szToken;
|
|
}
|
|
|
|
cleanup:
|
|
|
|
RRETURN(hr);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Function:
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 11-3-95 krishnag Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
__declspec(dllexport)
|
|
CLexer::CLexer():
|
|
_ptr(NULL),
|
|
_Buffer(NULL),
|
|
_dwLastTokenLength(0),
|
|
_dwLastToken(0),
|
|
_dwEndofString(0),
|
|
_bAtDisabled(FALSE),
|
|
_bFSlashDisabled(FALSE),
|
|
_bExclaimDisabled(FALSE)
|
|
{}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Function:
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 08-12-96 t-danal Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
__declspec(dllexport)
|
|
CLexer::~CLexer()
|
|
{
|
|
FreeADsStr(_Buffer);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Function:
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 11-3-95 krishnag Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CLexer::GetNextToken(LPTSTR szToken, LPTSTR szDisplayToken, LPDWORD pdwToken)
|
|
{
|
|
TCHAR c, cnext;
|
|
DWORD state = 0;
|
|
LPTSTR pch = szToken;
|
|
LPTSTR pDisplayCh = szDisplayToken;
|
|
BOOL fEscapeOn = FALSE, fQuotingOn = FALSE;
|
|
|
|
if (!szToken) {
|
|
RRETURN(E_ADS_BAD_PATHNAME);
|
|
}
|
|
|
|
_dwLastTokenLength = 0;
|
|
while (1) {
|
|
c = NextChar();
|
|
|
|
switch (state) {
|
|
case 0:
|
|
*pch++ = c;
|
|
_dwLastTokenLength++;
|
|
|
|
switch (c) {
|
|
|
|
case TEXT('"') :
|
|
//
|
|
// Quoting;
|
|
//
|
|
|
|
fQuotingOn = TRUE;
|
|
|
|
state = 1;
|
|
break;
|
|
|
|
case TEXT('\\') :
|
|
//
|
|
// Escaping; Ignore the '\' in the token and check to make
|
|
// sure that the next character exists
|
|
//
|
|
cnext = NextChar();
|
|
if (cnext == TEXT('/')) {
|
|
pch--;
|
|
}
|
|
PushbackChar();
|
|
|
|
fEscapeOn = TRUE;
|
|
|
|
state = 1;
|
|
break;
|
|
|
|
case TEXT('/') :
|
|
if (!_bFSlashDisabled) {
|
|
*pdwToken = TOKEN_FSLASH;
|
|
_dwLastToken = *pdwToken;
|
|
RRETURN(S_OK);
|
|
}
|
|
else {
|
|
state = 1;
|
|
}
|
|
break;
|
|
case TEXT(',') :
|
|
*pdwToken = TOKEN_COMMA;
|
|
_dwLastToken = *pdwToken;
|
|
RRETURN(S_OK);
|
|
break;
|
|
|
|
case TEXT(';') :
|
|
*pdwToken = TOKEN_SEMICOLON;
|
|
_dwLastToken = *pdwToken;
|
|
RRETURN(S_OK);
|
|
break;
|
|
|
|
case TEXT('=') :
|
|
*pdwToken = TOKEN_EQUAL;
|
|
_dwLastToken = *pdwToken;
|
|
RRETURN(S_OK);
|
|
break;
|
|
|
|
case TEXT(':') :
|
|
if (!_bAtDisabled && !_bExclaimDisabled) {
|
|
*pdwToken = TOKEN_COLON;
|
|
_dwLastToken = *pdwToken;
|
|
RRETURN(S_OK);
|
|
}else {
|
|
state = 1;
|
|
}
|
|
break;
|
|
|
|
case TEXT('\0') :
|
|
*pdwToken = TOKEN_END;
|
|
_dwLastToken = *pdwToken;
|
|
RRETURN(S_OK);
|
|
break;
|
|
|
|
case TEXT('@') :
|
|
|
|
if (!_bAtDisabled) {
|
|
*pdwToken = TOKEN_ATSIGN;
|
|
_dwLastToken = *pdwToken;
|
|
RRETURN(S_OK);
|
|
}else {
|
|
state = 1;
|
|
}
|
|
break;
|
|
|
|
case TEXT('!') :
|
|
|
|
if (!_bAtDisabled && !_bExclaimDisabled) {
|
|
*pdwToken = TOKEN_EXCLAMATION;
|
|
_dwLastToken = *pdwToken;
|
|
RRETURN(S_OK);
|
|
}else {
|
|
state = 1;
|
|
}
|
|
break;
|
|
|
|
case TEXT(' ') :
|
|
pch--;
|
|
_dwLastTokenLength--;
|
|
break;
|
|
|
|
default:
|
|
state = 1;
|
|
break;
|
|
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if ((fEscapeOn || fQuotingOn) && c == TEXT('\0') ) {
|
|
RRETURN(E_ADS_BAD_PATHNAME);
|
|
}
|
|
else if (fEscapeOn) {
|
|
fEscapeOn = FALSE;
|
|
*pch++ = c;
|
|
_dwLastTokenLength++;
|
|
state = 1;
|
|
break;
|
|
}
|
|
else if (fQuotingOn) {
|
|
if (c == TEXT('"')) {
|
|
fQuotingOn = FALSE;
|
|
}
|
|
else if (c == TEXT('\\')) {
|
|
//
|
|
// This is a special case, where a \ is
|
|
// being passed in to escape something inside
|
|
// quotes.
|
|
//
|
|
fEscapeOn = TRUE;
|
|
_dwLastTokenLength++;
|
|
|
|
*pch++ = c;
|
|
|
|
cnext = NextChar();
|
|
if (cnext == '/') {
|
|
pch--;
|
|
}
|
|
PushbackChar();
|
|
state = 1;
|
|
break;
|
|
}
|
|
*pch++ = c;
|
|
_dwLastTokenLength++;
|
|
break;
|
|
}
|
|
//
|
|
// Ok to put a switch here as all have breaks above.
|
|
//
|
|
switch (c) {
|
|
case TEXT('\\') :
|
|
|
|
fEscapeOn = TRUE;
|
|
_dwLastTokenLength++;
|
|
|
|
*pch++ = c;
|
|
|
|
cnext = NextChar();
|
|
if (cnext == '/') {
|
|
pch--;
|
|
}
|
|
PushbackChar();
|
|
|
|
break;
|
|
|
|
case TEXT('"') :
|
|
fQuotingOn = TRUE;
|
|
*pch++ = c;
|
|
_dwLastTokenLength++;
|
|
break;
|
|
|
|
case TEXT('\0'):
|
|
case TEXT(',') :
|
|
case TEXT('=') :
|
|
case TEXT(';') :
|
|
PushbackChar();
|
|
|
|
*pdwToken = TOKEN_IDENTIFIER;
|
|
_dwLastToken = *pdwToken;
|
|
RRETURN (S_OK);
|
|
break;
|
|
|
|
case TEXT('/') :
|
|
if (!_bFSlashDisabled) {
|
|
PushbackChar();
|
|
|
|
*pdwToken = TOKEN_IDENTIFIER;
|
|
_dwLastToken = *pdwToken;
|
|
RRETURN(S_OK);
|
|
}
|
|
else {
|
|
*pch++ = c;
|
|
_dwLastTokenLength++;
|
|
state = 1;
|
|
}
|
|
break;
|
|
case TEXT('!') :
|
|
case TEXT(':') :
|
|
if (!_bAtDisabled && !_bExclaimDisabled) {
|
|
|
|
PushbackChar();
|
|
*pdwToken = TOKEN_IDENTIFIER;
|
|
_dwLastToken = *pdwToken;
|
|
RRETURN(S_OK);
|
|
|
|
}else {
|
|
|
|
*pch++ = c;
|
|
_dwLastTokenLength++;
|
|
state = 1;
|
|
break;
|
|
|
|
}
|
|
case TEXT('@') :
|
|
if (!_bAtDisabled) {
|
|
|
|
PushbackChar();
|
|
*pdwToken = TOKEN_IDENTIFIER;
|
|
_dwLastToken = *pdwToken;
|
|
RRETURN(S_OK);
|
|
|
|
}else {
|
|
|
|
*pch++ = c;
|
|
_dwLastTokenLength++;
|
|
state = 1;
|
|
break;
|
|
|
|
}
|
|
|
|
default :
|
|
*pch++ = c;
|
|
_dwLastTokenLength++;
|
|
state = 1;
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
RRETURN(E_ADS_BAD_PATHNAME);
|
|
}
|
|
|
|
if (pDisplayCh) {
|
|
*pDisplayCh++ = c;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
__declspec(dllexport)
|
|
HRESULT
|
|
CLexer::GetNextToken(LPTSTR szToken, LPDWORD pdwToken)
|
|
{
|
|
RRETURN (GetNextToken(szToken, NULL, pdwToken));
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Function:
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 11-3-95 krishnag Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
TCHAR
|
|
CLexer::NextChar()
|
|
{
|
|
if (_ptr == NULL || *_ptr == TEXT('\0')) {
|
|
_dwEndofString = TRUE;
|
|
return(TEXT('\0'));
|
|
}
|
|
return(*_ptr++);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Function:
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 11-3-95 krishnag Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
CLexer::PushBackToken()
|
|
{
|
|
if (_dwLastToken == TOKEN_END) {
|
|
RRETURN(S_OK);
|
|
}
|
|
_ptr -= _dwLastTokenLength;
|
|
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Function:
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 11-3-95 krishnag Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
CLexer::PushbackChar()
|
|
{
|
|
if (_dwEndofString) {
|
|
return;
|
|
}
|
|
_ptr--;
|
|
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
// Function:
|
|
//
|
|
// Synopsis:
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 11-3-95 krishnag Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
BOOL
|
|
CLexer::IsKeyword(LPTSTR szToken, LPDWORD pdwToken)
|
|
{
|
|
DWORD i = 0;
|
|
|
|
for (i = 0; i < gdwKeywordListSize; i++) {
|
|
if (!_tcsicmp(szToken, KeywordList[i].Keyword)) {
|
|
*pdwToken = KeywordList[i].dwTokenId;
|
|
return(TRUE);
|
|
}
|
|
}
|
|
*pdwToken = 0;
|
|
return(FALSE);
|
|
}
|
|
|
|
__declspec(dllexport)
|
|
HRESULT
|
|
CLexer::InitializePath(LPTSTR szBuffer)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
_Buffer = AllocADsStr(szBuffer);
|
|
if(!_Buffer && szBuffer)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
_ptr = _Buffer;
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//Function:
|
|
//
|
|
//Synopsis:
|
|
//
|
|
//Arguments:
|
|
//
|
|
//Returns:
|
|
//
|
|
//Modifies:
|
|
//
|
|
//History: 11-3-95 krishnag Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT
|
|
AddComponent(POBJECTINFO pObjectInfo,
|
|
LPTSTR szComponent,
|
|
LPTSTR szValue,
|
|
LPTSTR szDisplayComponent,
|
|
LPTSTR szDisplayValue
|
|
)
|
|
{
|
|
if (!szComponent || !*szComponent || !szDisplayComponent || !*szDisplayComponent) {
|
|
RRETURN(E_FAIL);
|
|
}
|
|
|
|
if ( pObjectInfo->NumComponents < MAXCOMPONENTS ) {
|
|
|
|
pObjectInfo->ComponentArray[pObjectInfo->NumComponents].szComponent =
|
|
szComponent;
|
|
|
|
pObjectInfo->ComponentArray[pObjectInfo->NumComponents].szValue =
|
|
szValue;
|
|
|
|
pObjectInfo->DisplayComponentArray[pObjectInfo->NumComponents].szComponent =
|
|
szDisplayComponent;
|
|
|
|
pObjectInfo->DisplayComponentArray[pObjectInfo->NumComponents].szValue =
|
|
szDisplayValue;
|
|
|
|
pObjectInfo->NumComponents++;
|
|
|
|
RRETURN(S_OK);
|
|
|
|
} else {
|
|
|
|
RRETURN(E_ADS_BAD_PATHNAME);
|
|
}
|
|
|
|
}
|
|
|
|
HRESULT
|
|
AddProviderName(POBJECTINFO pObjectInfo, LPTSTR szToken)
|
|
{
|
|
if (!szToken || !*szToken) {
|
|
RRETURN(E_FAIL);
|
|
}
|
|
|
|
|
|
if (_tcscmp(szToken, szLDAPNamespaceName) == 0 ||
|
|
_tcscmp(szToken, szGCNamespaceName) == 0) {
|
|
|
|
//
|
|
// szProviderName is the provider name for both LDAP and GC namespaces
|
|
//
|
|
|
|
pObjectInfo->ProviderName = szProviderName;
|
|
}
|
|
else {
|
|
|
|
//
|
|
// Not one of the namespaces we handle, just copy
|
|
//
|
|
|
|
pObjectInfo->ProviderName = szToken;
|
|
}
|
|
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
HRESULT
|
|
AddNamespaceName(POBJECTINFO pObjectInfo, LPTSTR szToken)
|
|
{
|
|
if (!szToken || !*szToken) {
|
|
RRETURN(E_FAIL);
|
|
}
|
|
|
|
pObjectInfo->NamespaceName = szToken;
|
|
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
AddTreeName(POBJECTINFO pObjectInfo, LPTSTR szToken, LPWSTR szDisplayToken)
|
|
{
|
|
if (!szToken || !*szToken || !szDisplayToken || !*szDisplayToken) {
|
|
RRETURN(E_FAIL);
|
|
}
|
|
|
|
pObjectInfo->TreeName = szToken;
|
|
pObjectInfo->DisplayTreeName = szDisplayToken;
|
|
|
|
RRETURN(S_OK);
|
|
}
|
|
|
|
|
|
HRESULT
|
|
AddPortNumber(POBJECTINFO pObjectInfo, DWORD dwPort)
|
|
{
|
|
pObjectInfo->PortNumber = dwPort;
|
|
|
|
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);
|
|
}
|
|
|
|
void
|
|
CLexer::SetAtDisabler(
|
|
BOOL bFlag
|
|
)
|
|
{
|
|
_bAtDisabled = bFlag;
|
|
}
|
|
|
|
BOOL
|
|
CLexer::GetAtDisabler()
|
|
{
|
|
return(_bAtDisabled);
|
|
}
|
|
|
|
void
|
|
CLexer::SetFSlashDisabler(
|
|
BOOL bFlag
|
|
)
|
|
{
|
|
_bFSlashDisabled = bFlag;
|
|
}
|
|
|
|
BOOL
|
|
CLexer::GetFSlashDisabler()
|
|
{
|
|
return(_bFSlashDisabled);
|
|
}
|
|
|
|
void
|
|
CLexer::SetExclaimnationDisabler(
|
|
BOOL bFlag
|
|
)
|
|
{
|
|
_bExclaimDisabled = bFlag;
|
|
}
|
|
|
|
BOOL
|
|
CLexer::GetExclaimnationDisabler()
|
|
{
|
|
return(_bExclaimDisabled);
|
|
}
|
|
|
|
HRESULT
|
|
GetDisplayName(
|
|
LPWSTR szName,
|
|
LPWSTR *ppszDisplayName
|
|
)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
DWORD len = 0;
|
|
LPWSTR pch = szName;
|
|
LPWSTR pszDisplayCh = NULL, pszDisplay = NULL;
|
|
|
|
BOOL fQuoteMode = FALSE; // TRUE means we're processing between
|
|
// quotation marks
|
|
BOOL fEscaped = FALSE; // TRUE means next one char to be
|
|
// processed should be treated as literal
|
|
|
|
if (!ppszDisplayName ) {
|
|
RRETURN (E_INVALIDARG);
|
|
}
|
|
|
|
*ppszDisplayName = NULL;
|
|
|
|
if (!szName) {
|
|
RRETURN (S_OK);
|
|
}
|
|
|
|
pch = szName;
|
|
|
|
//
|
|
// Parsing Algorithm:
|
|
//
|
|
// If this char follows an unescaped backslash:
|
|
// Treat as literal, treat next char regularly (set fEscaped = FALSE)
|
|
// Else, if we're between quotation marks:
|
|
// If we see a quotation mark, leave quote mode
|
|
// Else, treat as literal
|
|
// Else, if we're not between quote marks, and we see a quote mark:
|
|
// Enter quote mode
|
|
// Else, if we see a backslash (and we're not already in escape or quote
|
|
// mode):
|
|
// Treat next char as literal (set fEscaped = TRUE)
|
|
// Else, if we see a forward-slash (and we're not in escape or quote mode):
|
|
// We need to escape it by prefixing with a backslash
|
|
// Else:
|
|
// Do nothing, just a plain old character
|
|
// Go on to next character, and repeat
|
|
//
|
|
// Backslashes inside quotation marks are always treated as literals,
|
|
// since that is the definition of being inside quotation marks
|
|
//
|
|
while (*pch) {
|
|
if (fEscaped) {
|
|
fEscaped = FALSE;
|
|
}
|
|
else if (fQuoteMode) {
|
|
if (*pch == L'"') {
|
|
fQuoteMode = FALSE;
|
|
}
|
|
}
|
|
else if (*pch == L'"') {
|
|
fQuoteMode = TRUE;
|
|
}
|
|
else if (*pch == L'\\') {
|
|
fEscaped = TRUE;
|
|
}
|
|
else if (*pch == L'/') {
|
|
//
|
|
// include space for the escape char
|
|
// we'll need to add
|
|
//
|
|
len++;
|
|
}
|
|
|
|
len++;
|
|
|
|
pch++;
|
|
}
|
|
|
|
pszDisplay = (LPWSTR) AllocADsMem((len+1) * sizeof(WCHAR));
|
|
|
|
if (!pszDisplay) {
|
|
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
|
|
}
|
|
|
|
pch = szName;
|
|
pszDisplayCh = pszDisplay;
|
|
|
|
fEscaped = FALSE;
|
|
fQuoteMode = FALSE;
|
|
|
|
while (*pch) {
|
|
if (fEscaped) {
|
|
fEscaped = FALSE;
|
|
}
|
|
else if (fQuoteMode) {
|
|
if (*pch == L'"') {
|
|
fQuoteMode = FALSE;
|
|
}
|
|
}
|
|
else if (*pch == L'"') {
|
|
fQuoteMode = TRUE;
|
|
}
|
|
else if (*pch == L'\\') {
|
|
fEscaped = TRUE;
|
|
}
|
|
else if (*pch == L'/') {
|
|
//
|
|
// unescaped forward slash needs to get escaped
|
|
//
|
|
*pszDisplayCh++ = L'\\';
|
|
}
|
|
|
|
*pszDisplayCh++ = *pch;
|
|
|
|
pch++;
|
|
}
|
|
|
|
*pszDisplayCh = L'\0';
|
|
|
|
*ppszDisplayName = pszDisplay;
|
|
|
|
error:
|
|
|
|
RRETURN(hr);
|
|
|
|
|
|
}
|
|
|
|
//
|
|
// Convert an ADs path to LDAP path
|
|
//
|
|
|
|
HRESULT
|
|
GetLDAPTypeName(
|
|
LPWSTR szName,
|
|
LPWSTR *ppszDisplayName
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD len = 0;
|
|
LPWSTR pch = NULL;
|
|
LPWSTR pszDisplayCh = NULL;
|
|
LPWSTR pszDisplay = NULL;
|
|
|
|
|
|
if (!ppszDisplayName ) {
|
|
RRETURN(E_ADS_BAD_PATHNAME);
|
|
}
|
|
|
|
*ppszDisplayName = NULL;
|
|
|
|
if (!szName) {
|
|
RRETURN (E_ADS_BAD_PATHNAME);
|
|
}
|
|
|
|
pch = szName;
|
|
|
|
//
|
|
// Parsing algorithm
|
|
// if this character is an escaped back slash
|
|
// if next character is a forward slash (we know this is a kind of ADsPath)
|
|
// we will remove the back slash
|
|
// accepts the current character
|
|
// goes on to process the next character
|
|
//
|
|
|
|
while (*pch) {
|
|
if(*pch == L'\\') {
|
|
|
|
pch++;
|
|
//
|
|
// If next character is /, we need to remove the escape character
|
|
//
|
|
if(*pch != L'/') {
|
|
len++;
|
|
}
|
|
|
|
}
|
|
|
|
if(*pch) {
|
|
len++;
|
|
pch++;
|
|
}
|
|
|
|
}
|
|
|
|
pszDisplay = (LPWSTR) AllocADsMem((len+1) * sizeof(WCHAR));
|
|
|
|
if (!pszDisplay) {
|
|
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
|
|
}
|
|
|
|
pch = szName;
|
|
pszDisplayCh = pszDisplay;
|
|
|
|
|
|
|
|
while (*pch) {
|
|
if(*pch == L'\\') {
|
|
//
|
|
// If next character is /, we need to remove the escape character
|
|
//
|
|
pch++;
|
|
|
|
if(*pch != L'/') {
|
|
*pszDisplayCh++ = L'\\';
|
|
}
|
|
|
|
}
|
|
|
|
if(*pch) {
|
|
*pszDisplayCh++ = *pch;
|
|
pch++;
|
|
}
|
|
|
|
}
|
|
|
|
*pszDisplayCh = L'\0';
|
|
|
|
*ppszDisplayName = pszDisplay;
|
|
|
|
error:
|
|
|
|
RRETURN(hr);
|
|
|
|
}
|