Example Code for Creating a User

This topic includes code examples that create a user in a domain controlled by Active Directory Domain Services.

Const ADS_UF_SCRIPT = &H1
Const ADS_UF_ACCOUNTDISABLE = &H2
Const ADS_UF_HOMEDIR_REQUIRED = &H8
Const ADS_UF_LOCKOUT = &H10
Const ADS_UF_PASSWD_NOTREQD = &H20
Const ADS_UF_PASSWD_CANT_CHANGE = &H40
Const ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED = &H80
Const ADS_UF_TEMP_DUPLICATE_ACCOUNT = &H100
Const ADS_UF_NORMAL_ACCOUNT = &H200
Const ADS_UF_INTERDOMAIN_TRUST_ACCOUNT = &H800
Const ADS_UF_WORKSTATION_TRUST_ACCOUNT = &H1000
Const ADS_UF_SERVER_TRUST_ACCOUNT = &H2000
Const ADS_UF_DONT_EXPIRE_PASSWD = &H10000
Const ADS_UF_MNS_LOGON_ACCOUNT = &H20000
Const ADS_UF_SMARTCARD_REQUIRED = &H40000
Const ADS_UF_TRUSTED_FOR_DELEGATION = &H80000
Const ADS_UF_NOT_DELEGATED = &H100000
Const ADS_UF_USE_DES_KEY_ONLY = &H200000
Const ADS_UF_DONT_REQUIRE_PREAUTH = &H400000
Const ADS_UF_PASSWORD_EXPIRED = &H800000
Const ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = &H1000000

Public Sub CreateUser(strName As String, 
                      strSAMAccountName As String,
                      strInitialPassword As String)
    Dim objRootDSE As IADs
    Dim objUsers As IADsContainer
    Dim objNewUser As IADsUser

    On Error Resume Next
    
    ' Bind to the rootDSE object.
    Set objRootDSE = GetObject("LDAP://rootDSE")
    If (Err.Number <> 0) Then
        Exit Sub
    End If
    
    ' Bind to the Users folder in the domain.
    Set objUsers = GetObject("LDAP://CN=Users," & 
                             objRootDSE.Get("defaultNamingContext"))
    If (Err.Number <> 0) Then
        Exit Sub
    End If
    
    ' Create the user object.
    Set objNewUser = objUsers.Create("user", "CN=" + strName)
    If (Err.Number <> 0) Then
        Exit Sub
    End If
    
    ' Set the sAMAccountName property.
    objNewUser.Put "sAMAccountName", strSAMAccountName
    If (Err.Number <> 0) Then
        Exit Sub
    End If
    
    ' Commit the new user.
    objNewUser.SetInfo
    If (Err.Number <> 0) Then
        Exit Sub
    End If

    ' Set the initial password. This must be performed after
    ' SetInfo is called because the user object must
    ' already exist on the server.
    objNewUser.SetPassword strInitialPassword
    If (Err.Number <> 0) Then
        Exit Sub
    End If
    
    ' Set the pwdLastSet property to zero, which forces the
    ' user to change their password at next log on.
    objNewUser.Put "pwdLastSet", 0
    If (Err.Number <> 0) Then
        Exit Sub
    End If
    
    ' To enable the user account, remove the
    ' ADS_UF_ACCOUNTDISABLE flag from the userAccountControl
    ' property. Also, remove the ADS_UF_PASSWD_NOTREQD and
    ' ADS_UF_DONT_EXPIRE_PASSWD flags from the
    ' userAccountControl property.
    userActCtrl = objNewUser.Get("userAccountControl")
    userActCtrl = userActCtrl And Not (ADS_UF_ACCOUNTDISABLE + 
                                       ADS_UF_PASSWD_NOTREQD + 
                                       ADS_UF_DONT_EXPIRE_PASSWD)
    objNewUser.Put "userAccountControl", userActCtrl
    If (Err.Number <> 0) Then
        Exit Sub
    End If
    
    ' Commit the updated properties.
    objNewUser.SetInfo
End Sub
//*******************************************************************
//
//  CreateUserFromADs()
//
//*******************************************************************

HRESULT CreateUserFromADs(LPCWSTR pwszContainerDN,
                          LPCWSTR pwszName, 
                          LPCWSTR pwszSAMAccountName, 
                          LPCWSTR pwszInitialPassword)
{
    HRESULT hr;

    //  Build the DN of the container.
    CComBSTR sbstrADsPath = "LDAP://";
    sbstrADsPath += pwszContainerDN;

    IADsContainer *pUsers = NULL;

    // Bind to the container.
    hr = ADsGetObject(sbstrADsPath, 
                      IID_IADsContainer, 
                      (LPVOID*)&pUsers);
    if(SUCCEEDED(hr))
    {
        IDispatch *pDisp = NULL;
        
        CComBSTR sbstrName = "CN=";
        sbstrName += pwszName;
        
        // Create the new object in the User folder.
        hr = pUsers->Create(CComBSTR("user"), sbstrName, &pDisp);

        if(SUCCEEDED(hr))
        { 
            IADsUser *padsUser = NULL;

            // Get the IADs interface.
            hr = pDisp->QueryInterface(IID_IADsUser,
                                       (void**) &padsUser);

            if(SUCCEEDED(hr))
            { 
                CComBSTR sbstrProp;
                /*
                The sAMAccountName property is required on operating system 
                versions prior to Windows Server 2003.
                The Windows Server 2003 operating system will create a 
                sAMAccountName value if one is not specified.
                */
                CComVariant svar;
                svar = pwszSAMAccountName;
                sbstrProp = "sAMAccountName";
                hr = padsUser->Put(sbstrProp, svar);

                /*
                Commit the new user to persistent memory. 
                The user does not exist until this is called.
                */
                hr = padsUser->SetInfo();

                /*
                Set the initial password. This must be done after 
                SetInfo is called because the user object must 
                already exist on the server.
                */
                hr = padsUser->SetPassword(CComBSTR(pwszInitialPassword));

                /*
                Set the pwdLastSet property to zero, which forces the 
                user to change the password the next time they log on.
                */
                sbstrProp = "pwdLastSet";
                svar = 0;
                hr = padsUser->Put(sbstrProp, svar);

                /*
                Enable the user account by removing the 
                ADS_UF_ACCOUNTDISABLE flag from the userAccountControl 
                property. Also, remove the ADS_UF_PASSWD_NOTREQD and 
                ADS_UF_DONT_EXPIRE_PASSWD flags from the 
                userAccountControl property.
                */
                svar.Clear();
                sbstrProp = "userAccountControl";
                hr = padsUser->Get(sbstrProp, &svar);
                if(SUCCEEDED(hr))
                {
                    svar = svar.lVal & ~(ADS_UF_ACCOUNTDISABLE | 
                        ADS_UF_PASSWD_NOTREQD | 
                        ADS_UF_DONT_EXPIRE_PASSWD);

                    hr = padsUser->Put(sbstrProp, svar);
                    hr = padsUser->SetInfo();
                }
                
                hr = padsUser->put_AccountDisabled(VARIANT_FALSE);
                hr = padsUser->SetInfo();

                padsUser->Release();
            }

            pDisp->Release();
        }

        pUsers->Release();
    }

    return hr;
}
//*******************************************************************
//
//  CreateUserFromDirObject()
//
//*******************************************************************

HRESULT CreateUserFromDirObject(LPCWSTR pwszContainerDN,
                                LPCWSTR pwszName, 
                                LPCWSTR pwszSAMAccountName, 
                                LPCWSTR pwszInitialPassword)
{
    HRESULT hr;

    //  Build the DN of the container.
    CComBSTR sbstrADsPath = "LDAP://";
    sbstrADsPath += pwszContainerDN;

    IDirectoryObject *pdoUsers = NULL;

    // Bind to the container.
    hr = ADsGetObject(sbstrADsPath, 
                      IID_IDirectoryObject,
                      (LPVOID*)&pdoUsers);
    if(SUCCEEDED(hr))
    {
        IDispatch *pDisp;
        ADS_ATTR_INFO rgAttrInfo[3];
        
        // Setup the objectClass property.
        ADSVALUE classValue;
        classValue.dwType = ADSTYPE_CASE_IGNORE_STRING;
        classValue.CaseIgnoreString = L"User";
        rgAttrInfo[0].pszAttrName = L"objectClass";
        rgAttrInfo[0].dwControlCode = ADS_ATTR_UPDATE;
        rgAttrInfo[0].dwADsType = ADSTYPE_CASE_IGNORE_STRING;
        rgAttrInfo[0].pADsValues = &classValue;
        rgAttrInfo[0].dwNumValues = 1;

        /*
        The sAMAccountName property is required on operating system versions 
        prior to Windows Server 2003. 
        The Windows Server 2003 operating system will create a 
        sAMAccountName value if one is not specified.
        */
        ADSVALUE sAMValue;
        sAMValue.dwType = ADSTYPE_CASE_IGNORE_STRING;
        sAMValue.CaseIgnoreString = 
           (ADS_CASE_IGNORE_STRING)pwszSAMAccountName;
        rgAttrInfo[1].pszAttrName = L"sAMAccountName";
        rgAttrInfo[1].dwControlCode = ADS_ATTR_UPDATE;
        rgAttrInfo[1].dwADsType = ADSTYPE_CASE_IGNORE_STRING;
        rgAttrInfo[1].pADsValues = &sAMValue;
        rgAttrInfo[1].dwNumValues = 1;

        /*
        Set the initial userAccountControl attribute so that
        the user is created as an enabled account and a
        password is required.
        */
        ADSVALUE userAccountControlValue;
        userAccountControlValue.dwType = ADSTYPE_INTEGER;
        userAccountControlValue.Integer = ADS_UF_NORMAL_ACCOUNT;
        rgAttrInfo[2].pszAttrName = L"userAccountControl";
        rgAttrInfo[2].dwControlCode = ADS_ATTR_UPDATE;
        rgAttrInfo[2].dwADsType = ADSTYPE_INTEGER;
        rgAttrInfo[2].pADsValues = &userAccountControlValue;
        rgAttrInfo[2].dwNumValues = 1;

        CComBSTR sbstrName = "CN=";
        sbstrName += pwszName;

        /*
        Create the object in the Users container with the specified 
        property values.
        */
        hr = pdoUsers->CreateDSObject(
              sbstrName,  
              rgAttrInfo, 
              sizeof(rgAttrInfo)/sizeof(ADS_ATTR_INFO), 
              &pDisp
             );

        if(SUCCEEDED(hr))
        {
            IDirectoryObject *pdoNewUser;

            hr = pDisp->QueryInterface(IID_IDirectoryObject, 
                                       (LPVOID*)&pdoNewUser);
            if(SUCCEEDED(hr))
            {
                ADSVALUE adsValue;
                DWORD dw;
                
                /*
                Set the initial password.
                */
                IADsUser *padsUser;
                hr = pdoNewUser->QueryInterface(IID_IADsUser, 
                                                (LPVOID*)&padsUser);
                if(SUCCEEDED(hr))
                {
                  hr = 
                   padsUser->SetPassword(CComBSTR(pwszInitialPassword));
                  padsUser->Release();
                }
                
                /*
                Set the pwdLastSet property to zero, which forces the 
                user to change their password at next log on.
                */
                adsValue.dwType = ADSTYPE_LARGE_INTEGER;
                adsValue.LargeInteger.LowPart = 0;
                adsValue.LargeInteger.HighPart = 0;
                rgAttrInfo[0].pszAttrName = L"pwdLastSet";
                rgAttrInfo[0].dwControlCode = ADS_ATTR_UPDATE;
                rgAttrInfo[0].dwADsType = ADSTYPE_LARGE_INTEGER;
                rgAttrInfo[0].pADsValues = &adsValue;
                rgAttrInfo[0].dwNumValues = 1;
                hr = pdoNewUser->SetObjectAttributes(rgAttrInfo,
                                                     1,
                                                     &dw);

                pdoNewUser->Release();
            }
            
            pDisp->Release();
        }
        
        pdoUsers->Release();
    }

    return hr;
}