1214 lines
27 KiB
C++
1214 lines
27 KiB
C++
|
//---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1996 - 1997
|
||
|
//
|
||
|
// File: getobj.cxx
|
||
|
//
|
||
|
// Contents: ADSI GetObject functionality
|
||
|
//
|
||
|
// History: 25-Feb-97 SophiaC Created.
|
||
|
// 25-Jun-97 MagnusH Added private extension mechanism
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
#include "iis.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]
|
||
|
// [BOOL bNamespaceRelative]
|
||
|
//
|
||
|
// Returns: HRESULT
|
||
|
//
|
||
|
// Modifies: *ppObject
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
RelativeGetObject(
|
||
|
BSTR ADsPath,
|
||
|
BSTR ClassName,
|
||
|
BSTR RelativeName,
|
||
|
CCredentials& Credentials,
|
||
|
IDispatch * FAR* ppObject,
|
||
|
BOOL bNamespaceRelative
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
LPWSTR pszBuffer = NULL;
|
||
|
DWORD dwLen;
|
||
|
|
||
|
*ppObject = NULL;
|
||
|
|
||
|
if (!RelativeName || !*RelativeName) {
|
||
|
RRETURN(E_ADS_UNKNOWN_OBJECT);
|
||
|
}
|
||
|
|
||
|
dwLen = wcslen(ADsPath) + wcslen(RelativeName) + wcslen(ClassName) + 4;
|
||
|
|
||
|
pszBuffer = (LPWSTR)AllocADsMem(dwLen*sizeof(WCHAR));
|
||
|
|
||
|
if (!pszBuffer) {
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
}
|
||
|
|
||
|
wcscpy(pszBuffer, ADsPath);
|
||
|
|
||
|
if (bNamespaceRelative)
|
||
|
wcscat(pszBuffer, L"//");
|
||
|
else
|
||
|
wcscat(pszBuffer, L"/");
|
||
|
wcscat(pszBuffer, RelativeName);
|
||
|
|
||
|
if (ClassName && *ClassName) {
|
||
|
wcscat(pszBuffer,L",");
|
||
|
wcscat(pszBuffer, ClassName);
|
||
|
}
|
||
|
|
||
|
hr = ::GetObject(
|
||
|
pszBuffer,
|
||
|
Credentials,
|
||
|
(LPVOID *)ppObject
|
||
|
);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
error:
|
||
|
|
||
|
if (pszBuffer) {
|
||
|
FreeADsMem(pszBuffer);
|
||
|
}
|
||
|
|
||
|
RRETURN(hr);
|
||
|
|
||
|
}
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
// Function: GetObject
|
||
|
//
|
||
|
// Synopsis: Called by ResolvePathName to return an object
|
||
|
//
|
||
|
// Arguments: [LPWSTR szBuffer]
|
||
|
// [LPVOID *ppObject]
|
||
|
//
|
||
|
// Returns: HRESULT
|
||
|
//
|
||
|
// Modifies: -
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
GetObject(
|
||
|
LPWSTR szBuffer,
|
||
|
CCredentials& Credentials,
|
||
|
LPVOID * ppObject
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
DWORD dwStatus = NO_ERROR;
|
||
|
|
||
|
WCHAR szCommonName[MAX_PATH+MAX_PROVIDER_TOKEN_LENGTH];
|
||
|
LPWSTR pszParent = NULL;
|
||
|
|
||
|
IMSAdminBase * pAdminBase = NULL;
|
||
|
METADATA_HANDLE hObjHandle = NULL;
|
||
|
METADATA_RECORD mdrData;
|
||
|
|
||
|
LPWSTR pszIISPathName = NULL;
|
||
|
|
||
|
WCHAR DataBuf[MAX_PATH];
|
||
|
DWORD dwReqdBufferLen;
|
||
|
|
||
|
OBJECTINFO ObjectInfo;
|
||
|
POBJECTINFO pObjectInfo = &ObjectInfo;
|
||
|
CLexer Lexer(szBuffer);
|
||
|
|
||
|
IIsSchema *pSchema = NULL;
|
||
|
|
||
|
IADs * pADs = NULL;
|
||
|
|
||
|
//
|
||
|
// Parse the pathname
|
||
|
//
|
||
|
|
||
|
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 @IIS!
|
||
|
//
|
||
|
|
||
|
hr = InitServerInfo(pObjectInfo->TreeName, &pAdminBase, &pSchema);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
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,
|
||
|
pSchema,
|
||
|
ppObject
|
||
|
);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
break;
|
||
|
|
||
|
case TOKEN_CLASS:
|
||
|
|
||
|
hr = GetClassObject(
|
||
|
pObjectInfo,
|
||
|
pSchema,
|
||
|
ppObject
|
||
|
);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
break;
|
||
|
|
||
|
case TOKEN_PROPERTY:
|
||
|
|
||
|
hr = GetPropertyObject(
|
||
|
pObjectInfo,
|
||
|
pSchema,
|
||
|
ppObject
|
||
|
);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
break;
|
||
|
|
||
|
case TOKEN_SYNTAX:
|
||
|
|
||
|
hr = GetSyntaxObject(
|
||
|
pObjectInfo,
|
||
|
ppObject
|
||
|
);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
|
||
|
pszIISPathName = AllocADsStr(szBuffer);
|
||
|
|
||
|
if (!pszIISPathName) {
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
}
|
||
|
|
||
|
*pszIISPathName = L'\0';
|
||
|
hr = BuildIISPathFromADsPath(
|
||
|
pObjectInfo,
|
||
|
pszIISPathName
|
||
|
);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
hr = OpenAdminBaseKey(
|
||
|
pObjectInfo->TreeName,
|
||
|
(LPWSTR)pszIISPathName,
|
||
|
METADATA_PERMISSION_READ,
|
||
|
&pAdminBase,
|
||
|
&hObjHandle
|
||
|
);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
//
|
||
|
// Find out Class Name
|
||
|
//
|
||
|
|
||
|
mdrData.dwMDIdentifier = MD_KEY_TYPE;
|
||
|
mdrData.dwMDDataType = STRING_METADATA;
|
||
|
mdrData.dwMDUserType = ALL_METADATA;
|
||
|
mdrData.dwMDAttributes = METADATA_INHERIT;
|
||
|
mdrData.dwMDDataLen = MAX_PATH;
|
||
|
mdrData.pbMDData = (PBYTE)DataBuf;
|
||
|
|
||
|
hr = pAdminBase->GetData(
|
||
|
hObjHandle,
|
||
|
L"",
|
||
|
&mdrData,
|
||
|
&dwReqdBufferLen
|
||
|
);
|
||
|
|
||
|
if (FAILED(hr)) {
|
||
|
if (hr == MD_ERROR_DATA_NOT_FOUND) {
|
||
|
|
||
|
memcpy((LPWSTR)DataBuf, DEFAULT_SCHEMA_CLASS_W,
|
||
|
SIZEOF_DEFAULT_CLASS_W);
|
||
|
|
||
|
if (pObjectInfo->ClassName[0] != L'\0' &&
|
||
|
_wcsicmp((LPWSTR)pObjectInfo->ClassName, DataBuf)) {
|
||
|
hr = E_ADS_BAD_PARAMETER;
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
if (pObjectInfo->ClassName[0] != L'\0' &&
|
||
|
_wcsicmp((LPWSTR)pObjectInfo->ClassName, DataBuf)) {
|
||
|
hr = E_ADS_BAD_PARAMETER;
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
}
|
||
|
|
||
|
hr = pSchema->ValidateClassName((LPWSTR)DataBuf);
|
||
|
if (hr == E_ADS_SCHEMA_VIOLATION) {
|
||
|
memcpy((LPWSTR)DataBuf, DEFAULT_SCHEMA_CLASS_W,
|
||
|
SIZEOF_DEFAULT_CLASS_W);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Close the handle now
|
||
|
//
|
||
|
|
||
|
if (hObjHandle) {
|
||
|
CloseAdminBaseKey(pAdminBase, hObjHandle);
|
||
|
hObjHandle = NULL;
|
||
|
}
|
||
|
|
||
|
pszParent = AllocADsStr(szBuffer);
|
||
|
|
||
|
if (!pszParent) {
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
}
|
||
|
|
||
|
*pszParent = L'\0';
|
||
|
|
||
|
hr = BuildADsParentPath(
|
||
|
szBuffer,
|
||
|
pszParent,
|
||
|
szCommonName
|
||
|
);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
hr = CIISGenObject::CreateGenericObject(
|
||
|
pszParent,
|
||
|
szCommonName,
|
||
|
(LPWSTR)DataBuf,
|
||
|
Credentials,
|
||
|
ADS_OBJECT_BOUND,
|
||
|
IID_IDispatch,
|
||
|
(void **)&pADs
|
||
|
);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
hr = pADs->QueryInterface(
|
||
|
IID_IDispatch,
|
||
|
ppObject
|
||
|
);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
|
||
|
if (pAdminBase && hObjHandle) {
|
||
|
CloseAdminBaseKey(pAdminBase, hObjHandle);
|
||
|
}
|
||
|
|
||
|
if (pADs) {
|
||
|
pADs->Release();
|
||
|
}
|
||
|
|
||
|
if (pszIISPathName) {
|
||
|
FreeADsStr(pszIISPathName);
|
||
|
}
|
||
|
|
||
|
if (pszParent) {
|
||
|
FreeADsStr(pszParent);
|
||
|
}
|
||
|
|
||
|
FreeObjectInfo( &ObjectInfo );
|
||
|
|
||
|
RRETURN(hr);
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
BuildIISPathFromADsPath(
|
||
|
LPWSTR szADsPathName,
|
||
|
LPWSTR * pszIISPathName
|
||
|
)
|
||
|
{
|
||
|
OBJECTINFO ObjectInfo;
|
||
|
POBJECTINFO pObjectInfo = &ObjectInfo;
|
||
|
CLexer Lexer(szADsPathName);
|
||
|
DWORD i = 0;
|
||
|
HRESULT hr;
|
||
|
LPWSTR szIISPathName = NULL;
|
||
|
|
||
|
*pszIISPathName = NULL;
|
||
|
|
||
|
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
|
||
|
hr = ADsObject(&Lexer, pObjectInfo);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
szIISPathName = AllocADsStr(szADsPathName);
|
||
|
if (!szIISPathName) {
|
||
|
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
}
|
||
|
|
||
|
*szIISPathName = L'\0';
|
||
|
hr = BuildIISPathFromADsPath(pObjectInfo, szIISPathName);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
*pszIISPathName = szIISPathName;
|
||
|
|
||
|
error:
|
||
|
|
||
|
FreeObjectInfo( &ObjectInfo );
|
||
|
|
||
|
RRETURN(hr);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT
|
||
|
BuildIISPathFromADsPath(
|
||
|
POBJECTINFO pObjectInfo,
|
||
|
LPWSTR pszIISPathName
|
||
|
)
|
||
|
{
|
||
|
|
||
|
DWORD dwNumComponents = 0;
|
||
|
DWORD i = 0;
|
||
|
|
||
|
dwNumComponents = pObjectInfo->NumComponents;
|
||
|
|
||
|
//
|
||
|
// wcscat "LM" to IIS Metabase path
|
||
|
//
|
||
|
|
||
|
wcscat(pszIISPathName, L"/LM/");
|
||
|
|
||
|
if (dwNumComponents) {
|
||
|
|
||
|
for (i = 0; i < dwNumComponents; i++) {
|
||
|
|
||
|
wcscat(pszIISPathName, pObjectInfo->ComponentArray[i].szComponent);
|
||
|
if( i < dwNumComponents -1 ) {
|
||
|
wcscat(pszIISPathName,L"/");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RRETURN(S_OK);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT
|
||
|
BuildADsParentPath(
|
||
|
LPWSTR szBuffer,
|
||
|
LPWSTR szParent,
|
||
|
LPWSTR szCommonName
|
||
|
)
|
||
|
{
|
||
|
OBJECTINFO ObjectInfo;
|
||
|
POBJECTINFO pObjectInfo = &ObjectInfo;
|
||
|
CLexer Lexer(szBuffer);
|
||
|
DWORD i = 0;
|
||
|
DWORD dwNumComponents = 0;
|
||
|
HRESULT hr;
|
||
|
LPWSTR pszComponent = NULL, pszValue = NULL;
|
||
|
|
||
|
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
|
||
|
//
|
||
|
|
||
|
wsprintf(szParent,L"ADs:");
|
||
|
|
||
|
hr = S_OK;
|
||
|
|
||
|
} 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 @IIS! object
|
||
|
|
||
|
wsprintf(szParent, L"%s:", pObjectInfo->ProviderName);
|
||
|
|
||
|
//
|
||
|
// And the common name is the TreeName
|
||
|
//
|
||
|
|
||
|
wsprintf(szCommonName,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(
|
||
|
szParent, L"%s://%s",
|
||
|
pObjectInfo->ProviderName,
|
||
|
pObjectInfo->TreeName
|
||
|
);
|
||
|
|
||
|
for (i = 0; i < dwNumComponents - 1; i++) {
|
||
|
|
||
|
wcscat(szParent, L"/");
|
||
|
|
||
|
|
||
|
pszComponent = pObjectInfo->ComponentArray[i].szComponent;
|
||
|
pszValue = pObjectInfo->ComponentArray[i].szValue;
|
||
|
|
||
|
|
||
|
if (pszComponent && pszValue) {
|
||
|
|
||
|
wcscat(
|
||
|
szParent,
|
||
|
pObjectInfo->ComponentArray[i].szComponent
|
||
|
);
|
||
|
wcscat(szParent,L"=");
|
||
|
wcscat(
|
||
|
szParent,
|
||
|
pObjectInfo->ComponentArray[i].szValue
|
||
|
);
|
||
|
}else if (pszComponent){
|
||
|
|
||
|
wcscat(
|
||
|
szParent,
|
||
|
pObjectInfo->ComponentArray[i].szComponent
|
||
|
);
|
||
|
|
||
|
}else {
|
||
|
//
|
||
|
// Error - we should never hit this case!!
|
||
|
//
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// And the common name is the last component
|
||
|
//
|
||
|
|
||
|
pszComponent = pObjectInfo->ComponentArray[dwNumComponents - 1].szComponent;
|
||
|
pszValue = pObjectInfo->ComponentArray[dwNumComponents - 1].szValue;
|
||
|
|
||
|
|
||
|
if (pszComponent && pszValue) {
|
||
|
|
||
|
wsprintf(szCommonName, L"%s=%s",pszComponent, pszValue);
|
||
|
|
||
|
}else if (pszComponent){
|
||
|
|
||
|
wsprintf(szCommonName, L"%s", pszComponent);
|
||
|
|
||
|
}else {
|
||
|
//
|
||
|
// Error - we should never hit this case!!
|
||
|
//
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
|
||
|
FreeObjectInfo( &ObjectInfo );
|
||
|
RRETURN(hr);
|
||
|
|
||
|
}
|
||
|
|
||
|
HRESULT
|
||
|
BuildADsParentPath(
|
||
|
POBJECTINFO pObjectInfo,
|
||
|
LPWSTR szParent,
|
||
|
LPWSTR szCommonName
|
||
|
)
|
||
|
{
|
||
|
DWORD i = 0;
|
||
|
DWORD dwNumComponents = 0;
|
||
|
HRESULT hr;
|
||
|
LPWSTR pszComponent = NULL, pszValue = NULL;
|
||
|
|
||
|
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
|
||
|
//
|
||
|
|
||
|
wsprintf(szParent,L"ADs:");
|
||
|
|
||
|
RRETURN(S_OK);
|
||
|
|
||
|
} 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 @IIS! 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->TreeName);
|
||
|
|
||
|
|
||
|
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->TreeName
|
||
|
);
|
||
|
|
||
|
for (i = 0; i < dwNumComponents - 1; i++) {
|
||
|
|
||
|
wcscat(szParent, L"/");
|
||
|
|
||
|
|
||
|
pszComponent = pObjectInfo->ComponentArray[i].szComponent;
|
||
|
pszValue = pObjectInfo->ComponentArray[i].szValue;
|
||
|
|
||
|
|
||
|
if (pszComponent && pszValue) {
|
||
|
|
||
|
wcscat(
|
||
|
szParent,
|
||
|
pObjectInfo->ComponentArray[i].szComponent
|
||
|
);
|
||
|
wcscat(szParent,L"=");
|
||
|
wcscat(
|
||
|
szParent,
|
||
|
pObjectInfo->ComponentArray[i].szValue
|
||
|
);
|
||
|
}else if (pszComponent){
|
||
|
|
||
|
wcscat(
|
||
|
szParent,
|
||
|
pObjectInfo->ComponentArray[i].szComponent
|
||
|
);
|
||
|
|
||
|
}else {
|
||
|
//
|
||
|
// Error - we should never hit this case!!
|
||
|
//
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// And the common name is the last component
|
||
|
//
|
||
|
|
||
|
pszComponent = pObjectInfo->ComponentArray[dwNumComponents - 1].szComponent;
|
||
|
pszValue = pObjectInfo->ComponentArray[dwNumComponents - 1].szValue;
|
||
|
|
||
|
|
||
|
if (pszComponent && pszValue) {
|
||
|
|
||
|
wsprintf(szCommonName, L"%s=%s",pszComponent, pszValue);
|
||
|
|
||
|
}else if (pszComponent){
|
||
|
|
||
|
wsprintf(szCommonName, L"%s", pszComponent);
|
||
|
|
||
|
}else {
|
||
|
//
|
||
|
// Error - we should never hit this case!!
|
||
|
//
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RRETURN(S_OK);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
VOID
|
||
|
FreeObjectInfo(
|
||
|
POBJECTINFO pObjectInfo
|
||
|
)
|
||
|
{
|
||
|
if ( !pObjectInfo )
|
||
|
return;
|
||
|
|
||
|
FreeADsStr( pObjectInfo->ProviderName );
|
||
|
FreeADsStr( pObjectInfo->TreeName );
|
||
|
|
||
|
for ( DWORD i = 0; i < pObjectInfo->NumComponents; i++ ) {
|
||
|
|
||
|
if (pObjectInfo->ComponentArray[i].szComponent) {
|
||
|
FreeADsStr( pObjectInfo->ComponentArray[i].szComponent );
|
||
|
}
|
||
|
if (pObjectInfo->ComponentArray[i].szValue) {
|
||
|
FreeADsStr( pObjectInfo->ComponentArray[i].szValue );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pObjectInfo->ComponentArray) {
|
||
|
FreeADsMem(pObjectInfo->ComponentArray);
|
||
|
}
|
||
|
|
||
|
// We don't need to free pObjectInfo since the object is always a static
|
||
|
// variable on the stack.
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
// Function: GetNamespaceObject
|
||
|
//
|
||
|
// Synopsis: called by GetObject
|
||
|
//
|
||
|
// Arguments: [POBJECTINFO pObjectInfo]
|
||
|
// [LPVOID * ppObject]
|
||
|
//
|
||
|
// Returns: HRESULT
|
||
|
//
|
||
|
// Modifies: -
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
GetNamespaceObject(
|
||
|
POBJECTINFO pObjectInfo,
|
||
|
CCredentials& Credentials,
|
||
|
LPVOID * ppObject
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
hr = ValidateNamespaceObject(
|
||
|
pObjectInfo
|
||
|
);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
hr = CIISNamespace::CreateNamespace(
|
||
|
L"ADs:",
|
||
|
L"IIS:",
|
||
|
Credentials,
|
||
|
ADS_OBJECT_BOUND,
|
||
|
IID_IUnknown,
|
||
|
ppObject
|
||
|
);
|
||
|
|
||
|
|
||
|
error:
|
||
|
|
||
|
RRETURN(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
// Function: GetSchemaObject
|
||
|
//
|
||
|
// Synopsis: called by GetObject
|
||
|
//
|
||
|
// Arguments: [POBJECTINFO pObjectInfo]
|
||
|
// [LPVOID * ppObject]
|
||
|
//
|
||
|
// Returns: HRESULT
|
||
|
//
|
||
|
// Modifies: -
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
GetSchemaObject(
|
||
|
POBJECTINFO pObjectInfo,
|
||
|
IIsSchema *pSchemaCache,
|
||
|
LPVOID * ppObject
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
DWORD dwObjectType = 0;
|
||
|
|
||
|
hr = ValidateSchemaObject(
|
||
|
pObjectInfo,
|
||
|
&dwObjectType
|
||
|
);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
//
|
||
|
// Note: The "error:" tag is at the end of the switch statement,
|
||
|
// so we can simply break out.
|
||
|
//
|
||
|
|
||
|
switch (dwObjectType) {
|
||
|
case IIS_SCHEMA_ID:
|
||
|
hr = GetIntSchemaObject(
|
||
|
pObjectInfo,
|
||
|
ppObject
|
||
|
);
|
||
|
break;
|
||
|
|
||
|
case IIS_CLASSPROP_ID:
|
||
|
hr = GetClassObject(
|
||
|
pObjectInfo,
|
||
|
pSchemaCache,
|
||
|
ppObject
|
||
|
);
|
||
|
if (FAILED(hr)) {
|
||
|
|
||
|
hr = GetPropertyObject(
|
||
|
pObjectInfo,
|
||
|
pSchemaCache,
|
||
|
ppObject
|
||
|
);
|
||
|
if (FAILED(hr)) {
|
||
|
|
||
|
hr = GetSyntaxObject(
|
||
|
pObjectInfo,
|
||
|
ppObject
|
||
|
);
|
||
|
}
|
||
|
if (FAILED(hr)) {
|
||
|
hr = E_ADS_UNKNOWN_OBJECT;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
hr = E_ADS_UNKNOWN_OBJECT;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
RRETURN(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
// Function: GetSchemaObject
|
||
|
//
|
||
|
// Synopsis:
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
GetIntSchemaObject(
|
||
|
POBJECTINFO pObjInfo,
|
||
|
LPVOID * ppObject
|
||
|
)
|
||
|
{
|
||
|
LPUNKNOWN pUnknown = NULL;
|
||
|
WCHAR ADsParent[MAX_PATH+MAX_PROVIDER_TOKEN_LENGTH];
|
||
|
WCHAR ADsName[MAX_PATH];
|
||
|
HRESULT hr = S_OK;
|
||
|
|
||
|
if (pObjInfo->NumComponents != 1)
|
||
|
RRETURN(E_ADS_BAD_PATHNAME);
|
||
|
|
||
|
if ( _wcsicmp( pObjInfo->ComponentArray[0].szComponent, SCHEMA_NAME ) != 0 )
|
||
|
{
|
||
|
hr = E_ADS_BAD_PATHNAME;
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
}
|
||
|
|
||
|
hr = BuildADsParentPath(pObjInfo, ADsParent, ADsName);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
hr = CIISSchema::CreateSchema( pObjInfo->TreeName,
|
||
|
ADsParent,
|
||
|
pObjInfo->ComponentArray[0].szComponent,
|
||
|
ADS_OBJECT_BOUND,
|
||
|
IID_IUnknown,
|
||
|
(void **)&pUnknown );
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
*ppObject = pUnknown;
|
||
|
|
||
|
RRETURN(hr);
|
||
|
|
||
|
error:
|
||
|
if (pUnknown)
|
||
|
pUnknown->Release();
|
||
|
|
||
|
*ppObject = NULL;
|
||
|
RRETURN(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
// Function: GetClassObject
|
||
|
//
|
||
|
// Synopsis:
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
GetClassObject(
|
||
|
POBJECTINFO pObjInfo,
|
||
|
IIsSchema *pSchemaCache,
|
||
|
LPVOID * ppObject
|
||
|
)
|
||
|
{
|
||
|
LPUNKNOWN pUnknown = NULL;
|
||
|
WCHAR ADsParent[MAX_PATH+MAX_PROVIDER_TOKEN_LENGTH];
|
||
|
WCHAR ADsName[MAX_PATH];
|
||
|
HRESULT hr = S_OK;
|
||
|
DWORD i;
|
||
|
DWORD dwNumComponents = pObjInfo->NumComponents;
|
||
|
|
||
|
if ( dwNumComponents != 2 && dwNumComponents != 3)
|
||
|
RRETURN(E_ADS_BAD_PATHNAME);
|
||
|
|
||
|
if ( (dwNumComponents == 2 &&
|
||
|
_wcsicmp( pObjInfo->ComponentArray[0].szComponent, SCHEMA_NAME ) != 0 ) ||
|
||
|
(dwNumComponents == 3 &&
|
||
|
_wcsicmp( pObjInfo->ComponentArray[0].szComponent, CLASS_CLASS_NAME ) != 0 ))
|
||
|
{
|
||
|
hr = E_ADS_BAD_PATHNAME;
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Validate the given class name
|
||
|
//
|
||
|
hr = pSchemaCache->ValidateClassName(
|
||
|
pObjInfo->ComponentArray[dwNumComponents-1].szComponent);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
//
|
||
|
// Class name found, create and return the object
|
||
|
//
|
||
|
|
||
|
hr = BuildADsParentPath(pObjInfo, ADsParent, ADsName);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
hr = CIISClass::CreateClass( ADsParent,
|
||
|
pObjInfo->ComponentArray[dwNumComponents-1].szComponent,
|
||
|
ADS_OBJECT_BOUND,
|
||
|
IID_IUnknown,
|
||
|
(void **)&pUnknown );
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
*ppObject = pUnknown;
|
||
|
|
||
|
RRETURN(hr);
|
||
|
|
||
|
error:
|
||
|
if (pUnknown)
|
||
|
pUnknown->Release();
|
||
|
|
||
|
*ppObject = NULL;
|
||
|
RRETURN(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
// Function: GetSyntaxObject
|
||
|
//
|
||
|
// Synopsis:
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
GetSyntaxObject(
|
||
|
POBJECTINFO pObjInfo,
|
||
|
LPVOID * ppObject
|
||
|
)
|
||
|
{
|
||
|
LPUNKNOWN pUnknown = NULL;
|
||
|
WCHAR ADsParent[MAX_PATH+MAX_PROVIDER_TOKEN_LENGTH];
|
||
|
WCHAR ADsName[MAX_PATH];
|
||
|
HRESULT hr = S_OK;
|
||
|
DWORD i;
|
||
|
DWORD dwNumComponents = pObjInfo->NumComponents;
|
||
|
|
||
|
if (dwNumComponents != 2 && dwNumComponents != 3)
|
||
|
RRETURN(E_ADS_BAD_PATHNAME);
|
||
|
|
||
|
if ( (dwNumComponents == 2 &&
|
||
|
_wcsicmp( pObjInfo->ComponentArray[0].szComponent, SCHEMA_NAME ) != 0 ) ||
|
||
|
(dwNumComponents == 3 &&
|
||
|
_wcsicmp( pObjInfo->ComponentArray[0].szComponent, SYNTAX_CLASS_NAME ) != 0 ))
|
||
|
{
|
||
|
hr = E_ADS_BAD_PATHNAME;
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Look for the given syntax name
|
||
|
//
|
||
|
|
||
|
for ( i = 0; i < g_cIISSyntax; i++ )
|
||
|
{
|
||
|
if ( _wcsicmp( g_aIISSyntax[i].bstrName,
|
||
|
pObjInfo->ComponentArray[dwNumComponents-1].szComponent ) == 0 )
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ( i == g_cIISSyntax )
|
||
|
{
|
||
|
// Syntax name not found, return error
|
||
|
|
||
|
hr = E_ADS_BAD_PATHNAME;
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Syntax name found, create and return the object
|
||
|
//
|
||
|
|
||
|
hr = BuildADsParentPath(pObjInfo, ADsParent, ADsName);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
hr = CIISSyntax::CreateSyntax( ADsParent,
|
||
|
&(g_aIISSyntax[i]),
|
||
|
ADS_OBJECT_BOUND,
|
||
|
IID_IUnknown,
|
||
|
(void **)&pUnknown );
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
*ppObject = pUnknown;
|
||
|
|
||
|
RRETURN(hr);
|
||
|
|
||
|
error:
|
||
|
if (pUnknown)
|
||
|
pUnknown->Release();
|
||
|
|
||
|
*ppObject = NULL;
|
||
|
RRETURN(hr);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+---------------------------------------------------------------------------
|
||
|
// Function: GetPropertyObject
|
||
|
//
|
||
|
// Synopsis:
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// Returns:
|
||
|
//
|
||
|
// Modifies:
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
GetPropertyObject(
|
||
|
POBJECTINFO pObjInfo,
|
||
|
IIsSchema *pSchemaCache,
|
||
|
LPVOID * ppObject
|
||
|
)
|
||
|
{
|
||
|
LPUNKNOWN pUnknown = NULL;
|
||
|
WCHAR ADsParent[MAX_PATH+MAX_PROVIDER_TOKEN_LENGTH];
|
||
|
WCHAR ADsName[MAX_PATH];
|
||
|
HRESULT hr = S_OK;
|
||
|
DWORD i;
|
||
|
DWORD dwNumComponents = pObjInfo->NumComponents;
|
||
|
|
||
|
if (dwNumComponents != 2 && dwNumComponents != 3)
|
||
|
RRETURN(E_ADS_BAD_PATHNAME);
|
||
|
|
||
|
if ( (dwNumComponents == 2 &&
|
||
|
_wcsicmp( pObjInfo->ComponentArray[0].szComponent, SCHEMA_NAME ) != 0 ) ||
|
||
|
(dwNumComponents == 3 &&
|
||
|
_wcsicmp( pObjInfo->ComponentArray[0].szComponent, PROPERTY_CLASS_NAME ) != 0 ))
|
||
|
{
|
||
|
hr = E_ADS_BAD_PATHNAME;
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Validate the given property name
|
||
|
//
|
||
|
hr = pSchemaCache->ValidatePropertyName(
|
||
|
pObjInfo->ComponentArray[dwNumComponents-1].szComponent);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
//
|
||
|
// Property name is found, so create and return the object
|
||
|
//
|
||
|
|
||
|
hr = BuildADsParentPath(pObjInfo, ADsParent, ADsName);
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
|
||
|
hr = CIISProperty::CreateProperty(
|
||
|
ADsParent,
|
||
|
pObjInfo->ComponentArray[dwNumComponents-1].szComponent,
|
||
|
ADS_OBJECT_BOUND,
|
||
|
IID_IUnknown,
|
||
|
(void **)&pUnknown );
|
||
|
BAIL_ON_FAILURE(hr);
|
||
|
|
||
|
*ppObject = pUnknown;
|
||
|
|
||
|
RRETURN(hr);
|
||
|
|
||
|
error:
|
||
|
if (pUnknown)
|
||
|
pUnknown->Release();
|
||
|
|
||
|
*ppObject = NULL;
|
||
|
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);
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT
|
||
|
ValidateObjectType(
|
||
|
POBJECTINFO pObjectInfo
|
||
|
)
|
||
|
{
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
else if (!_wcsicmp(pObjectInfo->ComponentArray[0].szComponent,L"class")) {
|
||
|
pObjectInfo->ObjectType = TOKEN_CLASS;
|
||
|
}
|
||
|
else if (!_wcsicmp(pObjectInfo->ComponentArray[0].szComponent,L"property")) {
|
||
|
pObjectInfo->ObjectType = TOKEN_PROPERTY;
|
||
|
}
|
||
|
else if (!_wcsicmp(pObjectInfo->ComponentArray[0].szComponent,L"syntax")) {
|
||
|
pObjectInfo->ObjectType = TOKEN_SYNTAX;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
RRETURN(S_OK);
|
||
|
}
|
||
|
|
||
|
|
||
|
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 = IIS_SCHEMA_ID;
|
||
|
RRETURN(S_OK);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 2:
|
||
|
|
||
|
*pdwObjectType = IIS_CLASSPROP_ID;
|
||
|
RRETURN(S_OK);
|
||
|
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
RRETURN(E_FAIL);
|
||
|
}
|