windows-nt/Source/XPSP1/NT/ds/adsi/nwnds/getobj.cxx
2020-09-26 16:20:57 +08:00

1093 lines
23 KiB
C++

//---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995
//
// File: getobj.cxx
//
// Contents: Windows NT 3.5 GetObject functionality
//
// History:
//----------------------------------------------------------------------------
#include "nds.hxx"
#pragma hdrstop
extern LPWSTR szProviderName;
//+---------------------------------------------------------------------------
// Function: RelativeGetObject
//
// Synopsis: Gets object relative to given Active Directory path.
//
// Arguments: [BSTR ADsPath]
// [BSTR ClassName]
// [BSTR RelativeName]
// [IUnknown** ppObject]
// [BOOT bNamespaceRelative]
//
// Returns: HRESULT
//
// Modifies: *ppObject
//
// History: 08-02-96 t-danal Created as such.
//
//----------------------------------------------------------------------------
HRESULT
RelativeGetObject(
BSTR ADsPath,
BSTR ClassName,
BSTR RelativeName,
CCredentials& Credentials,
IDispatch * FAR* ppObject,
BOOL bNamespaceRelative
)
{
WCHAR szBuffer[MAX_PATH];
HRESULT hr = S_OK;
*ppObject = NULL;
if (!RelativeName || !*RelativeName) {
RRETURN(E_ADS_UNKNOWN_OBJECT);
}
wcscpy(szBuffer, ADsPath);
if (bNamespaceRelative)
wcscat(szBuffer, L"//");
else
wcscat(szBuffer, L"/");
wcscat(szBuffer, RelativeName);
if (ClassName && *ClassName) {
wcscat(szBuffer,L",");
wcscat(szBuffer, ClassName);
}
hr = ::GetObject(
szBuffer,
Credentials,
(LPVOID *)ppObject
);
BAIL_ON_FAILURE(hr);
error:
RRETURN(hr);
}
//+---------------------------------------------------------------------------
// Function: GetObject
//
// Synopsis: Called by ResolvePathName to return an object
//
// Arguments: [LPWSTR szBuffer]
// [LPVOID *ppObject]
//
// Returns: HRESULT
//
// Modifies: -
//
// History: 11-3-95 krishnag Created.
//
//----------------------------------------------------------------------------
HRESULT
GetObject(
LPWSTR szBuffer,
CCredentials& Credentials,
LPVOID * ppObject
)
{
HRESULT hr;
DWORD dwStatus = NO_ERROR;
LPWSTR pszNDSTreeName = NULL;
LPWSTR pszNDSDn = NULL;
WCHAR szParent[MAX_PATH];
WCHAR szCommonName[MAX_PATH];
LPWSTR pszObjectClassName = NULL;
OBJECTINFO ObjectInfo;
POBJECTINFO pObjectInfo = &ObjectInfo;
CLexer Lexer(szBuffer);
NDS_CONTEXT_HANDLE hADsContext = NULL;
IADs * pADs = NULL;
NWDSCCODE ccode;
PNDS_CONTEXT pADsContext;
NWDSContextHandle context;
Object_Info_T ObjInfo;
WCHAR ObjectDN[MAX_DN_CHARS+1];
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
hr = ADsObject(&Lexer, pObjectInfo);
BAIL_ON_FAILURE(hr);
//
// Validate that this ADs pathname is to be processed by
// us - as in the provider name is @NDS!
//
hr = ValidateProvider(pObjectInfo);
BAIL_ON_FAILURE(hr);
hr = ValidateObjectType(pObjectInfo);
switch (pObjectInfo->ObjectType) {
case TOKEN_NAMESPACE:
//
// This means that this is a namespace object;
// instantiate the namespace object
//
hr = GetNamespaceObject(
pObjectInfo,
Credentials,
ppObject
);
BAIL_ON_FAILURE(hr);
break;
case TOKEN_SCHEMA:
hr = GetSchemaObject(
pObjectInfo,
Credentials,
ppObject
);
BAIL_ON_FAILURE(hr);
break;
default:
hr = BuildNDSPathFromADsPath2(
szBuffer,
&pszNDSTreeName,
&pszNDSDn
);
BAIL_ON_FAILURE(hr);
hr = ADsNdsOpenContext(
pszNDSTreeName,
Credentials,
&hADsContext
);
BAIL_ON_FAILURE(hr);
pADsContext = (PNDS_CONTEXT) hADsContext;
context = pADsContext->hContext;
ccode = NWDSReadObjectInfo(
context,
(pnstr8) (!pszNDSDn || (*pszNDSDn == L'\0') ? L"[Root]" : pszNDSDn),
(pnstr8) ObjectDN,
&ObjInfo);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
pszObjectClassName = (LPWSTR) ObjInfo.baseClass;
if (!pszObjectClassName) {
BAIL_ON_FAILURE(E_FAIL);
}
hr = BuildADsParentPath(
szBuffer,
szParent,
szCommonName
);
BAIL_ON_FAILURE(hr);
hr = CNDSGenObject::CreateGenericObject(
szParent,
szCommonName,
pszObjectClassName,
Credentials,
ADS_OBJECT_BOUND,
IID_IADs,
(void **)&pADs
);
BAIL_ON_FAILURE(hr);
// InstantiateDerivedObject should add-ref this pointer for us.
//
hr = InstantiateDerivedObject(
pADs,
Credentials,
IID_IUnknown,
(void **)ppObject
);
if (FAILED(hr)) {
hr = pADs->QueryInterface(
IID_IUnknown,
ppObject
);
BAIL_ON_FAILURE(hr);
}
break;
}
error:
if (pszNDSTreeName) {
FreeADsStr(pszNDSTreeName);
}
if (pszNDSDn) {
FreeADsStr(pszNDSDn);
}
if (pADs) {
pADs->Release();
}
if (hADsContext) {
ADsNdsCloseContext( hADsContext );
}
FreeObjectInfo( &ObjectInfo );
RRETURN(hr);
}
HRESULT
BuildADsPathFromNDSPath(
LPWSTR szNDSTreeName,
LPWSTR szNDSDNName,
LPWSTR *ppszADsPath
)
{
PKEYDATA pKeyData = NULL;
DWORD dwCount = 0;
DWORD i = 0;
LPWSTR pszDisplayTreeName = NULL;
LPWSTR pszDisplayDNName = NULL;
LPWSTR pszTemp = NULL;
HRESULT hr = S_OK;
if (!szNDSTreeName || !szNDSDNName || !ppszADsPath) {
RRETURN(E_FAIL);
}
*ppszADsPath = NULL;
hr = GetDisplayName(
szNDSTreeName,
&pszDisplayTreeName
);
BAIL_ON_FAILURE(hr);
pszTemp = (LPWSTR) AllocADsMem(
(wcslen(szProviderName) +
wcslen(L"://") +
wcslen(szNDSTreeName) +
wcslen(L"/") +
wcslen(szNDSDNName) +
1) * sizeof(WCHAR)
);
if (!pszTemp) {
BAIL_ON_FAILURE(hr);
}
wsprintf(pszTemp,L"%s://%s", szProviderName, szNDSTreeName);
hr = GetDisplayName(
szNDSDNName,
&pszDisplayDNName
);
BAIL_ON_FAILURE(hr);
pKeyData = CreateTokenList(
pszDisplayDNName,
L'.'
);
if (pKeyData) {
dwCount = pKeyData->cTokens;
for (i = 0; i < dwCount; i++) {
wcscat(pszTemp, L"/");
wcscat(pszTemp, pKeyData->pTokens[dwCount - 1 - i]);
}
}
if (pKeyData) {
FreeADsMem(pKeyData);
}
*ppszADsPath = pszTemp;
error:
if (pszDisplayTreeName) {
FreeADsMem(pszDisplayTreeName);
}
if (pszDisplayDNName) {
FreeADsMem(pszDisplayDNName);
}
RRETURN(hr);
}
HRESULT
BuildNDSPathFromADsPath(
LPWSTR szADsPathName,
LPWSTR * pszNDSPathName
)
{
OBJECTINFO ObjectInfo;
POBJECTINFO pObjectInfo = &ObjectInfo;
CLexer Lexer(szADsPathName);
DWORD i = 0;
DWORD dwNumComponents = 0;
HRESULT hr;
LPWSTR szNDSPathName = NULL;
*pszNDSPathName = NULL;
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
hr = ADsObject(&Lexer, pObjectInfo);
BAIL_ON_FAILURE(hr);
dwNumComponents = pObjectInfo->NumComponents;
szNDSPathName = AllocADsStr(szADsPathName);
if (!szNDSPathName) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
wcscpy(szNDSPathName, L"\\\\");
wcscat(szNDSPathName, pObjectInfo->TreeName);
if (dwNumComponents) {
wcscat(szNDSPathName, L"\\");
for (i = dwNumComponents; i > 0; i--) {
AppendComponent(
szNDSPathName,
&(pObjectInfo->ComponentArray[i-1])
);
if ((i - 1) > 0){
wcscat(szNDSPathName, L".");
}
}
}
*pszNDSPathName = szNDSPathName;
error:
FreeObjectInfo( &ObjectInfo );
RRETURN(hr);
}
HRESULT
AppendComponent(
LPWSTR szNDSPathName,
PCOMPONENT pComponent
)
{
if (pComponent->szComponent && pComponent->szValue) {
wcscat(szNDSPathName, pComponent->szComponent);
wcscat(szNDSPathName,L"=");
wcscat(szNDSPathName, pComponent->szValue);
}else if (pComponent->szComponent && !pComponent->szValue) {
wcscat(szNDSPathName, pComponent->szComponent);
}else {
//
// we should never hit this case
//
}
RRETURN(S_OK);
}
HRESULT
BuildADsParentPath(
LPWSTR szBuffer,
LPWSTR szParent,
LPWSTR szCommonName
)
{
OBJECTINFO ObjectInfo;
POBJECTINFO pObjectInfo = &ObjectInfo;
CLexer Lexer(szBuffer);
HRESULT hr = S_OK;
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
hr = ADsObject(&Lexer, pObjectInfo);
BAIL_ON_FAILURE(hr);
hr = BuildADsParentPath(
pObjectInfo,
szParent,
szCommonName
);
error:
FreeObjectInfo( &ObjectInfo );
RRETURN(hr);
}
//+---------------------------------------------------------------------------
// Function: GetNamespaceObject
//
// Synopsis: called by GetObject
//
// Arguments: [POBJECTINFO pObjectInfo]
// [LPVOID * ppObject]
//
// Returns: HRESULT
//
// Modifies: -
//
// History: 11-3-95 krishnag Created.
//
//----------------------------------------------------------------------------
HRESULT
GetNamespaceObject(
POBJECTINFO pObjectInfo,
CCredentials& Credentials,
LPVOID * ppObject
)
{
HRESULT hr;
hr = ValidateNamespaceObject(
pObjectInfo
);
BAIL_ON_FAILURE(hr);
hr = CNDSNamespace::CreateNamespace(
L"ADs:",
L"NDS:",
Credentials,
ADS_OBJECT_BOUND,
IID_IUnknown,
ppObject
);
error:
RRETURN(hr);
}
HRESULT
ValidateNamespaceObject(
POBJECTINFO pObjectInfo
)
{
if (!_wcsicmp(pObjectInfo->ProviderName, szProviderName)) {
RRETURN(S_OK);
}
RRETURN(E_FAIL);
}
HRESULT
ValidateProvider(
POBJECTINFO pObjectInfo
)
{
//
// The provider name is case-sensitive. This is a restriction that OLE
// has put on us.
//
if (!(wcscmp(pObjectInfo->ProviderName, szProviderName))) {
RRETURN(S_OK);
}
RRETURN(E_FAIL);
}
//+---------------------------------------------------------------------------
// Function: GetSchemaObject
//
// Synopsis: called by GetObject
//
// Arguments: [POBJECTINFO pObjectInfo]
// [LPVOID * ppObject]
//
// Returns: HRESULT
//
// Modifies: -
//
// History: 11-3-95 krishnag Created.
//
//----------------------------------------------------------------------------
HRESULT
GetSchemaObject(
POBJECTINFO pObjectInfo,
CCredentials& Credentials,
LPVOID * ppObject
)
{
HRESULT hr = S_OK;
DWORD dwObjectType = 0;
WCHAR szParent[MAX_PATH];
WCHAR szCommonName[MAX_PATH];
NDS_CONTEXT_HANDLE hADsContext = NULL;
hr = ValidateSchemaObject(
pObjectInfo,
&dwObjectType
);
BAIL_ON_FAILURE(hr);
hr = BuildADsParentPath(
pObjectInfo,
szParent,
szCommonName
);
BAIL_ON_FAILURE(hr);
switch(dwObjectType) {
case NDS_CLASS_ID:
case NDS_PROPERTY_ID:
case NDS_CLASSPROP_ID:
hr = ADsNdsOpenContext(
pObjectInfo->TreeName,
Credentials,
&hADsContext
);
BAIL_ON_FAILURE(hr);
break;
default:
break;
}
//
// Note: The "error:" tag is at the end of the switch statement,
// so we can simply break out.
//
switch (dwObjectType) {
case NDS_SCHEMA_ID:
hr = CNDSSchema::CreateSchema(
szParent,
szCommonName,
Credentials,
ADS_OBJECT_BOUND,
IID_IUnknown,
ppObject
);
break;
case NDS_CLASSPROP_ID:
hr = CNDSClass::CreateClass(
szParent,
szCommonName,
hADsContext,
Credentials,
ADS_OBJECT_BOUND,
IID_IUnknown,
ppObject
);
if (FAILED(hr)) {
hr = CNDSProperty::CreateProperty(
szParent,
szCommonName,
hADsContext,
Credentials,
ADS_OBJECT_BOUND,
IID_IUnknown,
ppObject
);
BAIL_ON_FAILURE(hr);
}
break;
case NDS_CLASS_ID:
hr = CNDSClass::CreateClass(
szParent,
szCommonName,
hADsContext,
Credentials,
ADS_OBJECT_BOUND,
IID_IUnknown,
ppObject
);
break;
case NDS_PROPERTY_ID:
hr = CNDSProperty::CreateProperty(
szParent,
szCommonName,
hADsContext,
Credentials,
ADS_OBJECT_BOUND,
IID_IUnknown,
ppObject
);
break;
default:
hr = E_ADS_UNKNOWN_OBJECT;
break;
}
error:
if (hADsContext) {
ADsNdsCloseContext(hADsContext);
}
RRETURN(hr);
}
HRESULT
ValidateSchemaObject(
POBJECTINFO pObjectInfo,
PDWORD pdwObjectType
)
{
DWORD dwNumComponents = 0;
dwNumComponents = pObjectInfo->NumComponents;
switch (dwNumComponents) {
case 1:
if (!_wcsicmp(pObjectInfo->ComponentArray[0].szComponent, L"schema")) {
*pdwObjectType = NDS_SCHEMA_ID;
RRETURN(S_OK);
}
break;
case 2:
if (pObjectInfo->ClassName) {
if (!_wcsicmp(pObjectInfo->ClassName, L"Property")) {
*pdwObjectType = NDS_PROPERTY_ID;
}
else {
*pdwObjectType = NDS_CLASS_ID;
}
}
else {
*pdwObjectType = NDS_CLASSPROP_ID;
}
RRETURN(S_OK);
default:
break;
}
RRETURN(E_FAIL);
}
HRESULT
BuildADsParentPath(
POBJECTINFO pObjectInfo,
LPWSTR szParent,
LPWSTR szCommonName
)
{
DWORD i = 0;
DWORD dwNumComponents = 0;
HRESULT hr;
dwNumComponents = pObjectInfo->NumComponents;
if (!dwNumComponents && !pObjectInfo->DisplayTreeName) {
//
// There are no CNs in this pathname and
// no tree name specified. This is the
// namespace object - its parent is the
// @ADs! object
//
wsprintf(szParent,L"ADs:");
RRETURN(S_OK);
} else if (!dwNumComponents && pObjectInfo->DisplayTreeName) {
//
// There are no CNs in this pathname and a tree
// name has been specified. This is the root
// object - its parent is the @NDS! object
wsprintf(szParent, L"%s:", pObjectInfo->ProviderName);
//
// And the common name is the TreeName. Remember the
// "//" will be added on when we reconstruct the full
// pathname
//
wsprintf(szCommonName,L"%s", pObjectInfo->DisplayTreeName);
RRETURN(S_OK);
}else {
//
// There are one or more CNs, a tree name has been
// specified. In the worst case the parent is the
// root object. In the best case a long CN.
//
wsprintf(
szParent, L"%s://%s",
pObjectInfo->ProviderName,
pObjectInfo->DisplayTreeName
);
for (i = 0; i < dwNumComponents - 1; i++) {
wcscat(szParent, L"/");
AppendComponent(szParent, &(pObjectInfo->DisplayComponentArray[i]));
}
//
// And the common name is the last component
//
szCommonName[0] = '\0';
AppendComponent(szCommonName, &(pObjectInfo->DisplayComponentArray[dwNumComponents-1]));
}
RRETURN(S_OK);
}
HRESULT
ValidateObjectType(
POBJECTINFO pObjectInfo
)
{
pObjectInfo->ObjectType = TOKEN_NDSOBJECT;
if (pObjectInfo->ProviderName && !pObjectInfo->TreeName
&& !pObjectInfo->NumComponents) {
pObjectInfo->ObjectType = TOKEN_NAMESPACE;
}else if (pObjectInfo->ProviderName && pObjectInfo->TreeName
&& pObjectInfo->NumComponents) {
if (!_wcsicmp(pObjectInfo->ComponentArray[0].szComponent,L"schema")) {
pObjectInfo->ObjectType = TOKEN_SCHEMA;
}
}
RRETURN(S_OK);
}
HRESULT
BuildNDSTreeNameFromADsPath(
LPWSTR szBuffer,
LPWSTR szNDSTreeName
)
{
OBJECTINFO ObjectInfo;
POBJECTINFO pObjectInfo = &ObjectInfo;
CLexer Lexer(szBuffer);
DWORD dwNumComponents = 0;
HRESULT hr;
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
hr = ADsObject(&Lexer, pObjectInfo);
BAIL_ON_FAILURE(hr);
dwNumComponents = pObjectInfo->NumComponents;
if (!dwNumComponents && !pObjectInfo->TreeName) {
//
// There are no CNs in this pathname and
// no tree name specified. This is the
// namespace object - its parent is the
// @ADs! object
//
hr = E_FAIL;
} else if (!dwNumComponents && pObjectInfo->TreeName) {
//
// There are no CNs in this pathname and a tree
// name has been specified. This is the root
// object - its parent is the @NDS! object
wsprintf(szNDSTreeName,L"\\\\%s", pObjectInfo->TreeName);
hr = S_OK;
}else {
//
// There are one or more CNs, a tree name has been
// specified. In the worst case the parent is the
// root object. In the best case a long CN.
//
wsprintf(szNDSTreeName,L"\\\\%s", pObjectInfo->TreeName);
hr = S_OK;
}
error:
FreeObjectInfo( &ObjectInfo );
RRETURN(hr);
}
HRESULT
BuildNDSPathFromADsPath(
LPWSTR szADsPathName,
LPWSTR szNDSTreeName,
LPWSTR szNDSPathName
)
{
OBJECTINFO ObjectInfo;
POBJECTINFO pObjectInfo = &ObjectInfo;
CLexer Lexer(szADsPathName);
DWORD i = 0;
DWORD dwNumComponents = 0;
HRESULT hr;
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
hr = ADsObject(&Lexer, pObjectInfo);
BAIL_ON_FAILURE(hr);
dwNumComponents = pObjectInfo->NumComponents;
wcscpy(szNDSTreeName, L"\\\\");
wcscat(szNDSTreeName, pObjectInfo->TreeName);
*szNDSPathName = L'\0';
if (dwNumComponents) {
for (i = dwNumComponents; i > 0; i--) {
AppendComponent(
szNDSPathName,
&(pObjectInfo->ComponentArray[i-1])
);
if ((i - 1) > 0){
wcscat(szNDSPathName, L".");
}
}
}
error:
FreeObjectInfo( &ObjectInfo );
RRETURN(hr);
}
VOID
FreeObjectInfo(
POBJECTINFO pObjectInfo
)
{
if ( !pObjectInfo )
return;
FreeADsStr( pObjectInfo->ProviderName );
FreeADsStr( pObjectInfo->TreeName );
FreeADsStr( pObjectInfo->DisplayTreeName );
FreeADsStr( pObjectInfo->ClassName);
for ( DWORD i = 0; i < pObjectInfo->NumComponents; i++ ) {
FreeADsStr( pObjectInfo->ComponentArray[i].szComponent );
FreeADsStr( pObjectInfo->ComponentArray[i].szValue );
FreeADsStr( pObjectInfo->DisplayComponentArray[i].szComponent );
FreeADsStr( pObjectInfo->DisplayComponentArray[i].szValue );
}
// We don't need to free pObjectInfo since the object is always a static
// variable on the stack.
}
HRESULT
GetDisplayName(
LPWSTR szName,
LPWSTR *ppszDisplayName
)
{
HRESULT hr = S_OK;
DWORD len = 0;
LPWSTR pch = szName;
LPWSTR pszDisplayCh = NULL, pszDisplay = NULL;
BOOL fQuotingOn = FALSE;
if (!ppszDisplayName ) {
RRETURN (E_INVALIDARG);
}
*ppszDisplayName = NULL;
if (!szName) {
RRETURN (S_OK);
}
pch = szName;
fQuotingOn = FALSE;
for (len=0; *pch; pch++, len++) {
if ((!(pch > szName && *(pch-1) == '\\')) &&
(*pch == L'"') ) {
fQuotingOn = ~fQuotingOn;
}
else if (!fQuotingOn && (!(pch > szName && *(pch-1) == '\\')) &&
(*pch == L'/' || *pch == L'<' || *pch == L'>') ) {
len++;
}
}
pszDisplay = (LPWSTR) AllocADsMem((len+1) * sizeof(WCHAR));
if (!pszDisplay) {
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
pch = szName;
pszDisplayCh = pszDisplay;
fQuotingOn = FALSE;
for (; *pch; pch++, pszDisplayCh++) {
if ((!(pch > szName && *(pch-1) == '\\')) &&
(*pch == L'"') ) {
fQuotingOn = ~fQuotingOn;
}
else if (!fQuotingOn && (!(pch > szName && *(pch-1) == '\\')) &&
(*pch == L'/' || *pch == L'<' || *pch == L'>') ) {
*pszDisplayCh++ = L'\\';
}
*pszDisplayCh = *pch;
}
*pszDisplayCh = L'\0';
*ppszDisplayName = pszDisplay;
error:
RRETURN(hr);
}
HRESULT
BuildNDSPathFromADsPath2(
LPWSTR szADsPathName,
LPWSTR * pszTreeName,
LPWSTR * pszDn
)
{
OBJECTINFO ObjectInfo;
POBJECTINFO pObjectInfo = &ObjectInfo;
CLexer Lexer(szADsPathName);
DWORD i = 0;
DWORD dwNumComponents = 0;
HRESULT hr;
LPWSTR szTreeName = NULL;
LPWSTR szDn = NULL;
*pszTreeName = NULL;
*pszDn = NULL;
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
hr = ADsObject(&Lexer, pObjectInfo);
BAIL_ON_FAILURE(hr);
dwNumComponents = pObjectInfo->NumComponents;
szTreeName = AllocADsStr(pObjectInfo->TreeName);
szDn = AllocADsStr(szADsPathName);
szDn[0] = L'\0';
if (!szDn) {
hr = E_OUTOFMEMORY;
BAIL_ON_FAILURE(hr);
}
if (dwNumComponents) {
for (i = dwNumComponents; i > 0; i--) {
AppendComponent(
szDn,
&(pObjectInfo->ComponentArray[i-1])
);
if ((i - 1) > 0){
wcscat(szDn, L".");
}
}
}
*pszTreeName = szTreeName;
*pszDn = szDn;
error:
FreeObjectInfo( &ObjectInfo );
RRETURN(hr);
}