//--------------------------------------------------------------------------- // // 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); }