Platform SDK: Active Directory, ADSI, and Directory Services

Example Code for Creating a Group on a Member Server or Windows NT Workstation/Windows 2000 Professional

[C++]

The following code fragment creates a group on a member server or a computer running Windows NT Workstation/Windows 2000 Professional:

void wmain( int argc, wchar_t *argv[ ])
{
    HRESULT hr;
    IDirectoryObject * pDirObjectRoot           = NULL;
    IDirectoryObject * pDirObjectSampleLocal    = NULL;
    BOOL               bMixedMode;
    IADsContainer    * pIADsCont                = NULL;
 
    // Initialize COM
    CoInitialize(0);
    IUnknown * pUnk;
 
    // Since we are using the WinNT provider, bind to the specific computer name,
    // put your computer name in the string below
    #ifdef USE_OPEN_OBJECT
        hr = ADsOpenObject(L"WinNT://MyComputerName,computer", ADS_OPENOBJECT_USERNAME, ADS_OPENOBJECT_PASSWORD , 
                                                           ADS_SECURE_AUTHENTICATION,IID_IADsContainer, (void**) &pIADsCont);
    #else
        hr = ADsGetObject(L"WinNT:// MyComputerName,computer", IID_IADsContainer, (void**) &pIADsCont);
    #endif
 
    if (SUCCEEDED(hr))
    {
        IDispatch * pIDispatch = NULL;
 
        BSTR bsGroup = SysAllocString(L"group");
        BSTR bsName = SysAllocString(L"ThisIsAGroup");
 
        hr = pIADsCont->Create(bsGroup,bsName , &pIDispatch);
 
        if (SUCCEEDED(hr))
        {
            puts(QueryAllInterfaces(pIDispatch));
 
            IADsGroup   * pGroup = NULL;
 
            hr = pIDispatch->QueryInterface(IID_IADsGroup,(void**)&pGroup);
 
            if (SUCCEEDED(hr))
            {
                hr = pGroup->SetInfo();
 
                if(SUCCEEDED(hr))
                {
                    // NOW- add some users (fill these in with Valid Users)
                    BSTR bsUserOne = SysAllocString(L"WinNT://MyComputerName /Administrator");
                    BSTR bsUserTwo = SysAllocString(L"WinNT://MyComputerName /jcooper");
                    hr = pGroup->Add(bsUserOne);
                    if (SUCCEEDED(hr))
                    {
                        hr = pGroup->Add(bsUserTwo);
                        if (SUCCEEDED(hr))
                        {
                            IADsMembers *   pADsMembers       = NULL;     // Ptr to Members of the IADsGroup
                            BOOL            fContinue         = TRUE;     // Looping Variable
                            IEnumVARIANT *  pEnumVariant      = NULL;     // Ptr to the Enum variant
                            IUnknown *      pUnknown          = NULL;     // IUnknown for getting the ENUM initially
                            VARIANT         VariantArray[FETCH_NUM];      // Variant array for temp holding returned data
                            ULONG           ulElementsFetched = NULL;     // Number of elements fetched
 
                            // Get a interface pointer to the IADsCollection of members
                            hr = pGroup->Members(&pADsMembers);
                            if (SUCCEEDED(hr))
                            {
                                // Ask the IADsCollection of members for a new ENUM Interface
                                // Note the enum comes back as an IUnknown *
                                hr = pADsMembers->get__NewEnum(&pUnknown);
                                if (SUCCEEDED(hr))
                                {
                                    // QI the IUnknown * for a IEnumVARIANT interface
                                    hr = pUnknown->QueryInterface(IID_IEnumVARIANT, (void **)&pEnumVariant);
                                    if (SUCCEEDED(hr))
                                    {
                                        // While have not hit errors or end of data....
                                        while (fContinue) 
                                        {
                                           ulElementsFetched = 0;
                                            // Get a "batch" number of group members- number of rows specified by FETCH_NUM
                                            hr = ADsEnumerateNext(pEnumVariant, FETCH_NUM, VariantArray, &ulElementsFetched);
 
                                            if (ulElementsFetched )//SUCCEEDED(hr) && hr != S_FALSE)
                                            {
                                                // Loop through the current batch- printing the path 
                                                // for each member
                                                for (ULONG i = 0; i < ulElementsFetched; i++ ) 
                                                {
                                                    IDispatch * pDispatch         = NULL; // ptr for holding dispath of element
                                                    IADs      * pIADsGroupMember  = NULL; // IADs ptr to group member
                                                    BSTR        bstrPath          = NULL; // Holds path of object
 
                                                    // Get the dispatch ptr for the variant
                                                    pDispatch = VariantArray[i].pdispVal;
                                                    assert(HAS_BIT_STYLE(VariantArray[i].vt,VT_DISPATCH));
 
                                                    // Get the IADs interface for the "member" of this group
                                                    hr = pDispatch->QueryInterface(IID_IADs,
                                                                                   (VOID **) &pIADsGroupMember) ;
                                                    if (SUCCEEDED(hr))
                                                    {
                                                        // Get the ADsPath property for this member
                                                        hr = pIADsGroupMember->get_ADsPath(&bstrPath) ;
                                                        if (SUCCEEDED(hr))
                                                        {
                                                            // Print the ADsPath of the group member
                                                            printf("\tMember Object: %ws\n", bstrPath);
                                                            SysFreeString(bstrPath);
                                                        }
                                                        pIADsGroupMember->Release();
                                                        pIADsGroupMember   = NULL;
                                                    }
                                                 }
                                                // Clear the variant array
                                                memset(VariantArray, 0, sizeof(VARIANT)*FETCH_NUM);
                                            }
                                            else
                                                fContinue = FALSE;
                                        }
                                        pEnumVariant->Release();
                                        pEnumVariant = NULL;
                                    }
                                    pUnknown->Release();
                                    pUnknown = NULL;
                                }
                                pADsMembers ->Release();
                                pADsMembers  = NULL;
                            }
                        }
                    }
                    SysFreeString(bsUserOne);
                    SysFreeString(bsUserTwo);
                    bsUserOne = NULL;
                    bsUserTwo = NULL;
                }
                pGroup->Release();
                pGroup = NULL;
            }
 
            pIDispatch->Release();
            pIDispatch = NULL;
        }
        pIADsCont->Release();
        pIADsCont = NULL;
    }
    CoUninitialize();
}
[Visual Basic]

The following code creates a group on a member server or a computer running Windows NT Workstation/Windows 2000 Professional:

On Error Resume Next
 
Dim IADsCont As IADsContainer
Dim oIADsGroup As IADsGroup
Dim ListIADsMembers As IADsMembers
Dim Member As IADs
 
sComputer = InputBox("This script creates a group on a member server or workstation." & vbCrLf & vbCrLf & "Specify the computer name:")
sGroup = InputBox("Specify the group name:")
 
If sComputer = "" Then
  MsgBox "No computer name was specified. You must specify a computer name."
  Exit Sub
End If
If sGroup = "" Then
  MsgBox "No group name was specified. You must specify a group name."
  Exit Sub
End If
 
'''''''''''''''''''''''''''''''''''''''
'Bind to the computer
'''''''''''''''''''''''''''''''''''''''
Set IADsCont = GetObject("WinNT://" & sComputer & ",computer")
If (Err.Number <> 0) Then
   BailOnFailure Err.Number, "on GetObject method"
End If
 
'''''''''''''''''''''''''''''''''''''''
'Create the group
'''''''''''''''''''''''''''''''''''''''
'Only Local groups can be created on member servers and Windows NT Workstation/Windows 2000 Professional.
Set oIADsGroup = IADsCont.Create("localGroup", sGroup)
If (Err.Number <> 0) Then
   BailOnFailure Err.Number, "on IADsContainer::Create method"
End If
 
'''''''''''''''''''''''''''''''''''''''
'Write the group to the computer's security database.
'''''''''''''''''''''''''''''''''''''''
oIADsGroup.SetInfo
 
'''''''''''''''''''''''''''''''''''''''
'Read the group that was just created
'and display its name and its members.
'''''''''''''''''''''''''''''''''''''''
strText = "The group " & oIADsGroup.Name & " was created on computer " & sComputer & "."
If (Err.Number <> 0) Then
    BailOnFailure Err.Number, "on IADsGroup::Name method"
End If
Set ListIADsMembers = oIADsGroup.members
If (Err.Number <> 0) Then
    BailOnFailure Err.Number, "on IADsGroup::members method"
End If
'Get the enumerate the members of the group from the members object
cmember = 0
For Each Member In ListIADsMembers
  If cmember = 0 Then
    strText = strText & vbCrLf & "       " & "Members:"
  End If
  strText = strText & vbCrLf & "       " & Member.Name & " (" & Member.Class & ")"
  cmember = cmember + 1
Next
If cmember = 0 Then
   strText = strText & vbCrLf & "       " & "No members"
End If
 
Call show_groups(strText, sComputer)
 
 
'''''''''''''''''''''''''''''''''''''''
'Display subroutines
'''''''''''''''''''''''''''''''''''''''
Sub show_groups(strText, strName)
    MsgBox strText, vbInformation, "Create group on " & strName
End Sub