Beispielcode zum Erstellen einer Klasse

Das folgende C- und C++-Codebeispiel zeigt, wie ein classSchema-Objekt im ADSI-Cache erstellt wird.

Die CreateClass-Beispielfunktion zeigt, wie das classSchema-Objekt erstellt wird, und gibt einen IADs-Zeiger auf das neue Objekt zurück. Beachten Sie, dass CreateClass nicht IADs::SetInfo aufruft, um das neue classSchema-Objekt in das Verzeichnis zu commiten. Der Aufrufer muss den Aufruf mit dem zurückgegebenen Zeiger machen.

Das folgende BytesToVariantArray-Codebeispiel zeigt eine Hilfsfunktion, die eine Oktettzeichenfolge in ein Variantarray packt.

HRESULT BytesToVariantArray(PBYTE pValue, 
                            ULONG cValueElements, 
                            VARIANT *pVariant);

////////////////////////////////////////////////////////// 
// CreateClass routine
// Calls IADsContainer::Create to create a new classSchema object in
// the schema container. Sets key properties of the new class.
// Be aware that the CreateClass routine does not commit the new class
// to the directory. The CreateClass caller must commit 
// the new class by calling IADs::SetInfo on the returned 
// pointer to the new class object.
////////////////////////////////////////////////////////// 
HRESULT CreateClass(
    IADsContainer *pSchema,
    LPOLESTR szClassName,
    LPOLESTR szLDAPDisplayName,
    LPOLESTR szClassOID,
    const GUID * pSchemaIDGUID,
    LPOLESTR szSubClassOf,
    LPOLESTR *arrayAuxiliaryClasses,
    DWORD dwSizearrayAuxiliaryClasses,
    LPOLESTR szDefaultObjectCategory,
    LPOLESTR szDescription,
    BOOL bDefaultHidingValue,
    LPOLESTR szDefaultSecurityDescriptor,
    LPOLESTR szRDNAttribute,
    int iObjectClassCategory,
    LPOLESTR *arrayPossibleSuperiors,
    DWORD dwSizearrayPossibleSuperiors,
    LPOLESTR *arrayMustContain,
    DWORD dwSizearrayMustContain,
    LPOLESTR *arrayMayContain,
    DWORD dwSizearrayMayContain,
    LPOLESTR szAdminDisplayName,
    IADs **ppNewClass // Return an IADs pointer to the new class.
    )
{
    if ((!szClassName)
        ||(!szClassOID)
        ||(!szSubClassOf)
        ||(!iObjectClassCategory)
        ||(!arrayPossibleSuperiors)
    )
    {
        return E_INVALIDARG;
    }

    if (!ppNewClass)
    {
        return E_POINTER;
    }

    HRESULT hr = E_FAIL;
    IDispatch *pDisp = NULL;
    LPOLESTR szStart = L"cn=";
    DWORD dwLength = wcslen(szStart) + wcslen(szClassName) + 1;
    LPOLESTR szBuffer = new OLECHAR[dwLength];
    wcscpy_s(szBuffer,szStart);
    wcscat_s(szBuffer,szClassName);
    *ppNewClass = NULL;
    VARIANT var;

    VariantInit(&var);

    if (!pSchema)
    {
        return E_POINTER;
    }

    hr = pSchema->Create(CComBSTR("classSchema"), 
                         CComBSTR(szBuffer), 
                         &pDisp);
    delete [] szBuffer;

    if (SUCCEEDED(hr))
    {
        hr = pDisp->QueryInterface(IID_IADs, (void**)ppNewClass);

        while (SUCCEEDED(hr))
        {
            // Put this value so that it can be read from the cache.
            var.vt = VT_BSTR;
            var.bstrVal = SysAllocString(szClassName);
            hr = (*ppNewClass)->Put(CComBSTR("cn"), var);
            VariantClear(&var);
         
            // Put lDAPDisplayName.
            // If NULL, let it default; that is do not set it.
            if (szLDAPDisplayName)
            {
                var.vt = VT_BSTR;
                var.bstrVal = SysAllocString(szLDAPDisplayName);
                hr = (*ppNewClass)->Put(CComBSTR("lDAPDisplayName"), 
                                        var);
                VariantClear(&var);
            }
         
            // Put attributeID.
            var.vt = VT_BSTR;
            var.bstrVal = SysAllocString(szClassOID);
            hr = (*ppNewClass)->Put(CComBSTR("governsID"), var);
            VariantClear(&var);
         
            // Put schemaIDGUID.
            // If NULL, let it default; that is do not set it.
            if (pSchemaIDGUID)
            {
                hr = BytesToVariantArray(
                    (LPBYTE)pSchemaIDGUID, // Pointer to bytes to 
                                           // put in a variant array.
                    sizeof(GUID),       // Size, in bytes, of pValue.
                    &var // Return variant containing 
                         // octet string (VT_UI1|VT_ARRAY).
                    );

                if (SUCCEEDED(hr))
                {
                    hr = (*ppNewClass)->Put(CComBSTR("schemaIDGUID"), 
                                            var);
                    VariantClear(&var);
                }
            }
         
            // Put subClassOf.
            var.vt = VT_BSTR;
            // Verify existence of the class.
            var.bstrVal = SysAllocString(szSubClassOf);
            hr = (*ppNewClass)->Put(CComBSTR("subClassOf"), var);
            VariantClear(&var);
         
            // Put defaultObjectCategory.
            // If NULL, do not set it.
            if (szDefaultObjectCategory)
            {
                var.vt = VT_BSTR;
                    // Verify that it is a valid DN.
                var.bstrVal = SysAllocString(szDefaultObjectCategory);
                hr = (*ppNewClass)->Put(CComBSTR("defaultObjectCategory"), 
                                                 var);
                VariantClear(&var);
            }
         
            // Put objectClassCategory.
            var.vt = VT_I4;
            var.lVal = iObjectClassCategory;
            hr = (*ppNewClass)->Put(CComBSTR("objectClassCategory"), 
                                    var);
            VariantClear(&var);
         
            // Put defaultHidingValue.
            var.vt = VT_BOOL;
            if (bDefaultHidingValue)
            {
                var.boolVal = VARIANT_TRUE;
            }
            else
            {
                var.boolVal = VARIANT_FALSE;
            }
            hr = (*ppNewClass)->Put(CComBSTR("defaultHidingValue"), 
                                    var);
            VariantClear(&var);
         
            // Put RDNAttrID.
            // If NULL, do not set it.
            if (szRDNAttribute)
            {
                var.vt = VT_BSTR;

                // Verify that it is a valid attribute.
                var.bstrVal = SysAllocString(szRDNAttribute);
                hr = (*ppNewClass)->Put(CComBSTR("rDNAttID"), var);
                VariantClear(&var);
            }
         
            // Put defaultSecurityDescriptor.
            // If NULL, let it default; that is do not set it.
            if (szDefaultSecurityDescriptor)
            {
                var.vt = VT_BSTR;
                var.bstrVal = 
                  SysAllocString(szDefaultSecurityDescriptor);
                hr = 
                  (*ppNewClass)->Put(CComBSTR("defaultSecurityDescriptor"), 
                                     var);
                VariantClear(&var);
            }
         
            if (arrayPossibleSuperiors && 
                dwSizearrayPossibleSuperiors)
            {
                // Build a Variant of array type, using the 
                // specified string array.
                hr = ADsBuildVarArrayStr(arrayPossibleSuperiors, 
                                         dwSizearrayPossibleSuperiors, 
                                         &var);
                if (SUCCEEDED(hr))
                {
                    // Verify that all the specified classes
                    // are valid.
                    hr = (*ppNewClass)->Put(CComBSTR("possSuperiors"), 
                                            var);
                    VariantClear(&var);
                }
            }
         
            if (arrayMustContain && dwSizearrayMustContain)
            {
                // Build a Variant of array type, 
                // using the specified string array.
                hr = ADsBuildVarArrayStr(arrayMustContain, 
                                         dwSizearrayMustContain,
                                         &var);
                if (SUCCEEDED(hr))
                {
                    // Verify that all the specified 
                    // attributes are valid.
                    hr = (*ppNewClass)->Put(CComBSTR("mustContain"), 
                                            var);
                    VariantClear(&var);
                }
            }
         
            if (arrayMayContain && dwSizearrayMayContain)
            {
                // Build a Variant of array type, 
                // using the specified string array.
                hr = ADsBuildVarArrayStr(arrayMayContain, 
                                         dwSizearrayMayContain, 
                                         &var);
                if (SUCCEEDED(hr))
                {
                    // Verify that all the specified 
                    // attributes are valid.
                    hr = (*ppNewClass)->Put(CComBSTR("mayContain"), 
                                            var);
                    VariantClear(&var);
                }
            }
         
            if (arrayAuxiliaryClasses && 
                dwSizearrayAuxiliaryClasses)
            {
                // Build a Variant of array type,
                // using the specified string array.
                hr = ADsBuildVarArrayStr(arrayAuxiliaryClasses, 
                                         dwSizearrayAuxiliaryClasses,
                                         &var);
                if (SUCCEEDED(hr))
                {
                    // Verify that all the 
                    // specified classes are valid.
                    hr = (*ppNewClass)->Put(CComBSTR("auxiliaryClass"),
                                            var);
                    VariantClear(&var);
                }
            }
         
            // Put description.
            var.vt = VT_BSTR;
            var.bstrVal = SysAllocString(szDescription);
            hr = (*ppNewClass)->Put(CComBSTR("description"), 
                                    var);
            VariantClear(&var);
         
         
            // Put adminDisplayName.
            // If NULL, set it to the same string as cn.
            var.vt = VT_BSTR;
            if (!szAdminDisplayName)
            {
                var.bstrVal = SysAllocString(szClassName);
            }
            else
            {
                var.bstrVal = SysAllocString(szAdminDisplayName);
            }
            hr = (*ppNewClass)->Put(CComBSTR("adminDisplayName"), 
                                var);
            VariantClear(&var);
         
            // End of properties to set.
            break;
        }
    }

    if (pDisp)
    {
        pDisp->Release();
    }
     
    if (FAILED(hr))
    {
        // Cleanup, if failed.
        if (*ppNewClass)
        {
            (*ppNewClass)->Release();
            (*ppNewClass) = NULL;
        }
    }
     
    return hr;
}

////////////////////////////////////////////////////////// 
// BytesToVariantArray
// Packs an octet string into a variant array.
////////////////////////////////////////////////////////// 
HRESULT BytesToVariantArray(
    PBYTE pValue, // Pointer to bytes to put in a 
                  // variant array.
    ULONG cValueElements,// Size of pValue in bytes.
    VARIANT *pVariant // Return variant that contains 
                      // octet string (VT_UI1|VT_ARRAY).
    )
{
    HRESULT hr = E_FAIL;
    SAFEARRAY *pArrayVal = NULL;
    SAFEARRAYBOUND arrayBound;
    CHAR HUGEP *pArray = NULL;
 
    // Set bound for array.
    arrayBound.lLbound = 0;
    arrayBound.cElements = cValueElements;
 
    // Create the safe array for the octet string. 
    // unsigned char elements;single dimension;aBound size.
    pArrayVal = SafeArrayCreate(VT_UI1, 1, &arrayBound);
 
    if (!(pArrayVal == NULL) )
    {
        hr = SafeArrayAccessData(pArrayVal, 
                                (void HUGEP * FAR *) &pArray );
        if (SUCCEEDED(hr))
        {
            // Copy bytes to the safe array.
            memcpy( pArray, pValue, arrayBound.cElements );
            SafeArrayUnaccessData( pArrayVal );
            // Set type to array of unsigned char.
            V_VT(pVariant) = VT_ARRAY | VT_UI1;
            // Assign the safe array to the array member.
            V_ARRAY(pVariant) = pArrayVal;
            hr = S_OK;
        }
        else
        {
            // Cleanup if the array cannot be accessed.
            if ( pArrayVal )
            {
                SafeArrayDestroy( pArrayVal );
            }
        }
    }
    else
    {
        hr = E_OUTOFMEMORY;
    }
 
    return hr;
}