Jump to content

Display a Locked Account on AD (W2k) LDAP 3.0


rikho
 Share

Recommended Posts

Hi all

I read all -> http://www.autoitscript.com/forum/index.ph...mp;#entry221862

I got ADFUNCTION.AU3 -> I know that islockedaccount is bugged.

I just want to display the lockoutime value in an msgbox

ADSI edit show me that the propertie lockoutTime is a Optionnal value in INTEGER8 syntax...

i think i'm not in the good direction

Is some one can try to help me ?

My code bellow :

#include <array.au3>
#include <adfunctions.au3>

$sUser = InputBox("Username", "Enter the username:")
$samname = ($sUser)
$strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $samname & ");ADsPath;subtree"
$objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the object
$ldap_entry = $objRecordSet.fields (0).value
$oObject = ObjGet($ldap_entry); Retrieve the COM Object for the object
$result = $oObject.LockoutTime
$oObject.PurgePropertyList

If $result = "" Then
    Exit
Else
    MsgBox(0, '', $result)
EndIf

My include adfunctions.au3

; Active Directory Function Library. Include this to allow access to Active Directory Functions

; Author : Jonthan Clelland
; Email : jclelland@statestreet.com
; Version : 3.0

; _ADDoError  : Error event handler for COM errors. This is global so will pick up errors from your program if you include this library
; _ADCreateUser : Creates a user in a particular OU
; _ADCreateGroup : Creates a group in a particular OU
; _ADAddUserToGroup : Adds a user to a group (if the user is not already a member of the group)
; _ADRemoveUserFromGroup : Removes a user from a group
; _ADObjectExists : Returns 1 if the given object (SamAccountName) exists in the local AD Tree
; _ADModifyAttribute : Sets the attribute of the given object to the value specified
; _ADIsMemberOf : Returns 1 if the user is a member of the group
; _ADGetUserGroups : Returns an array (byreference) containing the groups that the user is a member of
; _ADRecursiveGetMemberOf : Returns a recursed list of group membership for a group or user
; _ADGetGroupMembers : Returns an array of the group members
; _ADGetGroupMemberOf : Returns a simple list of group membership for a group
; _ADHasFullRights : Returns 1 if the given user has full rights over the given group
; _ADGroupMailEnable : Mail enables a group
; _ADUserCreateMailbox : Creates a mailbox for a user
; _ADUserDeleteMailbox : Deletes the mailbox for a user
; _ADGetObjectsInOU : Returns a filtered list of objects and attributes in a given OU
; _ADDNToSamAccountName : Returns the SamAccountName of an FQDN
; _ADSamAccountNameToFQDN : Returns a FQDN from a SamAccountName
; _ADDNToDisplayName :Returns the Display Name of an FQDN
; _ADCreateObject : Creates an object of a specified type
; _ADCreateComputer : Creates a computer and assigns permissions for a user/group to add the computer
; _ADDeleteObject : Deletes an object
; _ADGetObjectClass : Returns the class of an object
; _ADGetObjectClassFromFQDN : Returns the class of an object from it's FQDN
; _ADGetObjectAttribute : Returns a (single-value) attribute of an object
; _ADListDomainControllers : Returns a list of Domain Controllers for the current domain
; _ADOUObjectNames : Returns display names of filtered objects within an OU
; _ADGroupManagerCanModify : Returns 1 if the manager of the group can modify the member list, 0 if not, -1 if there is no manager assigned
; _ADAddAccountToMailboxRights : Adds useraccount to mailbox with full rights and send as permissions.

; NOTES : Please use the following command to store the local user's groups for the function 'HasFullRights'. This is to allow cross-domain
; permission checks. $loggedonusergroups is a global variable declared in the 'Define AD Constants' region. If you are using this command
; in this library, move the command below the declaration of the variable and remove the comment charcater.

; _ADRecursiveGetMemberOf ($loggedonusergroups, _ADSamAccountNameToFQDN (@UserName))

; include array functions (we use _arraysearch in some functions)
#include <Array.au3>

#Region; Define AD Constants

Global Const $ADS_GROUP_TYPE_GLOBAL_GROUP = 0x2
Global Const $ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP = 0x4
Global Const $ADS_GROUP_TYPE_UNIVERSAL_GROUP = 0x8
Global Const $ADS_GROUP_TYPE_SECURITY_ENABLED = 0x80000000
Global Const $ADS_GROUP_TYPE_GLOBAL_SECURITY = BitOR($ADS_GROUP_TYPE_GLOBAL_GROUP, $ADS_GROUP_TYPE_SECURITY_ENABLED)
Global Const $ADS_GROUP_TYPE_UNIVERSAL_SECURITY = BitOR($ADS_GROUP_TYPE_UNIVERSAL_GROUP, $ADS_GROUP_TYPE_SECURITY_ENABLED)
Global Const $ADS_GROUP_TYPE_DOMAIN_LOCAL_SECURITY = BitOR($ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP, $ADS_GROUP_TYPE_SECURITY_ENABLED)

Global Const $ADS_UF_PASSWD_NOTREQD = 0x0020
Global Const $ADS_UF_WORKSTATION_TRUST_ACCOUNT = 0x1000
Global Const $ADS_ACETYPE_ACCESS_ALLOWED = 0x0
Global Const $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT = 0x5
Global Const $ADS_FLAG_OBJECT_TYPE_PRESENT = 0x1
Global Const $ADS_RIGHT_GENERIC_READ = 0x80000000
Global Const $ADS_RIGHT_DS_SELF = 0x8
Global Const $ADS_RIGHT_DS_WRITE_PROP = 0x20
Global Const $ADS_RIGHT_DS_CONTROL_ACCESS = 0x100
Global Const $ADS_UF_ACCOUNTDISABLE = 2
Global Const $ADS_OPTION_SECURITY_MASK = 3
Global Const $ADS_SECURITY_INFO_DACL = 4

Global Const $ALLOWED_TO_AUTHENTICATE = "{68B1D179-0D15-4d4f-AB71-46152E79A7BC}"
Global Const $RECEIVE_AS = "{AB721A56-1E2f-11D0-9819-00AA0040529B}"
Global Const $SEND_AS = "{AB721A54-1E2f-11D0-9819-00AA0040529B}"
Global Const $USER_CHANGE_PASSWORD = "{AB721A53-1E2f-11D0-9819-00AA0040529b}"
Global Const $USER_FORCE_CHANGE_PASSWORD = "{00299570-246D-11D0-A768-00AA006E0529}"
Global Const $USER_ACCOUNT_RESTRICTIONS = "{4C164200-20C0-11D0-A768-00AA006E0529}"
Global Const $VALIDATED_DNS_HOST_NAME = "{72E39547-7B18-11D1-ADEF-00C04FD8D5CD}"
Global Const $VALIDATED_SPN = "{F3A64788-5306-11D1-A9C5-0000F80367C1}"
Const $Member_SchemaIDGuid = "{BF9679C0-0DE6-11D0-A285-00AA003049E2}"

Global $objConnection = ObjCreate("ADODB.Connection"); Create COM object to AD
$objConnection.ConnectionString = "Provider=ADsDSOObject"
$objConnection.Open("Active Directory Provider"); Open connection to AD


Global $objRootDSE = ObjGet("LDAP://RootDSE")
Global $strDNSDomain = $objRootDSE.Get("defaultNamingContext"); Retrieve the current AD domain name
Global $strHostServer = $objRootDSE.Get("dnsHostName"); Retrieve the name of the connected DC
Global $strConfiguration = $objRootDSE.Get("ConfigurationNamingContext"); Retrieve the Configuration naming context

Global $loggedonusergroups; populate this with the logged on user groups in your own app

#EndRegion  

$oMyError = ObjEvent("AutoIt.Error", "_ADDoError"); Install a custom error handler

;  MyErrFunc
Func _ADDoError()
    $HexNumber = Hex($oMyError.number, 8)
    
    If $HexNumber = 80020009 Then
        SetError(3)
        Return
    EndIf
    
    If $HexNumber = "8007203A" Then
        SetError(4)
        Return
    EndIf
    
    MsgBox(262144, "", "We intercepted a COM Error !" & @CRLF & _
            "Number is: " & $HexNumber & @CRLF & _
            "Windescription is: " & $oMyError.windescription & @CRLF & _
            "Script Line number is: " & $oMyError.scriptline)
    
    Select
        Case $oMyError.windescription = "Access is denied."
            $objConnection.Close("Active Directory Provider")
            $objConnection.Open("Active Directory Provider")
            SetError(2)
        Case 1
            SetError(1)
    EndSelect
    
EndFunc;==>_ADDoError

; _ADCreateUser
; $userou = OU to create the group in. Form is "sampleou=ou, sampleparent=ou, sampledomain1=dc, sampledomain2=dc, sampledomain3=dc"
; $user = Username, form is SamAccountName without leading 'CN='
; $fname = First Name
; $lname = Last Name
; $description = optional - Description

Func _ADCreateUser($userou, $user, $fname, $lname, $description = "User")
    If _ADObjectExists($user) Then Return 0

    $ObjOU = ObjGet("LDAP://" & $strHostServer & "/" & $userou)
    If $fname = "" Then
        $cnname = "CN=" & $lname
    Else
        $cnname = "CN=" & $lname & "\, " & $fname
    EndIf
    $ObjUser = $ObjOU.Create("User", $cnname)
    
    $ObjUser.Put("sAMAccountName", $user)
    $ObjUser.Put("description", $description)

    $ObjUser.SetInfo
    Return 1
EndFunc;==>_ADCreateUser

; _ADCreateGroup
; $gruopou = OU to create the group in. Form is "sampleou=ou, sampleparent=ou, sampledomain1=dc, sampledomain2=dc, sampledomain3=dc"
; $group = groupname, form is SamAccountName without leading 'CN='
; $type = Group type. Defaults to Global Security. See the global constands for other types. NOTE Global security must be 'BitOr'ed with a scope.

Func _ADCreateGroup($groupou, $group, $type = -2147483646)
    If _ADObjectExists($group) Then Return 0
    If StringLeft($group, 3) <> "CN=" Then
        $groupcn = "CN=" & $group
    Else
        $groupcn = $group
    EndIf
    $groupcn = StringReplace($groupcn, "#", "\#")
    $groupcn = StringReplace($groupcn, ",", "\,")
    $groupcn = StringReplace($groupcn, "/", "\/")
    
    $ObjOU = ObjGet("LDAP://" & $strHostServer & "/" & $groupou)
    $ObjGroup = $ObjOU.Create("Group", $groupcn)
    
    $groupsam = StringReplace($group, ",", " ")
    $groupsam = StringReplace($groupsam, "#", " ")
    $groupsam = StringReplace($groupsam, "/", " ")
    $ObjGroup.Put("sAMAccountName", $groupsam)
    $ObjGroup.Put("grouptype", $type)
    
    $ObjGroup.SetInfo
    
    Return 1
EndFunc;==>_ADCreateGroup

; _ADAddUserToGroup
; Takes the group (SamAccountName without leading 'CN=') and the user (SamAccountName without leading 'CN=')
; Adds the user to the group
; Returns 0 if the user is already a member of the group,
; Returns 1 if the user was added to the group
; Returns -1 if there was an error

Func _ADAddUserToGroup($group, $user)
    If _ADIsMemberOf($group, $user) Then Return 0
    $oUsr = ObjGet("LDAP://" & $strHostServer & "/" & $user); Retrieve the COM Object for the user
    $oGroup = ObjGet("LDAP://" & $strHostServer & "/" & $group); Retrieve the COM Object for the group
    
    $oGroup.Add($oUsr.AdsPath)
    $oGroup.SetInfo
    $oGroup = 0
    $oUser = 0
    Return _ADIsMemberOf($group, $user)
EndFunc;==>_ADAddUserToGroup

; _ADRemoveUserFromGroup
; Takes the group (SamAccountName without leading 'CN=') and the user (SamAccountName without leading 'CN=')
; Removes the user from the group (if the user is a member of the group)
; Returns 0 if the user isn't a member of the group, 1 if the user was removed from the group
; Returns -1 if the removal failed.

Func _ADRemoveUserFromGroup($group, $user)
    If _ADIsMemberOf($group, $user) = 0 Then Return 0

    $oUsr = ObjGet("LDAP://" & $strHostServer & "/" & $user); Retrieve the COM Object for the user

    $oGroup = ObjGet("LDAP://" & $strHostServer & "/" & $group); Retrieve the COM Object for the group
    
    $oGroup.Remove($oUsr.AdsPath)
    $oGroup.SetInfo
    
    $oGroup = 0
    $oUser = 0
    
    If _ADIsMemberOf($group, $user) Then
        Return -1
    Else
        Return 1
    EndIf
    
EndFunc;==>_ADRemoveUserFromGroup

; _ADObjectExists
; Takes an object name (SamAccountName without leading 'CN=')
; Returns 1 if the object exists in the tree, 0 otherwise

Func _ADObjectExists($object)
    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $object & ");ADsPath;subtree"
    
    
    $objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the group, if it exists
    
    If $objRecordSet.RecordCount = 1 Then
        $objRecordSet = 0
        Return 1
    Else
        $objRecordSet = 0
        Return 0
    EndIf
EndFunc;==>_ADObjectExists

; _ADModifyAttribute
; $object = Object to modify (samAccountName)
; $attribute = Attribute to modify
; $value = value to set attribute to, use a blank string "" to delete an attribute

Func _ADModifyAttribute($object, $attribute, $value)
    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $object & ");ADsPath;subtree"
    $objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the object
    
    $ldap_entry = $objRecordSet.fields(0).value
    $oObject = ObjGet($ldap_entry); Retrieve the COM Object for the object
    
    $oObject.GetInfo
    
    If $value = "" Then
        $oObject.PutEx(1, $attribute, 0)
    Else
        $oObject.Put($attribute, $value)
    EndIf

    $oObject.SetInfo
    $oObject.PurgePropertyList
    
    $oObject = 0
    
    Return 1
EndFunc;==>_ADModifyAttribute

; _ADIsMemberOf
; Takes samAccountNames for a group and a user
; Returns 1 if the the user is a member of the group, 0 otherwise

Func _ADIsMemberOf($group, $user)
    $ObjGroup = ObjGet("LDAP://" & $strHostServer & "/" & $group)
    $ismember = $ObjGroup.IsMember("LDAP://" & $strHostServer & "/" & $user)
    $ObjGroup = 0
    Return -$ismember
EndFunc;==>_ADIsMemberOf

; _ADGetUserGroups
; the currently logged on user is a member of. Returns an array of Full DNs of the Group names that the user is immediately a member of
; with element 0 containing the number of groups.
; $user - optional -- SamAccountName of a user, defaults to locally logged on user

Func _ADGetUserGroups(ByRef $usergroups, $user = @UserName)
    Local $oUsr
    
    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $user & ");ADsPath;subtree"
    $objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the logged on user
    $ldap_entry = $objRecordSet.fields(0).value
    $oUsr = ObjGet($ldap_entry); Retrieve the COM Object for the logged on user
    
    $usergroups = $oUsr.GetEx("memberof")
    
    $oUsr = 0
    
    $count = UBound($usergroups)
    _ArrayInsert($usergroups, 0, $count)
EndFunc;==>_ADGetUserGroups

; _ADRecursiveGetMemberOf
; Takes a Full DN of a group or user and returns a recursively searched list of groups the object is a member of to the array
; This will traverse through groups that the object is immediately a member of and check their group membership as well.
; The return values are full DNs. For groups that are inherited, the return is the DN of the group, and the DN of the first group
; it was inherited from, seperated by '|'.
Func _ADRecursiveGetMemberOf(ByRef $memberof, $fqdn)
    Local $objItem, $tempmemberof, $i = 0
    
    $objItem = ObjGet("LDAP://" & $strHostServer & "/" & $fqdn); Retrieve the COM Object for the logged on user
    
    $memberof = $objItem.GetEx("memberof")
    
    $objItem = 0
    
    If $memberof = 0 Then
        Dim $memberof[1] = [0]
        Return 0
    EndIf
    
    Do
        If StringInStr($memberof[$i], "|") Then
            $currgroup = StringLeft($memberof[$i], StringInStr($memberof[$i], "|") - 1)
        Else
            $currgroup = $memberof[$i]
        EndIf
        $currgroup = StringReplace($currgroup, "/", "\/")
        _ADGetGroupMemberOf($tempmemberof, $currgroup)
        For $j = 1 To $tempmemberof[0]
            $exists = 0
            $k = UBound($memberof)
            Do
                $k -= 1
                If StringInStr($memberof[$k], $tempmemberof[$j]) Then $exists = 1
            Until $exists = 1 Or $k = 0
            If $exists = 0 Then _ArrayAdd($memberof, $tempmemberof[$j] & "|" & $currgroup)
        Next
        $i += 1
    Until $i = UBound($memberof)
    
    $count = UBound($memberof)
    _ArrayInsert($memberof, 0, $count)
    
    Return 1
EndFunc;==>_ADRecursiveGetMemberOf

; _ADRecursiveGetGroupMembers
; Takes a Full DN of a group and returns a recursively searched list of members of that group (and groups that are members of the group)
; The return values are full DNs. For groups that are inherited, the return is the DN of the group, and the DN of the first group
; it was inherited from, seperated by '|'.
Func _ADRecursiveGetGroupMembers(ByRef $members, $fqdn)
    Local $objItem, $tempmembers, $i = 1
    
;$objItem = ObjGet("LDAP://" & $strHostServer & "/" & $fqdn); Retrieve the COM Object for the logged on user
    
    _ADGetGroupMembers($members, $fqdn)
    
    If $members[0] = 0 Then
        Return 0
    EndIf
    
    Do
        If StringInStr($members[$i], "|") Then
            $currgroup = StringLeft($members[$i], StringInStr($members[$i], "|") - 1)
        Else
            $currgroup = $members[$i]
        EndIf
        $currgroup = StringReplace($currgroup, "/", "\/")
        If _ADGetObjectClassFromFQDN($currgroup) = "group" Then
            _ADGetGroupMembers($tempmembers, $currgroup)
            For $j = 1 To $tempmembers[0]
                $exists = 0
                $k = UBound($members)
                Do
                    $k -= 1
                    If StringInStr($members[$k], $tempmembers[$j]) Then $exists = 1
                Until $exists = 1 Or $k = 0
                If $exists = 0 Then _ArrayAdd($members, $tempmembers[$j] & "|" & $currgroup)
            Next
        EndIf
        $i += 1
    Until $i = UBound($members)
    
    $count = UBound($members)
;_ArrayInsert($members, 0, $count)
    $members[0] = $count - 1
    
    Return 1
EndFunc;==>_ADRecursiveGetGroupMembers

; _ADGetGroupMembers
; Arguments,
; $members - Array that the result will be stored in
; $group - Group to retrieve members from
; $sort - optional, default 0 : Set to 1 to sort the array
; Returns an array to $members where $members[0] will be the number of users in the group and
; $members[1] to $members[$members[0]] are the distinguished names of the users

Func _ADGetGroupMembers(ByRef $members, $groupdn, $sort = 0)
;If _ADObjectExists($group) = 0 Then Return 0
    
    Local $oUsr, $objCommand, $groups

    $objCommand = ObjCreate("ADODB.Command")
    $objCommand.ActiveConnection = $objConnection
    $objCommand.Properties("Searchscope") = 2

    Dim $members[1]
    $i = 0

    While 1
        $rangemodifier = $i * 1000
        $range = "Range=" & $rangemodifier & "-" & $rangemodifier + 999
        $strCmdText = "<LDAP://" & $strHostServer & "/" & $groupdn & ">;;member;" & $range & ";base"
        $objCommand.CommandText = $strCmdText
        $objRecordSet = $objCommand.Execute
        $membersadd = $objRecordSet.fields(0).Value
        If $membersadd = 0 Then ExitLoop
        ReDim $members[UBound($members) + 1000]
        For $j = $rangemodifier + 1 To $rangemodifier + 1000
            $members[$j] = $membersadd[$j - $rangemodifier - 1]
        Next
        $i += 1
        $objRecordSet.Close
    WEnd

    $rangemodifier = $i * 1000
    $range = "Range=" & $rangemodifier & "-*"
    $strCmdText = "<LDAP://" & $strHostServer & "/" & $groupdn & ">;;member;" & $range & ";base"
    $objCommand.CommandText = $strCmdText
    $objRecordSet = $objCommand.Execute
    $membersadd = $objRecordSet.fields(0).Value

    ReDim $members[UBound($members) + UBound($membersadd)]

    For $j = $rangemodifier + 1 To $rangemodifier + UBound($membersadd)
        $members[$j] = $membersadd[$j - $rangemodifier - 1]
    Next

    $objRecordSet.Close
    
    $objCommand = 0
    $objRecordSet = 0
    
    $members[0] = UBound($members) - 1
    
    If $sort = 1 Then
        _ArraySort($members, 0, 1)
    EndIf
    
    Return 1
EndFunc;==>_ADGetGroupMembers

; _ADGetGroupMemberOf
Func _ADGetGroupMemberOf(ByRef $memberof, $groupdn, $sort = 0)
    Local $oUsr, $objCommand, $groups

    $objCommand = ObjCreate("ADODB.Command")
    $objCommand.ActiveConnection = $objConnection
    $objCommand.Properties("Searchscope") = 2
    
    Dim $memberof[1]
    $i = 0

    While 1
        $rangemodifier = $i * 1000
        $range = "Range=" & $rangemodifier & "-" & $rangemodifier + 999
        $strCmdText = "<LDAP://" & $strHostServer & "/" & $groupdn & ">;;memberof;" & $range & ";base"
        $objCommand.CommandText = $strCmdText
        $objRecordSet = $objCommand.Execute
        $membersadd = $objRecordSet.fields(0).Value
        If $membersadd = 0 Then ExitLoop
        ReDim $memberof[UBound($memberof) + 1000]
        For $j = $rangemodifier + 1 To $rangemodifier + 1000
            $memberof[$j] = $membersadd[$j - $rangemodifier - 1]
        Next
        $i += 1
        $objRecordSet.Close
    WEnd

    $rangemodifier = $i * 1000
    $range = "Range=" & $rangemodifier & "-*"
    $strCmdText = "<LDAP://" & $strHostServer & "/" & $groupdn & ">;;memberof;" & $range & ";base"
    $objCommand.CommandText = $strCmdText
    $objRecordSet = $objCommand.Execute
    $membersadd = $objRecordSet.fields(0).Value
    ReDim $memberof[UBound($memberof) + UBound($membersadd)]

    For $j = $rangemodifier + 1 To $rangemodifier + UBound($membersadd)
        $memberof[$j] = $membersadd[$j - $rangemodifier - 1]
    Next
    $objRecordSet.Close
    
    $objCommand = 0
    $objRecordSet = 0
    
    $memberof[0] = UBound($memberof) - 1
    
    If $sort = 1 Then
        _ArraySort($memberof, 0, 1)
    EndIf
    
    Return $memberof[0]
    
EndFunc;==>_ADGetGroupMemberOf

; _ADHasFullRights
; Take an object's SamAccountName, a user's SamAccountName
; Returns 1 if User has full rights on the object
; Returns 0 otherwise

Func _ADHasFullRights($object, $user = @UserName)
    Dim $hfr_groups
    If $user = @UserName Then
        $hfr_groups = $loggedonusergroups
    Else
        _ADGetUserGroups($hfr_groups, $user)
    EndIf

    
    $oObject = ObjGet("LDAP://" & $strHostServer & "/" & $object)
    
    If IsObj($oObject) Then
        $security = $oObject.Get("ntSecurityDescriptor")
        $dacl = $security.DiscretionaryAcl
        For $ace In $dacl
            $trusteearray = StringSplit($ace.Trustee, "\")
            $trusteegroup = $trusteearray[$trusteearray[0]]
            For $i = 0 To UBound($hfr_groups) - 1
                If StringInStr($hfr_groups[$i], "CN=" & $trusteegroup) And $ace.AccessMask = 983551 Then Return 1
            Next
        Next
    EndIf
    
    $oObject = 0
    $security = 0
    $dacl = 0
    
    Return 0
EndFunc;==>_ADHasFullRights

; _ADGroupMailEnable
; Takes a group and enables mail on that group
Func _ADGroupMailEnable($group)
    If _ADObjectExists($group) = 0 Then Return 0
    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $group & ");ADsPath;subtree"
    $objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the group, if it exists
    
    $ldap_entry = $objRecordSet.fields(0).value
    $oGroup = ObjGet($ldap_entry); Retrieve the COM Object for the object
    
    $oGroup.Put("grouptype", $ADS_GROUP_TYPE_UNIVERSAL_SECURITY)
    $oGroup.MailEnable
    $oGroup.SetInfo
    
    $oGroup = 0
    
    Return 1
EndFunc;==>_ADGroupMailEnable

; _ADUserCreateMailbox
; $user - User to add mailbox to
; $mdbstore - Mailbox storename
; $store - Information store
; $server - Email server
; $admingroup - Administrative group in Exchange
; $domain - Domain name
Func _ADUserCreateMailbox($user, $mdbstore, $store, $server, $admingroup, $domain)
    If _ADObjectExists($user) = 0 Then Return 0
    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $user & ");ADsPath;subtree"
    $objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the group, if it exists
    
    $ldap_entry = $objRecordSet.fields(0).value
    $oUser = ObjGet($ldap_entry); Retrieve the COM Object for the object
    
    If $oUser.HomeMDB <> "" Then Return 0
    
    $mailboxpath = "LDAP://CN="
    $mailboxpath = $mailboxpath & $mdbstore
    $mailboxpath = $mailboxpath & ",CN="
    $mailboxpath = $mailboxpath & $store
    $mailboxpath = $mailboxpath & ",CN=InformationStore"
    $mailboxpath = $mailboxpath & ",CN="
    $mailboxpath = $mailboxpath & $server
    $mailboxpath = $mailboxpath & ",CN=Servers,CN="
    $mailboxpath = $mailboxpath & $admingroup
    $mailboxpath = $mailboxpath & ",CN=Administrative Groups,CN=State Street,CN=Microsoft Exchange,CN=Services,CN=Configuration,"
    $mailboxpath = $mailboxpath & $domain
    
    $oUser.CreateMailbox($mailboxpath)
    $oUser.SetInfo
    
    $oUser = 0
    
    Return 1
EndFunc;==>_ADUserCreateMailbox

; _ADUserDeleteMailbox
; Deletes a user's mailbox
Func _ADUserDeleteMailbox($user)
    If _ADObjectExists($user) = 0 Then Return 0

    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $user & ");ADsPath;subtree"
    $objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the group, if it exists
    
    $ldap_entry = $objRecordSet.fields(0).value
    $oUser = ObjGet($ldap_entry); Retrieve the COM Object for the object
    
    If $oUser.HomeMDB = "" Then Return 0
    
    $oUser.DeleteMailbox
    $oUser.SetInfo
    
    $oUser = 0
    
    Return 1
EndFunc;==>_ADUserDeleteMailbox

; _ADGetObjectsInOU
; Returns an array of the objects in an OU
; $ou : The OU to retrieve from
; $filter : optional, default "name'*'". An additional LDAP filter if required.
; $searchscope : optional, default 2. 0 = base, 1 = one-level, 2 = sub-tree
; $datatoretrieve : optional, default "Name". A comma-seperated list of values to retrieve. More than one value will create
; a 2-dimensional array, array[0][0] will contain the number of items returned, which start at array[1][0]

Func _ADGetObjectsInOU(ByRef $ObjectArray, $ou, $filter = "name='*'", $searchscope = 2, $datatoretrieve = "sAMAccountName", $sortby = "sAMAccountName")
    Local $objRecordSet
    $objCommand = ObjCreate("ADODB.Command")
    $objCommand.ActiveConnection = $objConnection
    $objCommand.Properties("Page Size") = 256
    $objCommand.Properties("Searchscope") = $searchscope
    $objCommand.Properties("TimeOut") = 20
    
    $strCmdText = "<LDAP://" & $strHostServer & "/" & $ou & ">;" & $filter & ";" & $datatoretrieve & ";subtree"
    
    $objCommand.CommandText = $strCmdText
    $objRecordSet = $objCommand.Execute

    $recordcount = $objRecordSet.RecordCount
    If $recordcount = 0 Then
        $objCommand = 0
        $objRecordSet = 0
        Return 0
    EndIf
    
    If StringInStr($datatoretrieve, ",") Then

        $dtrArray = StringSplit($datatoretrieve, ",")
        
        Dim $ObjectArray[$recordcount + 1][$dtrArray[0]]
        
        $ObjectArray[0][0] = $recordcount
        $ObjectArray[0][1] = $dtrArray[0]
        
        $count = 1
        $objRecordSet.MoveFirst
        Do
            For $i = 1 To $dtrArray[0]
                $ObjectArray[$count][$i - 1] = $objRecordSet.Fields($dtrArray[$i] ).Value
            Next
            $objRecordSet.MoveNext
            $count += 1
        Until $objRecordSet.EOF
    Else
        Dim $ObjectArray[$recordcount + 1]
        $ObjectArray[0] = UBound($ObjectArray) - 1
        If $ObjectArray[0] = 0 Then
            $ObjectArray = 0
            Return 0
        Else
            $count = 1
            $objRecordSet.MoveFirst
            Do
                $ObjectArray[$count] = $objRecordSet.Fields($datatoretrieve).Value
                $objRecordSet.MoveNext
                $count += 1
            Until $objRecordSet.EOF
        EndIf
    EndIf
    
    $objCommand = 0
    $objRecordSet = 0
    
    Return 1
    
EndFunc;==>_ADGetObjectsInOU

; _ADDNToSamAccountName
; Takes a FQDN and returns the SamID of the account

Func _ADDNToSamAccountName($fqdn)
    $obj = ObjGet("LDAP://" & $strHostServer & "/" & $fqdn)
    If $obj = 0 Then
        MsgBox(262144, "", "Failed to retrieve AD object")
        Return 0
    EndIf
    
    $samname = $obj.sAMAccountName
    
    $obj = 0
    
    Return $samname
EndFunc;==>_ADDNToSamAccountName

; _ADSamAccountNameToFQDN
; Takes a SamID and returns the FQDN of the account

Func _ADSamAccountNameToFQDN($samname)
    
    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $samname & ");distinguishedName;subtree"
    $objRecordSet = $objConnection.Execute($strQuery)
    
    If $objRecordSet.RecordCount = 1 Then
        $fqdn = $objRecordSet.fields(0).value
        $objRecordSet = 0
        Return StringReplace($fqdn, "/", "\/")
    Else
        $objRecordSet = 0
        Return ""
    EndIf
EndFunc;==>_ADSamAccountNameToFQDN

; _ADDNToDisplayName
; Returns the Display Name of an FQDN
Func _ADDNToDisplayName($fqdn)
    $objItem = ObjGet("LDAP://" & $strHostServer & "/" & $fqdn)
    $name = $objItem.name
    $objItem = 0
    Return $name
EndFunc;==>_ADDNToDisplayName

; _ADCreateObject
; $objectou = OU to create the group in. Form is "sampleou=ou, sampleparent=ou, sampledomain1=dc, sampledomain2=dc, sampledomain3=dc"
; $object = Object name, form is SamAccountName without leading 'CN='
; $type = Type of object to create

Func _ADCreateObject($objectou, $object, $type)
    If _ADObjectExists($object) Then Return 0
    
    If StringLeft($object, 3) <> "CN=" Then
        $object = "CN=" & $object
    EndIf

    $ObjOU = ObjGet("LDAP://" & $strHostServer & "/" & $objectou)
    $ObjADObj = $ObjOU.Create($type, $object)
    
    $ObjADObj.Put("sAMAccountName", StringTrimLeft($object, 3))
    If $type = "Computer" Then
        $ObjADObj.Put("UserAccountControl", BitOR(0x0020, 0x1000))
    EndIf
    
    $ObjADObj.SetInfo
    
    $ObjADObj = 0
    
    Return 1
EndFunc;==>_ADCreateObject

; _ADCreateComputer
; $strComputer = Name of the computer object to create
; $computerOU = Full DN of the OU to create the computer in
; $strComputerUser = User or group that will be allowed to add the computer to the domain (SamAccountName)
Func _ADCreateComputer($strComputer, $computerOU, $strComputerUser)

    $objContainer = ObjGet("LDAP://" & $strHostServer & "/" & $computerOU)

    $objComputer = $objContainer.Create("Computer", "cn=" & $strComputer)
    $objComputer.Put("sAMAccountName", $strComputer & "$")
    $objComputer.Put("userAccountControl", BitOR($ADS_UF_PASSWD_NOTREQD, $ADS_UF_WORKSTATION_TRUST_ACCOUNT))
    $objComputer.SetInfo

    $objSecurityDescriptor = $objComputer.Get("ntSecurityDescriptor")
    $objDACL = $objSecurityDescriptor.DiscretionaryAcl

    $objACE1 = ObjCreate("AccessControlEntry")
    $objACE1.Trustee = $strComputerUser
    $objACE1.AccessMask = $ADS_RIGHT_GENERIC_READ
    $objACE1.AceFlags = 0
    $objACE1.AceType = $ADS_ACETYPE_ACCESS_ALLOWED

    $objACE2 = ObjCreate("AccessControlEntry")
    $objACE2.Trustee = $strComputerUser
    $objACE2.AccessMask = $ADS_RIGHT_DS_CONTROL_ACCESS
    $objACE2.AceFlags = 0
    $objACE2.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $objACE2.Flags = $ADS_FLAG_OBJECT_TYPE_PRESENT
    $objACE2.ObjectType = $ALLOWED_TO_AUTHENTICATE

    $objACE3 = ObjCreate("AccessControlEntry")
    $objACE3.Trustee = $strComputerUser
    $objACE3.AccessMask = $ADS_RIGHT_DS_CONTROL_ACCESS
    $objACE3.AceFlags = 0
    $objACE3.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $objACE3.Flags = $ADS_FLAG_OBJECT_TYPE_PRESENT
    $objACE3.ObjectType = $RECEIVE_AS

    $objACE4 = ObjCreate("AccessControlEntry")
    $objACE4.Trustee = $strComputerUser
    $objACE4.AccessMask = $ADS_RIGHT_DS_CONTROL_ACCESS
    $objACE4.AceFlags = 0
    $objACE4.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $objACE4.Flags = $ADS_FLAG_OBJECT_TYPE_PRESENT
    $objACE4.ObjectType = $SEND_AS

    $objACE5 = ObjCreate("AccessControlEntry")
    $objACE5.Trustee = $strComputerUser
    $objACE5.AccessMask = $ADS_RIGHT_DS_CONTROL_ACCESS
    $objACE5.AceFlags = 0
    $objACE5.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $objACE5.Flags = $ADS_FLAG_OBJECT_TYPE_PRESENT
    $objACE5.ObjectType = $USER_CHANGE_PASSWORD

    $objACE6 = ObjCreate("AccessControlEntry")
    $objACE6.Trustee = $strComputerUser
    $objACE6.AccessMask = $ADS_RIGHT_DS_CONTROL_ACCESS
    $objACE6.AceFlags = 0
    $objACE6.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $objACE6.Flags = $ADS_FLAG_OBJECT_TYPE_PRESENT
    $objACE6.ObjectType = $USER_FORCE_CHANGE_PASSWORD

    $objACE7 = ObjCreate("AccessControlEntry")
    $objACE7.Trustee = $strComputerUser
    $objACE7.AccessMask = $ADS_RIGHT_DS_WRITE_PROP
    $objACE7.AceFlags = 0
    $objACE7.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $objACE7.Flags = $ADS_FLAG_OBJECT_TYPE_PRESENT
    $objACE7.ObjectType = $USER_ACCOUNT_RESTRICTIONS

    $objACE8 = ObjCreate("AccessControlEntry")
    $objACE8.Trustee = $strComputerUser
    $objACE8.AccessMask = $ADS_RIGHT_DS_SELF
    $objACE8.AceFlags = 0
    $objACE8.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $objACE8.Flags = $ADS_FLAG_OBJECT_TYPE_PRESENT
    $objACE8.ObjectType = $VALIDATED_DNS_HOST_NAME

    $objACE9 = ObjCreate("AccessControlEntry")
    $objACE9.Trustee = $strComputerUser
    $objACE9.AccessMask = $ADS_RIGHT_DS_SELF
    $objACE9.AceFlags = 0
    $objACE9.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $objACE9.Flags = $ADS_FLAG_OBJECT_TYPE_PRESENT
    $objACE9.ObjectType = $VALIDATED_SPN

    $objDACL.AddAce($objACE1)
    $objDACL.AddAce($objACE2)
    $objDACL.AddAce($objACE3)
    $objDACL.AddAce($objACE4)
    $objDACL.AddAce($objACE5)
    $objDACL.AddAce($objACE6)
    $objDACL.AddAce($objACE7)
    $objDACL.AddAce($objACE8)
    $objDACL.AddAce($objACE9)

    $objSecurityDescriptor.DiscretionaryAcl = $objDACL
    $objComputer.Put("ntSecurityDescriptor", $objSecurityDescriptor)
    $objComputer.SetInfo

EndFunc;==>_ADCreateComputer

; _ADDeleteObject
; $object = DisplayName of object to delete. $type="user" or "group".

Func _ADDeleteObject($ou, $object, $type)
    If StringLeft($object, 3) <> "CN=" Then
        $object = "CN=" & StringReplace($object, ",", "\,")
    EndIf
    $ObjOU = ObjGet("LDAP://" & $strHostServer & "/" & $ou)
    $ObjOU.Delete($type, $object)
    $ObjOU = 0
    Return 1
EndFunc;==>_ADDeleteObject

; _ADGetObjectClass
; Returns the Class of an object. Returns 0 if the object does not exist.
Func _ADGetObjectClass($object)
    If _ADObjectExists($object) = 0 Then Return 0

    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $object & ");ADsPath;subtree"
    $objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the object
    $ldap_entry = $objRecordSet.fields(0).value
    $oObject = ObjGet($ldap_entry); Retrieve the COM Object for the object
    
    $class = $oObject.Class
    $oObject = 0
    
    Return $class
    
EndFunc;==>_ADGetObjectClass

; _ADGetObjectClassFromFQDN
; Returns the Class of an objectfrom an objects FQDN. Returns 0 if the object does not exist.
Func _ADGetObjectClassFromFQDN($object)
    $oObject = ObjGet("LDAP://" & $strHostServer & "/" & $object); Retrieve the COM Object for the object
    If IsObj($oObject) = 0 Then Return 0
    $class = $oObject.Class
    $oObject = 0
    Return $class
EndFunc;==>_ADGetObjectClassFromFQDN

; _ADGetObjectAttribute
; Retrieves the specified (single-value) attribute for the given SamAccountName
; Returns 0 if the object does not exist, the attribute does not exist for that
; object or if the value is multi-string.
; Otherwise returns the result
Func _ADGetObjectAttribute($object, $attribute)
    If _ADObjectExists($object) = 0 Then Return 0

    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $object & ");ADsPath;subtree"
    $objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the object
    $ldap_entry = $objRecordSet.fields(0).value
    $oObject = ObjGet($ldap_entry); Retrieve the COM Object for the object
    $result = $oObject.Get($attribute)
    $oObject.PurgePropertyList
    $oObject = 0
    If $result = "" Then
        Return ""
    Else
;~      Return $result
        MsgBox(0,'',$result)
    EndIf
    
EndFunc;==>_ADGetObjectAttribute

; _ADListDomainControllers
; Retrieves the names of all domain controllers in the current Domain
Func _ADListDomainControllers(ByRef $DCList)
    $objCommand = ObjCreate("ADODB.Command")
    $objCommand.ActiveConnection = $objConnection
    $objCommand.Properties("Page Size") = 1000
    $objCommand.Properties("Searchscope") = 2
    
    $objCommand.CommandText = "Select distinguishedName FROM 'LDAP://" & $strHostServer & "/ou=Domain Controllers," & $strDNSDomain & "' WHERE objectclass='computer'"
    
    $objRecordSet = $objCommand.Execute
    Dim $DCList[$objRecordSet.RecordCount + 1]
    $objRecordSet.MoveFirst
    
    Do
        $DCList[0] += 1
        
        $objCommand.CommandText = "<LDAP://" & $strHostServer & "/" & $objRecordSet.Fields("distinguishedName" ).Value & ">;;serverReferenceBL;Range=0-*;base"
        $objRecSet2 = $objCommand.Execute
        
        $objRecSet2.MoveFirst
        Do
            $temparray = $objRecSet2.Fields(0).Value
            $DCList[$DCList[0]] = $temparray[0]
            $objRecSet2.MoveNext
        Until $objRecSet2.EOF
        
        $objRecordSet.MoveNext
    Until $objRecordSet.EOF
    
    $objCommand = 0
    $objRecordSet = 0
    Return
EndFunc;==>_ADListDomainControllers

; _ADOUObjectNames
; A faster call for returning the Display Name of objects in a given OU
Func _ADOUObjectNames(ByRef $objects, $ou, $filter = 0)
    Local $i
    
    $ObjOU = ObjGet("LDAP://" & $strHostServer & "/" & $ou)

    If $filter <> 0 Then $ObjOU.Filter = $filter

    Dim $tempobjects[100000]
    
    $i = 0

    For $object In $ObjOU
        $tempobjects[$i] = $object.name
        $i += 1
    Next
    
    If $i = 0 Then
        $objects = 0
        $ObjOU = 0
        Return
    EndIf
    
    Dim $objects[$i + 1]
    $objects[0] = $i
    
    For $j = 1 To $i
        $tempstr = $tempobjects[$j - 1]
        $tempstr = StringTrimLeft($tempstr, 3)
        $objects[$j] = StringReplace($tempstr, "\,", ",")
    Next
    $ObjOU = 0
EndFunc;==>_ADOUObjectNames

; _ADGroupManagerCanModify :
; Returns 1 if the manager of the group can modify the member list, 0 if not, -1 if there is no manager assigned
; Takes full DNs to the group and user

Func _ADGroupManagerCanModify($groupdn)
    $ObjGroup = ObjGet("LDAP://" & $strHostServer & "/" & $groupdn)
    $managedBy = $ObjGroup.Get("managedBy")
    
    If $managedBy = "" Then Return -1
    
    $ObjUser = ObjGet("LDAP://" & $strHostServer & "/" & $managedBy)
    
    $arrUserDN = StringSplit($managedBy, "DC=", 1)
    $strDomain = StringTrimRight($arrUserDN[2], 1)
    $strSamAccountName = $ObjUser.Get("sAMAccountName")
    
    $objNTSecurityDescriptor = $ObjGroup.Get("ntSecurityDescriptor")
    $objDiscretionaryAcl = $objNTSecurityDescriptor.DiscretionaryAcl
    
    $blnMatch = False
    For $objAce In $objDiscretionaryAcl
        If StringLower($objAce.Trustee) = StringLower($strDomain & "\" & $strSamAccountName) And _
                $objAce.ObjectType = $Member_SchemaIDGuid And _
                $objAce.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT And _
                BitAND($objAce.AccessMask, $ADS_RIGHT_DS_WRITE_PROP) = $ADS_RIGHT_DS_WRITE_PROP Then $blnMatch = True
    Next
    
    $ObjGroup = 0
    $ObjUser = 0
    $objNTSecurityDescriptor = 0
    $objDiscretionaryAcl = 0
    
    If $blnMatch Then
        Return 1
    Else
        Return 0
    EndIf
EndFunc;==>_ADGroupManagerCanModify

; _ADSetGroupManagerCanModify - Sets the Group manager to be able to modify the member list
; Takes a group DN
; Returns
; -1 if no manager is assigned
; 0 if the manager can already modify the list
; 1 if successful


Func _ADSetGroupManagerCanModify($groupdn)
    If _ADGroupManagerCanModify($groupdn) = 1 Then Return 0
    
    $ObjGroup = ObjGet("LDAP://" & $strHostServer & "/" & $groupdn)
    $managedBy = $ObjGroup.Get("managedBy")
    
    If $managedBy = "" Then Return -1
    
    $ObjUser = ObjGet("LDAP://" & $strHostServer & "/" & $managedBy)
    
    $arrUserDN = StringSplit($managedBy, "DC=", 1)
    $strDomain = StringTrimRight($arrUserDN[2], 1)
    $strSamAccountName = $ObjUser.Get("sAMAccountName")
    
    $objNTSecurityDescriptor = $ObjGroup.Get("ntSecurityDescriptor")
    
    $objNTSecurityDescriptor.Owner = $strDomain & "\" & @UserName
    $objDiscretionaryAcl = $objNTSecurityDescriptor.DiscretionaryAcl
    
    $objAce = ObjCreate("AccessControlEntry")
    $objAce.Trustee = $strDomain & "\" & $strSamAccountName
    $objAce.AccessMask = $ADS_RIGHT_DS_WRITE_PROP
    $objAce.AceFlags = 0
    $objAce.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $objAce.Flags = $ADS_FLAG_OBJECT_TYPE_PRESENT
    $objAce.ObjectType = $Member_SchemaIDGuid
    
    $objDiscretionaryAcl.AddAce($objAce)
    $objNTSecurityDescriptor.DiscretionaryAcl = $objDiscretionaryAcl
    $ObjGroup.Put("ntSecurityDescriptor", $objNTSecurityDescriptor)
    $ObjGroup.SetInfo
    If @error = 3 Then
        MsgBox(262144, "Error", "An error occurred assigning permissions on the group.")
        $ObjGroup = 0
        $objDiscretionaryAcl = 0
        $objNTSecurityDescriptor = 0
        $objAce = 0
        Return 0
    EndIf
    $ObjGroup = 0
    $objDiscretionaryAcl = 0
    $objNTSecurityDescriptor = 0
    $objAce = 0
    Return 1
EndFunc;==>_ADSetGroupManagerCanModify

; _ADGroupAssignManager
; Takes a group DN and a User DN, assigns the user as the manager of the group

Func _ADGroupAssignManager($groupdn, $userdn)
    $ObjGroup = ObjGet("LDAP://" & $strHostServer & "/" & $groupdn)
    
    $ObjGroup.Put("managedBy", $userdn)
    $ObjGroup.SetInfo
    $ObjGroup = 0
    Return 1
EndFunc;==>_ADGroupAssignManager

; _ADGroupRemoveManager
; Takes a group DN and deletes the group's manager
; arg $option -- 0 (default) removes the manager; 1 only removes manager's modify permission

Func _ADGroupRemoveManager($groupdn, $option = 0)
    $ObjGroup = ObjGet("LDAP://" & $strHostServer & "/" & $groupdn)
    
    $managedBy = $ObjGroup.Get("managedBy")
    
    If $managedBy = "" Then Return -1
    
    $ObjUser = ObjGet("LDAP://" & $strHostServer & "/" & $managedBy)
    
    $arrUserDN = StringSplit($managedBy, "DC=", 1)
    $strDomain = StringTrimRight($arrUserDN[2], 1)
    $strSamAccountName = $ObjUser.Get("sAMAccountName")
    
    $objNTSecurityDescriptor = $ObjGroup.Get("ntSecurityDescriptor")
    
    $objNTSecurityDescriptor.Owner = $strDomain & "\" & @UserName
    $objDiscretionaryAcl = $objNTSecurityDescriptor.DiscretionaryAcl
    $objTempAcl = ObjCreate("AccessControlList")
    
    $blnMatch = False
    For $objAce In $objDiscretionaryAcl
        If StringLower($objAce.Trustee) = StringLower($strDomain & "\" & $strSamAccountName) And _
                $objAce.ObjectType = $Member_SchemaIDGuid And _
                $objAce.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT And _
                $objAce.AccessMask = $ADS_RIGHT_DS_WRITE_PROP Then _
                $objDiscretionaryAcl.RemoveAce($objAce)
    Next
    
    $objNTSecurityDescriptor.DiscretionaryAcl = $objDiscretionaryAcl
    $ObjGroup.Put("ntSecurityDescriptor", $objNTSecurityDescriptor)
    If Not $option Then $ObjGroup.PutEx(1, "managedBy", 0)
    $ObjGroup.SetInfo
    
    $ObjGroup = 0
    $ObjUser = 0
    $objNTSecurityDescriptor = 0
    $objDiscretionaryAcl = 0
    
EndFunc;==>_ADGroupRemoveManager

; _ADEnableAccount
; Takes a DN of an object and enables it if the user has permissions
; Returns 1 if successful, @error otherwise

Func _ADEnableAccount($fqdn)
    $objAccount = ObjGet("LDAP://" & $strHostServer & "/" & $fqdn)
    
    $objAccount.AccountDisabled = False
    $objAccount.SetInfo
    $loc_error = @error
    $objAccount = 0
    If $loc_error = 0 Then
        Return 1
    Else
        Return $loc_error
    EndIf
EndFunc;==>_ADEnableAccount

; _ADDisableAccount
; Takes a DN of an object and disables it if the user has permissions
; Returns 1 if successful, @error otherwise

Func _ADDisableAccount($fqdn)
    $objAccount = ObjGet("LDAP://" & $strHostServer & "/" & $fqdn)
    
    $intUAC = $objAccount.Get("userAccountControl")
    
    $objAccount.Put("userAccountControl", BitOR($intUAC, $ADS_UF_ACCOUNTDISABLE))
    $objAccount.SetInfo
    $loc_error = @error
    $objAccount = 0
    If $loc_error = 0 Then
        Return 1
    Else
        Return $loc_error
    EndIf
EndFunc;==>_ADDisableAccount

; _ADGetLastLoginDate
; Takes a SamAccountName of a user account and returns the .lastlogin information for the current DC
Func _ADGetLastLoginDate($user)
    If _ADObjectExists($user) = 0 Then Return 0

    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $user & ");ADsPath;subtree"
    $objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the object
    $ldap_entry = $objRecordSet.fields(0).value
    $oObject = ObjGet($ldap_entry); Retrieve the COM Object for the object
    $result = $oObject.LastLogin
    $oObject.PurgePropertyList
    
    If $result = "" Then
        Return ""
    Else
        Return $result
    EndIf
EndFunc;==>_ADGetLastLoginDate

; _ADAddAccountToMailboxRights
; Takes $mailbox as FQDN and $accountsam as "domain\username"
; Adds Full mailbox rights and 'send as' permission for $accountsam on $mailbox.
; Returns 2 if account already has rights, otherwise returns @error (should be 0 for success, 1 for failure)
Func _ADAddAccountToMailboxRights($mailbox, $accountsam)
    $obj_mailbox = ObjGet("LDAP://" & $strHostServer & "/" & $mailbox)
    If Not IsObj($obj_mailbox) Then
;MsgBox(0, "Error", "Mailbox was not a FQDN or was not found.")
        SetError(3)
        Return
    EndIf
    $obj_mailboxsecurity = $obj_mailbox.MailboxRights
    $mailbox_dacl = $obj_mailboxsecurity.DiscretionaryAcl
    
    For $ace In $mailbox_dacl
        If $ace.trustee = $accountsam Then
;MsgBox(0, "", "User already has full rights to mailbox")
            SetError(2)
            Return @error
        EndIf
    Next
    
    $obj_ace1 = ObjCreate("AccessControlEntry")
    $obj_ace1.Trustee = $accountsam
    $obj_ace1.AccessMask = 1
    $obj_ace1.AceType = 0
    $obj_ace1.AceFlags = 2
    $obj_ace1.ObjectType = 0
    $obj_ace1.InheritedObjectType = 0
    $obj_ace1.Flags = 0
    
    $mailbox_dacl.AddAce($obj_ace1)
    
    $obj_mailboxsecurity.DiscretionaryAcl = $mailbox_dacl
    $obj_mailbox.MailboxRights = $obj_mailboxsecurity
    
    $obj_ntsecurity = $obj_mailbox.Get("ntSecurityDescriptor")
    $ntsecurity_dacl = $obj_ntsecurity.DiscretionaryAcl
    
    $obj_ace2 = ObjCreate("AccessControlEntry")
    $obj_ace2.Trustee = $accountsam
    $obj_ace2.AccessMask = $ADS_RIGHT_DS_CONTROL_ACCESS
    $obj_ace2.AceFlags = 0
    $obj_ace2.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $obj_ace2.Flags = 1;$ADS_FLAG_OBJECT_TYPE_PRESENT
    $obj_ace2.ObjectType = $SEND_AS
    
    $ntsecurity_dacl.AddAce($obj_ace2)
    
    $obj_ntsecurity.DiscretionaryAcl = $ntsecurity_dacl
    $obj_mailbox.Put("ntSecurityDescriptor", $obj_ntsecurity)
    $obj_mailbox.SetOption($ADS_OPTION_SECURITY_MASK, $ADS_SECURITY_INFO_DACL)
    $obj_mailbox.SetInfo
    
    Return @error
EndFunc;==>_ADAddAccountToMailboxRights

Func _ADRemoveMailboxRights($mailbox, $accountsam)
    $obj_mailbox = ObjGet("LDAP://" & $strHostServer & "/" & $mailbox)
    If Not IsObj($obj_mailbox) Then
;MsgBox(0, "Error", "Mailbox was not a FQDN or was not found.")
        SetError(3)
        Return
    EndIf
    $obj_mailboxsecurity = $obj_mailbox.MailboxRights
    $mailbox_dacl = $obj_mailboxsecurity.DiscretionaryAcl
    
    For $ace In $mailbox_dacl
        If $ace.trustee = $accountsam Then
            $mailbox_dacl.RemoveAce($ace)
        EndIf
    Next
    
    $obj_mailboxsecurity.DiscretionaryAcl = $mailbox_dacl
    $obj_mailbox.MailboxRights = $obj_mailboxsecurity
    
    $obj_ntsecurity = $obj_mailbox.Get("ntSecurityDescriptor")
    $ntsecurity_dacl = $obj_ntsecurity.DiscretionaryAcl
    
    For $ace In $ntsecurity_dacl
        If $ace.trustee = $accountsam Then
            $ntsecurity_dacl.RemoveAce($ace)
        EndIf
    Next
    
    $obj_ntsecurity.DiscretionaryAcl = $ntsecurity_dacl
    $obj_mailbox.Put("ntSecurityDescriptor", $obj_ntsecurity)
    $obj_mailbox.SetOption($ADS_OPTION_SECURITY_MASK, $ADS_SECURITY_INFO_DACL)
    $obj_mailbox.SetInfo
    Return @error
    
EndFunc;==>_ADRemoveMailboxRights

; _ADGetMailboxPerms
; Takes a mailbox and an array.
; Returns all SamIDs for non-inherited ACEs on the mailbox (stored in the specified array as SamIds)
; Can be filtered on an accessmask value (default = 1, full permissions)
Func _ADGetMailboxPerms($mailbox, ByRef $outputarray, $filter = 1)
    $obj_mailbox = ObjGet("LDAP://" & $strHostServer & "/" & $mailbox)
    If Not IsObj($obj_mailbox) Then
;MsgBox(0, "Error", "Mailbox was not a FQDN or was not found.")
        SetError(3)
        Return
    EndIf
    $obj_mailboxsecurity = $obj_mailbox.MailboxRights
    $mailbox_dacl = $obj_mailboxsecurity.DiscretionaryAcl
    
    For $ace In $mailbox_dacl
        If $ace.AceFlags = 2 Then
            If BitAND($ace.AccessMask, 1) = 1 And $ace.AceType = 0 Then
                _ArrayAdd($outputarray, $ace.Trustee)
            EndIf
        EndIf
    Next
EndFunc;==>_ADGetMailboxPerms
Edited by rikho
Link to comment
Share on other sites

  • 3 weeks later...

Hi,

I'm having the same problem with attritbute "lastLogonTimestamp".

It's also INTEGER8. Any ideas so far? Do you have solved the problem?

Querying with DSQUERY works - ADFUNCTIONS.AU3 not.

Greet,

-supersonic.

Hi all

I read all -> http://www.autoitscript.com/forum/index.ph...mp;#entry221862

I got ADFUNCTION.AU3 -> I know that islockedaccount is bugged.

I just want to display the lockoutime value in an msgbox

ADSI edit show me that the propertie lockoutTime is a Optionnal value in INTEGER8 syntax...

i think i'm not in the good direction

Is some one can try to help me ?

My code bellow :

#include <array.au3>
#include <adfunctions.au3>

$sUser = InputBox("Username", "Enter the username:")
$samname = ($sUser)
$strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $samname & ");ADsPath;subtree"
$objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the object
$ldap_entry = $objRecordSet.fields (0).value
$oObject = ObjGet($ldap_entry); Retrieve the COM Object for the object
$result = $oObject.LockoutTime
$oObject.PurgePropertyList

If $result = "" Then
    Exit
Else
    MsgBox(0, '', $result)
EndIf

My include adfunctions.au3

; Active Directory Function Library. Include this to allow access to Active Directory Functions

; Author : Jonthan Clelland
; Email : jclelland@statestreet.com
; Version : 3.0

; _ADDoError  : Error event handler for COM errors. This is global so will pick up errors from your program if you include this library
; _ADCreateUser : Creates a user in a particular OU
; _ADCreateGroup : Creates a group in a particular OU
; _ADAddUserToGroup : Adds a user to a group (if the user is not already a member of the group)
; _ADRemoveUserFromGroup : Removes a user from a group
; _ADObjectExists : Returns 1 if the given object (SamAccountName) exists in the local AD Tree
; _ADModifyAttribute : Sets the attribute of the given object to the value specified
; _ADIsMemberOf : Returns 1 if the user is a member of the group
; _ADGetUserGroups : Returns an array (byreference) containing the groups that the user is a member of
; _ADRecursiveGetMemberOf : Returns a recursed list of group membership for a group or user
; _ADGetGroupMembers : Returns an array of the group members
; _ADGetGroupMemberOf : Returns a simple list of group membership for a group
; _ADHasFullRights : Returns 1 if the given user has full rights over the given group
; _ADGroupMailEnable : Mail enables a group
; _ADUserCreateMailbox : Creates a mailbox for a user
; _ADUserDeleteMailbox : Deletes the mailbox for a user
; _ADGetObjectsInOU : Returns a filtered list of objects and attributes in a given OU
; _ADDNToSamAccountName : Returns the SamAccountName of an FQDN
; _ADSamAccountNameToFQDN : Returns a FQDN from a SamAccountName
; _ADDNToDisplayName :Returns the Display Name of an FQDN
; _ADCreateObject : Creates an object of a specified type
; _ADCreateComputer : Creates a computer and assigns permissions for a user/group to add the computer
; _ADDeleteObject : Deletes an object
; _ADGetObjectClass : Returns the class of an object
; _ADGetObjectClassFromFQDN : Returns the class of an object from it's FQDN
; _ADGetObjectAttribute : Returns a (single-value) attribute of an object
; _ADListDomainControllers : Returns a list of Domain Controllers for the current domain
; _ADOUObjectNames : Returns display names of filtered objects within an OU
; _ADGroupManagerCanModify : Returns 1 if the manager of the group can modify the member list, 0 if not, -1 if there is no manager assigned
; _ADAddAccountToMailboxRights : Adds useraccount to mailbox with full rights and send as permissions.

; NOTES : Please use the following command to store the local user's groups for the function 'HasFullRights'. This is to allow cross-domain
; permission checks. $loggedonusergroups is a global variable declared in the 'Define AD Constants' region. If you are using this command
; in this library, move the command below the declaration of the variable and remove the comment charcater.

; _ADRecursiveGetMemberOf ($loggedonusergroups, _ADSamAccountNameToFQDN (@UserName))

; include array functions (we use _arraysearch in some functions)
#include <Array.au3>

#Region; Define AD Constants

Global Const $ADS_GROUP_TYPE_GLOBAL_GROUP = 0x2
Global Const $ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP = 0x4
Global Const $ADS_GROUP_TYPE_UNIVERSAL_GROUP = 0x8
Global Const $ADS_GROUP_TYPE_SECURITY_ENABLED = 0x80000000
Global Const $ADS_GROUP_TYPE_GLOBAL_SECURITY = BitOR($ADS_GROUP_TYPE_GLOBAL_GROUP, $ADS_GROUP_TYPE_SECURITY_ENABLED)
Global Const $ADS_GROUP_TYPE_UNIVERSAL_SECURITY = BitOR($ADS_GROUP_TYPE_UNIVERSAL_GROUP, $ADS_GROUP_TYPE_SECURITY_ENABLED)
Global Const $ADS_GROUP_TYPE_DOMAIN_LOCAL_SECURITY = BitOR($ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP, $ADS_GROUP_TYPE_SECURITY_ENABLED)

Global Const $ADS_UF_PASSWD_NOTREQD = 0x0020
Global Const $ADS_UF_WORKSTATION_TRUST_ACCOUNT = 0x1000
Global Const $ADS_ACETYPE_ACCESS_ALLOWED = 0x0
Global Const $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT = 0x5
Global Const $ADS_FLAG_OBJECT_TYPE_PRESENT = 0x1
Global Const $ADS_RIGHT_GENERIC_READ = 0x80000000
Global Const $ADS_RIGHT_DS_SELF = 0x8
Global Const $ADS_RIGHT_DS_WRITE_PROP = 0x20
Global Const $ADS_RIGHT_DS_CONTROL_ACCESS = 0x100
Global Const $ADS_UF_ACCOUNTDISABLE = 2
Global Const $ADS_OPTION_SECURITY_MASK = 3
Global Const $ADS_SECURITY_INFO_DACL = 4

Global Const $ALLOWED_TO_AUTHENTICATE = "{68B1D179-0D15-4d4f-AB71-46152E79A7BC}"
Global Const $RECEIVE_AS = "{AB721A56-1E2f-11D0-9819-00AA0040529B}"
Global Const $SEND_AS = "{AB721A54-1E2f-11D0-9819-00AA0040529B}"
Global Const $USER_CHANGE_PASSWORD = "{AB721A53-1E2f-11D0-9819-00AA0040529b}"
Global Const $USER_FORCE_CHANGE_PASSWORD = "{00299570-246D-11D0-A768-00AA006E0529}"
Global Const $USER_ACCOUNT_RESTRICTIONS = "{4C164200-20C0-11D0-A768-00AA006E0529}"
Global Const $VALIDATED_DNS_HOST_NAME = "{72E39547-7B18-11D1-ADEF-00C04FD8D5CD}"
Global Const $VALIDATED_SPN = "{F3A64788-5306-11D1-A9C5-0000F80367C1}"
Const $Member_SchemaIDGuid = "{BF9679C0-0DE6-11D0-A285-00AA003049E2}"

Global $objConnection = ObjCreate("ADODB.Connection"); Create COM object to AD
$objConnection.ConnectionString = "Provider=ADsDSOObject"
$objConnection.Open("Active Directory Provider"); Open connection to AD


Global $objRootDSE = ObjGet("LDAP://RootDSE")
Global $strDNSDomain = $objRootDSE.Get("defaultNamingContext"); Retrieve the current AD domain name
Global $strHostServer = $objRootDSE.Get("dnsHostName"); Retrieve the name of the connected DC
Global $strConfiguration = $objRootDSE.Get("ConfigurationNamingContext"); Retrieve the Configuration naming context

Global $loggedonusergroups; populate this with the logged on user groups in your own app

#EndRegion  

$oMyError = ObjEvent("AutoIt.Error", "_ADDoError"); Install a custom error handler

;  MyErrFunc
Func _ADDoError()
    $HexNumber = Hex($oMyError.number, 8)
    
    If $HexNumber = 80020009 Then
        SetError(3)
        Return
    EndIf
    
    If $HexNumber = "8007203A" Then
        SetError(4)
        Return
    EndIf
    
    MsgBox(262144, "", "We intercepted a COM Error !" & @CRLF & _
            "Number is: " & $HexNumber & @CRLF & _
            "Windescription is: " & $oMyError.windescription & @CRLF & _
            "Script Line number is: " & $oMyError.scriptline)
    
    Select
        Case $oMyError.windescription = "Access is denied."
            $objConnection.Close("Active Directory Provider")
            $objConnection.Open("Active Directory Provider")
            SetError(2)
        Case 1
            SetError(1)
    EndSelect
    
EndFunc;==>_ADDoError

; _ADCreateUser
; $userou = OU to create the group in. Form is "sampleou=ou, sampleparent=ou, sampledomain1=dc, sampledomain2=dc, sampledomain3=dc"
; $user = Username, form is SamAccountName without leading 'CN='
; $fname = First Name
; $lname = Last Name
; $description = optional - Description

Func _ADCreateUser($userou, $user, $fname, $lname, $description = "User")
    If _ADObjectExists($user) Then Return 0

    $ObjOU = ObjGet("LDAP://" & $strHostServer & "/" & $userou)
    If $fname = "" Then
        $cnname = "CN=" & $lname
    Else
        $cnname = "CN=" & $lname & "\, " & $fname
    EndIf
    $ObjUser = $ObjOU.Create("User", $cnname)
    
    $ObjUser.Put("sAMAccountName", $user)
    $ObjUser.Put("description", $description)

    $ObjUser.SetInfo
    Return 1
EndFunc;==>_ADCreateUser

; _ADCreateGroup
; $gruopou = OU to create the group in. Form is "sampleou=ou, sampleparent=ou, sampledomain1=dc, sampledomain2=dc, sampledomain3=dc"
; $group = groupname, form is SamAccountName without leading 'CN='
; $type = Group type. Defaults to Global Security. See the global constands for other types. NOTE Global security must be 'BitOr'ed with a scope.

Func _ADCreateGroup($groupou, $group, $type = -2147483646)
    If _ADObjectExists($group) Then Return 0
    If StringLeft($group, 3) <> "CN=" Then
        $groupcn = "CN=" & $group
    Else
        $groupcn = $group
    EndIf
    $groupcn = StringReplace($groupcn, "#", "\#")
    $groupcn = StringReplace($groupcn, ",", "\,")
    $groupcn = StringReplace($groupcn, "/", "\/")
    
    $ObjOU = ObjGet("LDAP://" & $strHostServer & "/" & $groupou)
    $ObjGroup = $ObjOU.Create("Group", $groupcn)
    
    $groupsam = StringReplace($group, ",", " ")
    $groupsam = StringReplace($groupsam, "#", " ")
    $groupsam = StringReplace($groupsam, "/", " ")
    $ObjGroup.Put("sAMAccountName", $groupsam)
    $ObjGroup.Put("grouptype", $type)
    
    $ObjGroup.SetInfo
    
    Return 1
EndFunc;==>_ADCreateGroup

; _ADAddUserToGroup
; Takes the group (SamAccountName without leading 'CN=') and the user (SamAccountName without leading 'CN=')
; Adds the user to the group
; Returns 0 if the user is already a member of the group,
; Returns 1 if the user was added to the group
; Returns -1 if there was an error

Func _ADAddUserToGroup($group, $user)
    If _ADIsMemberOf($group, $user) Then Return 0
    $oUsr = ObjGet("LDAP://" & $strHostServer & "/" & $user); Retrieve the COM Object for the user
    $oGroup = ObjGet("LDAP://" & $strHostServer & "/" & $group); Retrieve the COM Object for the group
    
    $oGroup.Add($oUsr.AdsPath)
    $oGroup.SetInfo
    $oGroup = 0
    $oUser = 0
    Return _ADIsMemberOf($group, $user)
EndFunc;==>_ADAddUserToGroup

; _ADRemoveUserFromGroup
; Takes the group (SamAccountName without leading 'CN=') and the user (SamAccountName without leading 'CN=')
; Removes the user from the group (if the user is a member of the group)
; Returns 0 if the user isn't a member of the group, 1 if the user was removed from the group
; Returns -1 if the removal failed.

Func _ADRemoveUserFromGroup($group, $user)
    If _ADIsMemberOf($group, $user) = 0 Then Return 0

    $oUsr = ObjGet("LDAP://" & $strHostServer & "/" & $user); Retrieve the COM Object for the user

    $oGroup = ObjGet("LDAP://" & $strHostServer & "/" & $group); Retrieve the COM Object for the group
    
    $oGroup.Remove($oUsr.AdsPath)
    $oGroup.SetInfo
    
    $oGroup = 0
    $oUser = 0
    
    If _ADIsMemberOf($group, $user) Then
        Return -1
    Else
        Return 1
    EndIf
    
EndFunc;==>_ADRemoveUserFromGroup

; _ADObjectExists
; Takes an object name (SamAccountName without leading 'CN=')
; Returns 1 if the object exists in the tree, 0 otherwise

Func _ADObjectExists($object)
    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $object & ");ADsPath;subtree"
    
    
    $objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the group, if it exists
    
    If $objRecordSet.RecordCount = 1 Then
        $objRecordSet = 0
        Return 1
    Else
        $objRecordSet = 0
        Return 0
    EndIf
EndFunc;==>_ADObjectExists

; _ADModifyAttribute
; $object = Object to modify (samAccountName)
; $attribute = Attribute to modify
; $value = value to set attribute to, use a blank string "" to delete an attribute

Func _ADModifyAttribute($object, $attribute, $value)
    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $object & ");ADsPath;subtree"
    $objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the object
    
    $ldap_entry = $objRecordSet.fields(0).value
    $oObject = ObjGet($ldap_entry); Retrieve the COM Object for the object
    
    $oObject.GetInfo
    
    If $value = "" Then
        $oObject.PutEx(1, $attribute, 0)
    Else
        $oObject.Put($attribute, $value)
    EndIf

    $oObject.SetInfo
    $oObject.PurgePropertyList
    
    $oObject = 0
    
    Return 1
EndFunc;==>_ADModifyAttribute

; _ADIsMemberOf
; Takes samAccountNames for a group and a user
; Returns 1 if the the user is a member of the group, 0 otherwise

Func _ADIsMemberOf($group, $user)
    $ObjGroup = ObjGet("LDAP://" & $strHostServer & "/" & $group)
    $ismember = $ObjGroup.IsMember("LDAP://" & $strHostServer & "/" & $user)
    $ObjGroup = 0
    Return -$ismember
EndFunc;==>_ADIsMemberOf

; _ADGetUserGroups
; the currently logged on user is a member of. Returns an array of Full DNs of the Group names that the user is immediately a member of
; with element 0 containing the number of groups.
; $user - optional -- SamAccountName of a user, defaults to locally logged on user

Func _ADGetUserGroups(ByRef $usergroups, $user = @UserName)
    Local $oUsr
    
    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $user & ");ADsPath;subtree"
    $objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the logged on user
    $ldap_entry = $objRecordSet.fields(0).value
    $oUsr = ObjGet($ldap_entry); Retrieve the COM Object for the logged on user
    
    $usergroups = $oUsr.GetEx("memberof")
    
    $oUsr = 0
    
    $count = UBound($usergroups)
    _ArrayInsert($usergroups, 0, $count)
EndFunc;==>_ADGetUserGroups

; _ADRecursiveGetMemberOf
; Takes a Full DN of a group or user and returns a recursively searched list of groups the object is a member of to the array
; This will traverse through groups that the object is immediately a member of and check their group membership as well.
; The return values are full DNs. For groups that are inherited, the return is the DN of the group, and the DN of the first group
; it was inherited from, seperated by '|'.
Func _ADRecursiveGetMemberOf(ByRef $memberof, $fqdn)
    Local $objItem, $tempmemberof, $i = 0
    
    $objItem = ObjGet("LDAP://" & $strHostServer & "/" & $fqdn); Retrieve the COM Object for the logged on user
    
    $memberof = $objItem.GetEx("memberof")
    
    $objItem = 0
    
    If $memberof = 0 Then
        Dim $memberof[1] = [0]
        Return 0
    EndIf
    
    Do
        If StringInStr($memberof[$i], "|") Then
            $currgroup = StringLeft($memberof[$i], StringInStr($memberof[$i], "|") - 1)
        Else
            $currgroup = $memberof[$i]
        EndIf
        $currgroup = StringReplace($currgroup, "/", "\/")
        _ADGetGroupMemberOf($tempmemberof, $currgroup)
        For $j = 1 To $tempmemberof[0]
            $exists = 0
            $k = UBound($memberof)
            Do
                $k -= 1
                If StringInStr($memberof[$k], $tempmemberof[$j]) Then $exists = 1
            Until $exists = 1 Or $k = 0
            If $exists = 0 Then _ArrayAdd($memberof, $tempmemberof[$j] & "|" & $currgroup)
        Next
        $i += 1
    Until $i = UBound($memberof)
    
    $count = UBound($memberof)
    _ArrayInsert($memberof, 0, $count)
    
    Return 1
EndFunc;==>_ADRecursiveGetMemberOf

; _ADRecursiveGetGroupMembers
; Takes a Full DN of a group and returns a recursively searched list of members of that group (and groups that are members of the group)
; The return values are full DNs. For groups that are inherited, the return is the DN of the group, and the DN of the first group
; it was inherited from, seperated by '|'.
Func _ADRecursiveGetGroupMembers(ByRef $members, $fqdn)
    Local $objItem, $tempmembers, $i = 1
    
;$objItem = ObjGet("LDAP://" & $strHostServer & "/" & $fqdn); Retrieve the COM Object for the logged on user
    
    _ADGetGroupMembers($members, $fqdn)
    
    If $members[0] = 0 Then
        Return 0
    EndIf
    
    Do
        If StringInStr($members[$i], "|") Then
            $currgroup = StringLeft($members[$i], StringInStr($members[$i], "|") - 1)
        Else
            $currgroup = $members[$i]
        EndIf
        $currgroup = StringReplace($currgroup, "/", "\/")
        If _ADGetObjectClassFromFQDN($currgroup) = "group" Then
            _ADGetGroupMembers($tempmembers, $currgroup)
            For $j = 1 To $tempmembers[0]
                $exists = 0
                $k = UBound($members)
                Do
                    $k -= 1
                    If StringInStr($members[$k], $tempmembers[$j]) Then $exists = 1
                Until $exists = 1 Or $k = 0
                If $exists = 0 Then _ArrayAdd($members, $tempmembers[$j] & "|" & $currgroup)
            Next
        EndIf
        $i += 1
    Until $i = UBound($members)
    
    $count = UBound($members)
;_ArrayInsert($members, 0, $count)
    $members[0] = $count - 1
    
    Return 1
EndFunc;==>_ADRecursiveGetGroupMembers

; _ADGetGroupMembers
; Arguments,
; $members - Array that the result will be stored in
; $group - Group to retrieve members from
; $sort - optional, default 0 : Set to 1 to sort the array
; Returns an array to $members where $members[0] will be the number of users in the group and
; $members[1] to $members[$members[0]] are the distinguished names of the users

Func _ADGetGroupMembers(ByRef $members, $groupdn, $sort = 0)
;If _ADObjectExists($group) = 0 Then Return 0
    
    Local $oUsr, $objCommand, $groups

    $objCommand = ObjCreate("ADODB.Command")
    $objCommand.ActiveConnection = $objConnection
    $objCommand.Properties("Searchscope") = 2

    Dim $members[1]
    $i = 0

    While 1
        $rangemodifier = $i * 1000
        $range = "Range=" & $rangemodifier & "-" & $rangemodifier + 999
        $strCmdText = "<LDAP://" & $strHostServer & "/" & $groupdn & ">;;member;" & $range & ";base"
        $objCommand.CommandText = $strCmdText
        $objRecordSet = $objCommand.Execute
        $membersadd = $objRecordSet.fields(0).Value
        If $membersadd = 0 Then ExitLoop
        ReDim $members[UBound($members) + 1000]
        For $j = $rangemodifier + 1 To $rangemodifier + 1000
            $members[$j] = $membersadd[$j - $rangemodifier - 1]
        Next
        $i += 1
        $objRecordSet.Close
    WEnd

    $rangemodifier = $i * 1000
    $range = "Range=" & $rangemodifier & "-*"
    $strCmdText = "<LDAP://" & $strHostServer & "/" & $groupdn & ">;;member;" & $range & ";base"
    $objCommand.CommandText = $strCmdText
    $objRecordSet = $objCommand.Execute
    $membersadd = $objRecordSet.fields(0).Value

    ReDim $members[UBound($members) + UBound($membersadd)]

    For $j = $rangemodifier + 1 To $rangemodifier + UBound($membersadd)
        $members[$j] = $membersadd[$j - $rangemodifier - 1]
    Next

    $objRecordSet.Close
    
    $objCommand = 0
    $objRecordSet = 0
    
    $members[0] = UBound($members) - 1
    
    If $sort = 1 Then
        _ArraySort($members, 0, 1)
    EndIf
    
    Return 1
EndFunc;==>_ADGetGroupMembers

; _ADGetGroupMemberOf
Func _ADGetGroupMemberOf(ByRef $memberof, $groupdn, $sort = 0)
    Local $oUsr, $objCommand, $groups

    $objCommand = ObjCreate("ADODB.Command")
    $objCommand.ActiveConnection = $objConnection
    $objCommand.Properties("Searchscope") = 2
    
    Dim $memberof[1]
    $i = 0

    While 1
        $rangemodifier = $i * 1000
        $range = "Range=" & $rangemodifier & "-" & $rangemodifier + 999
        $strCmdText = "<LDAP://" & $strHostServer & "/" & $groupdn & ">;;memberof;" & $range & ";base"
        $objCommand.CommandText = $strCmdText
        $objRecordSet = $objCommand.Execute
        $membersadd = $objRecordSet.fields(0).Value
        If $membersadd = 0 Then ExitLoop
        ReDim $memberof[UBound($memberof) + 1000]
        For $j = $rangemodifier + 1 To $rangemodifier + 1000
            $memberof[$j] = $membersadd[$j - $rangemodifier - 1]
        Next
        $i += 1
        $objRecordSet.Close
    WEnd

    $rangemodifier = $i * 1000
    $range = "Range=" & $rangemodifier & "-*"
    $strCmdText = "<LDAP://" & $strHostServer & "/" & $groupdn & ">;;memberof;" & $range & ";base"
    $objCommand.CommandText = $strCmdText
    $objRecordSet = $objCommand.Execute
    $membersadd = $objRecordSet.fields(0).Value
    ReDim $memberof[UBound($memberof) + UBound($membersadd)]

    For $j = $rangemodifier + 1 To $rangemodifier + UBound($membersadd)
        $memberof[$j] = $membersadd[$j - $rangemodifier - 1]
    Next
    $objRecordSet.Close
    
    $objCommand = 0
    $objRecordSet = 0
    
    $memberof[0] = UBound($memberof) - 1
    
    If $sort = 1 Then
        _ArraySort($memberof, 0, 1)
    EndIf
    
    Return $memberof[0]
    
EndFunc;==>_ADGetGroupMemberOf

; _ADHasFullRights
; Take an object's SamAccountName, a user's SamAccountName
; Returns 1 if User has full rights on the object
; Returns 0 otherwise

Func _ADHasFullRights($object, $user = @UserName)
    Dim $hfr_groups
    If $user = @UserName Then
        $hfr_groups = $loggedonusergroups
    Else
        _ADGetUserGroups($hfr_groups, $user)
    EndIf

    
    $oObject = ObjGet("LDAP://" & $strHostServer & "/" & $object)
    
    If IsObj($oObject) Then
        $security = $oObject.Get("ntSecurityDescriptor")
        $dacl = $security.DiscretionaryAcl
        For $ace In $dacl
            $trusteearray = StringSplit($ace.Trustee, "\")
            $trusteegroup = $trusteearray[$trusteearray[0]]
            For $i = 0 To UBound($hfr_groups) - 1
                If StringInStr($hfr_groups[$i], "CN=" & $trusteegroup) And $ace.AccessMask = 983551 Then Return 1
            Next
        Next
    EndIf
    
    $oObject = 0
    $security = 0
    $dacl = 0
    
    Return 0
EndFunc;==>_ADHasFullRights

; _ADGroupMailEnable
; Takes a group and enables mail on that group
Func _ADGroupMailEnable($group)
    If _ADObjectExists($group) = 0 Then Return 0
    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $group & ");ADsPath;subtree"
    $objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the group, if it exists
    
    $ldap_entry = $objRecordSet.fields(0).value
    $oGroup = ObjGet($ldap_entry); Retrieve the COM Object for the object
    
    $oGroup.Put("grouptype", $ADS_GROUP_TYPE_UNIVERSAL_SECURITY)
    $oGroup.MailEnable
    $oGroup.SetInfo
    
    $oGroup = 0
    
    Return 1
EndFunc;==>_ADGroupMailEnable

; _ADUserCreateMailbox
; $user - User to add mailbox to
; $mdbstore - Mailbox storename
; $store - Information store
; $server - Email server
; $admingroup - Administrative group in Exchange
; $domain - Domain name
Func _ADUserCreateMailbox($user, $mdbstore, $store, $server, $admingroup, $domain)
    If _ADObjectExists($user) = 0 Then Return 0
    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $user & ");ADsPath;subtree"
    $objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the group, if it exists
    
    $ldap_entry = $objRecordSet.fields(0).value
    $oUser = ObjGet($ldap_entry); Retrieve the COM Object for the object
    
    If $oUser.HomeMDB <> "" Then Return 0
    
    $mailboxpath = "LDAP://CN="
    $mailboxpath = $mailboxpath & $mdbstore
    $mailboxpath = $mailboxpath & ",CN="
    $mailboxpath = $mailboxpath & $store
    $mailboxpath = $mailboxpath & ",CN=InformationStore"
    $mailboxpath = $mailboxpath & ",CN="
    $mailboxpath = $mailboxpath & $server
    $mailboxpath = $mailboxpath & ",CN=Servers,CN="
    $mailboxpath = $mailboxpath & $admingroup
    $mailboxpath = $mailboxpath & ",CN=Administrative Groups,CN=State Street,CN=Microsoft Exchange,CN=Services,CN=Configuration,"
    $mailboxpath = $mailboxpath & $domain
    
    $oUser.CreateMailbox($mailboxpath)
    $oUser.SetInfo
    
    $oUser = 0
    
    Return 1
EndFunc;==>_ADUserCreateMailbox

; _ADUserDeleteMailbox
; Deletes a user's mailbox
Func _ADUserDeleteMailbox($user)
    If _ADObjectExists($user) = 0 Then Return 0

    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $user & ");ADsPath;subtree"
    $objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the group, if it exists
    
    $ldap_entry = $objRecordSet.fields(0).value
    $oUser = ObjGet($ldap_entry); Retrieve the COM Object for the object
    
    If $oUser.HomeMDB = "" Then Return 0
    
    $oUser.DeleteMailbox
    $oUser.SetInfo
    
    $oUser = 0
    
    Return 1
EndFunc;==>_ADUserDeleteMailbox

; _ADGetObjectsInOU
; Returns an array of the objects in an OU
; $ou : The OU to retrieve from
; $filter : optional, default "name'*'". An additional LDAP filter if required.
; $searchscope : optional, default 2. 0 = base, 1 = one-level, 2 = sub-tree
; $datatoretrieve : optional, default "Name". A comma-seperated list of values to retrieve. More than one value will create
; a 2-dimensional array, array[0][0] will contain the number of items returned, which start at array[1][0]

Func _ADGetObjectsInOU(ByRef $ObjectArray, $ou, $filter = "name='*'", $searchscope = 2, $datatoretrieve = "sAMAccountName", $sortby = "sAMAccountName")
    Local $objRecordSet
    $objCommand = ObjCreate("ADODB.Command")
    $objCommand.ActiveConnection = $objConnection
    $objCommand.Properties("Page Size") = 256
    $objCommand.Properties("Searchscope") = $searchscope
    $objCommand.Properties("TimeOut") = 20
    
    $strCmdText = "<LDAP://" & $strHostServer & "/" & $ou & ">;" & $filter & ";" & $datatoretrieve & ";subtree"
    
    $objCommand.CommandText = $strCmdText
    $objRecordSet = $objCommand.Execute

    $recordcount = $objRecordSet.RecordCount
    If $recordcount = 0 Then
        $objCommand = 0
        $objRecordSet = 0
        Return 0
    EndIf
    
    If StringInStr($datatoretrieve, ",") Then

        $dtrArray = StringSplit($datatoretrieve, ",")
        
        Dim $ObjectArray[$recordcount + 1][$dtrArray[0]]
        
        $ObjectArray[0][0] = $recordcount
        $ObjectArray[0][1] = $dtrArray[0]
        
        $count = 1
        $objRecordSet.MoveFirst
        Do
            For $i = 1 To $dtrArray[0]
                $ObjectArray[$count][$i - 1] = $objRecordSet.Fields($dtrArray[$i] ).Value
            Next
            $objRecordSet.MoveNext
            $count += 1
        Until $objRecordSet.EOF
    Else
        Dim $ObjectArray[$recordcount + 1]
        $ObjectArray[0] = UBound($ObjectArray) - 1
        If $ObjectArray[0] = 0 Then
            $ObjectArray = 0
            Return 0
        Else
            $count = 1
            $objRecordSet.MoveFirst
            Do
                $ObjectArray[$count] = $objRecordSet.Fields($datatoretrieve).Value
                $objRecordSet.MoveNext
                $count += 1
            Until $objRecordSet.EOF
        EndIf
    EndIf
    
    $objCommand = 0
    $objRecordSet = 0
    
    Return 1
    
EndFunc;==>_ADGetObjectsInOU

; _ADDNToSamAccountName
; Takes a FQDN and returns the SamID of the account

Func _ADDNToSamAccountName($fqdn)
    $obj = ObjGet("LDAP://" & $strHostServer & "/" & $fqdn)
    If $obj = 0 Then
        MsgBox(262144, "", "Failed to retrieve AD object")
        Return 0
    EndIf
    
    $samname = $obj.sAMAccountName
    
    $obj = 0
    
    Return $samname
EndFunc;==>_ADDNToSamAccountName

; _ADSamAccountNameToFQDN
; Takes a SamID and returns the FQDN of the account

Func _ADSamAccountNameToFQDN($samname)
    
    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $samname & ");distinguishedName;subtree"
    $objRecordSet = $objConnection.Execute($strQuery)
    
    If $objRecordSet.RecordCount = 1 Then
        $fqdn = $objRecordSet.fields(0).value
        $objRecordSet = 0
        Return StringReplace($fqdn, "/", "\/")
    Else
        $objRecordSet = 0
        Return ""
    EndIf
EndFunc;==>_ADSamAccountNameToFQDN

; _ADDNToDisplayName
; Returns the Display Name of an FQDN
Func _ADDNToDisplayName($fqdn)
    $objItem = ObjGet("LDAP://" & $strHostServer & "/" & $fqdn)
    $name = $objItem.name
    $objItem = 0
    Return $name
EndFunc;==>_ADDNToDisplayName

; _ADCreateObject
; $objectou = OU to create the group in. Form is "sampleou=ou, sampleparent=ou, sampledomain1=dc, sampledomain2=dc, sampledomain3=dc"
; $object = Object name, form is SamAccountName without leading 'CN='
; $type = Type of object to create

Func _ADCreateObject($objectou, $object, $type)
    If _ADObjectExists($object) Then Return 0
    
    If StringLeft($object, 3) <> "CN=" Then
        $object = "CN=" & $object
    EndIf

    $ObjOU = ObjGet("LDAP://" & $strHostServer & "/" & $objectou)
    $ObjADObj = $ObjOU.Create($type, $object)
    
    $ObjADObj.Put("sAMAccountName", StringTrimLeft($object, 3))
    If $type = "Computer" Then
        $ObjADObj.Put("UserAccountControl", BitOR(0x0020, 0x1000))
    EndIf
    
    $ObjADObj.SetInfo
    
    $ObjADObj = 0
    
    Return 1
EndFunc;==>_ADCreateObject

; _ADCreateComputer
; $strComputer = Name of the computer object to create
; $computerOU = Full DN of the OU to create the computer in
; $strComputerUser = User or group that will be allowed to add the computer to the domain (SamAccountName)
Func _ADCreateComputer($strComputer, $computerOU, $strComputerUser)

    $objContainer = ObjGet("LDAP://" & $strHostServer & "/" & $computerOU)

    $objComputer = $objContainer.Create("Computer", "cn=" & $strComputer)
    $objComputer.Put("sAMAccountName", $strComputer & "$")
    $objComputer.Put("userAccountControl", BitOR($ADS_UF_PASSWD_NOTREQD, $ADS_UF_WORKSTATION_TRUST_ACCOUNT))
    $objComputer.SetInfo

    $objSecurityDescriptor = $objComputer.Get("ntSecurityDescriptor")
    $objDACL = $objSecurityDescriptor.DiscretionaryAcl

    $objACE1 = ObjCreate("AccessControlEntry")
    $objACE1.Trustee = $strComputerUser
    $objACE1.AccessMask = $ADS_RIGHT_GENERIC_READ
    $objACE1.AceFlags = 0
    $objACE1.AceType = $ADS_ACETYPE_ACCESS_ALLOWED

    $objACE2 = ObjCreate("AccessControlEntry")
    $objACE2.Trustee = $strComputerUser
    $objACE2.AccessMask = $ADS_RIGHT_DS_CONTROL_ACCESS
    $objACE2.AceFlags = 0
    $objACE2.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $objACE2.Flags = $ADS_FLAG_OBJECT_TYPE_PRESENT
    $objACE2.ObjectType = $ALLOWED_TO_AUTHENTICATE

    $objACE3 = ObjCreate("AccessControlEntry")
    $objACE3.Trustee = $strComputerUser
    $objACE3.AccessMask = $ADS_RIGHT_DS_CONTROL_ACCESS
    $objACE3.AceFlags = 0
    $objACE3.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $objACE3.Flags = $ADS_FLAG_OBJECT_TYPE_PRESENT
    $objACE3.ObjectType = $RECEIVE_AS

    $objACE4 = ObjCreate("AccessControlEntry")
    $objACE4.Trustee = $strComputerUser
    $objACE4.AccessMask = $ADS_RIGHT_DS_CONTROL_ACCESS
    $objACE4.AceFlags = 0
    $objACE4.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $objACE4.Flags = $ADS_FLAG_OBJECT_TYPE_PRESENT
    $objACE4.ObjectType = $SEND_AS

    $objACE5 = ObjCreate("AccessControlEntry")
    $objACE5.Trustee = $strComputerUser
    $objACE5.AccessMask = $ADS_RIGHT_DS_CONTROL_ACCESS
    $objACE5.AceFlags = 0
    $objACE5.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $objACE5.Flags = $ADS_FLAG_OBJECT_TYPE_PRESENT
    $objACE5.ObjectType = $USER_CHANGE_PASSWORD

    $objACE6 = ObjCreate("AccessControlEntry")
    $objACE6.Trustee = $strComputerUser
    $objACE6.AccessMask = $ADS_RIGHT_DS_CONTROL_ACCESS
    $objACE6.AceFlags = 0
    $objACE6.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $objACE6.Flags = $ADS_FLAG_OBJECT_TYPE_PRESENT
    $objACE6.ObjectType = $USER_FORCE_CHANGE_PASSWORD

    $objACE7 = ObjCreate("AccessControlEntry")
    $objACE7.Trustee = $strComputerUser
    $objACE7.AccessMask = $ADS_RIGHT_DS_WRITE_PROP
    $objACE7.AceFlags = 0
    $objACE7.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $objACE7.Flags = $ADS_FLAG_OBJECT_TYPE_PRESENT
    $objACE7.ObjectType = $USER_ACCOUNT_RESTRICTIONS

    $objACE8 = ObjCreate("AccessControlEntry")
    $objACE8.Trustee = $strComputerUser
    $objACE8.AccessMask = $ADS_RIGHT_DS_SELF
    $objACE8.AceFlags = 0
    $objACE8.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $objACE8.Flags = $ADS_FLAG_OBJECT_TYPE_PRESENT
    $objACE8.ObjectType = $VALIDATED_DNS_HOST_NAME

    $objACE9 = ObjCreate("AccessControlEntry")
    $objACE9.Trustee = $strComputerUser
    $objACE9.AccessMask = $ADS_RIGHT_DS_SELF
    $objACE9.AceFlags = 0
    $objACE9.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $objACE9.Flags = $ADS_FLAG_OBJECT_TYPE_PRESENT
    $objACE9.ObjectType = $VALIDATED_SPN

    $objDACL.AddAce($objACE1)
    $objDACL.AddAce($objACE2)
    $objDACL.AddAce($objACE3)
    $objDACL.AddAce($objACE4)
    $objDACL.AddAce($objACE5)
    $objDACL.AddAce($objACE6)
    $objDACL.AddAce($objACE7)
    $objDACL.AddAce($objACE8)
    $objDACL.AddAce($objACE9)

    $objSecurityDescriptor.DiscretionaryAcl = $objDACL
    $objComputer.Put("ntSecurityDescriptor", $objSecurityDescriptor)
    $objComputer.SetInfo

EndFunc;==>_ADCreateComputer

; _ADDeleteObject
; $object = DisplayName of object to delete. $type="user" or "group".

Func _ADDeleteObject($ou, $object, $type)
    If StringLeft($object, 3) <> "CN=" Then
        $object = "CN=" & StringReplace($object, ",", "\,")
    EndIf
    $ObjOU = ObjGet("LDAP://" & $strHostServer & "/" & $ou)
    $ObjOU.Delete($type, $object)
    $ObjOU = 0
    Return 1
EndFunc;==>_ADDeleteObject

; _ADGetObjectClass
; Returns the Class of an object. Returns 0 if the object does not exist.
Func _ADGetObjectClass($object)
    If _ADObjectExists($object) = 0 Then Return 0

    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $object & ");ADsPath;subtree"
    $objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the object
    $ldap_entry = $objRecordSet.fields(0).value
    $oObject = ObjGet($ldap_entry); Retrieve the COM Object for the object
    
    $class = $oObject.Class
    $oObject = 0
    
    Return $class
    
EndFunc;==>_ADGetObjectClass

; _ADGetObjectClassFromFQDN
; Returns the Class of an objectfrom an objects FQDN. Returns 0 if the object does not exist.
Func _ADGetObjectClassFromFQDN($object)
    $oObject = ObjGet("LDAP://" & $strHostServer & "/" & $object); Retrieve the COM Object for the object
    If IsObj($oObject) = 0 Then Return 0
    $class = $oObject.Class
    $oObject = 0
    Return $class
EndFunc;==>_ADGetObjectClassFromFQDN

; _ADGetObjectAttribute
; Retrieves the specified (single-value) attribute for the given SamAccountName
; Returns 0 if the object does not exist, the attribute does not exist for that
; object or if the value is multi-string.
; Otherwise returns the result
Func _ADGetObjectAttribute($object, $attribute)
    If _ADObjectExists($object) = 0 Then Return 0

    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $object & ");ADsPath;subtree"
    $objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the object
    $ldap_entry = $objRecordSet.fields(0).value
    $oObject = ObjGet($ldap_entry); Retrieve the COM Object for the object
    $result = $oObject.Get($attribute)
    $oObject.PurgePropertyList
    $oObject = 0
    If $result = "" Then
        Return ""
    Else
;~      Return $result
        MsgBox(0,'',$result)
    EndIf
    
EndFunc;==>_ADGetObjectAttribute

; _ADListDomainControllers
; Retrieves the names of all domain controllers in the current Domain
Func _ADListDomainControllers(ByRef $DCList)
    $objCommand = ObjCreate("ADODB.Command")
    $objCommand.ActiveConnection = $objConnection
    $objCommand.Properties("Page Size") = 1000
    $objCommand.Properties("Searchscope") = 2
    
    $objCommand.CommandText = "Select distinguishedName FROM 'LDAP://" & $strHostServer & "/ou=Domain Controllers," & $strDNSDomain & "' WHERE objectclass='computer'"
    
    $objRecordSet = $objCommand.Execute
    Dim $DCList[$objRecordSet.RecordCount + 1]
    $objRecordSet.MoveFirst
    
    Do
        $DCList[0] += 1
        
        $objCommand.CommandText = "<LDAP://" & $strHostServer & "/" & $objRecordSet.Fields("distinguishedName" ).Value & ">;;serverReferenceBL;Range=0-*;base"
        $objRecSet2 = $objCommand.Execute
        
        $objRecSet2.MoveFirst
        Do
            $temparray = $objRecSet2.Fields(0).Value
            $DCList[$DCList[0]] = $temparray[0]
            $objRecSet2.MoveNext
        Until $objRecSet2.EOF
        
        $objRecordSet.MoveNext
    Until $objRecordSet.EOF
    
    $objCommand = 0
    $objRecordSet = 0
    Return
EndFunc;==>_ADListDomainControllers

; _ADOUObjectNames
; A faster call for returning the Display Name of objects in a given OU
Func _ADOUObjectNames(ByRef $objects, $ou, $filter = 0)
    Local $i
    
    $ObjOU = ObjGet("LDAP://" & $strHostServer & "/" & $ou)

    If $filter <> 0 Then $ObjOU.Filter = $filter

    Dim $tempobjects[100000]
    
    $i = 0

    For $object In $ObjOU
        $tempobjects[$i] = $object.name
        $i += 1
    Next
    
    If $i = 0 Then
        $objects = 0
        $ObjOU = 0
        Return
    EndIf
    
    Dim $objects[$i + 1]
    $objects[0] = $i
    
    For $j = 1 To $i
        $tempstr = $tempobjects[$j - 1]
        $tempstr = StringTrimLeft($tempstr, 3)
        $objects[$j] = StringReplace($tempstr, "\,", ",")
    Next
    $ObjOU = 0
EndFunc;==>_ADOUObjectNames

; _ADGroupManagerCanModify :
; Returns 1 if the manager of the group can modify the member list, 0 if not, -1 if there is no manager assigned
; Takes full DNs to the group and user

Func _ADGroupManagerCanModify($groupdn)
    $ObjGroup = ObjGet("LDAP://" & $strHostServer & "/" & $groupdn)
    $managedBy = $ObjGroup.Get("managedBy")
    
    If $managedBy = "" Then Return -1
    
    $ObjUser = ObjGet("LDAP://" & $strHostServer & "/" & $managedBy)
    
    $arrUserDN = StringSplit($managedBy, "DC=", 1)
    $strDomain = StringTrimRight($arrUserDN[2], 1)
    $strSamAccountName = $ObjUser.Get("sAMAccountName")
    
    $objNTSecurityDescriptor = $ObjGroup.Get("ntSecurityDescriptor")
    $objDiscretionaryAcl = $objNTSecurityDescriptor.DiscretionaryAcl
    
    $blnMatch = False
    For $objAce In $objDiscretionaryAcl
        If StringLower($objAce.Trustee) = StringLower($strDomain & "\" & $strSamAccountName) And _
                $objAce.ObjectType = $Member_SchemaIDGuid And _
                $objAce.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT And _
                BitAND($objAce.AccessMask, $ADS_RIGHT_DS_WRITE_PROP) = $ADS_RIGHT_DS_WRITE_PROP Then $blnMatch = True
    Next
    
    $ObjGroup = 0
    $ObjUser = 0
    $objNTSecurityDescriptor = 0
    $objDiscretionaryAcl = 0
    
    If $blnMatch Then
        Return 1
    Else
        Return 0
    EndIf
EndFunc;==>_ADGroupManagerCanModify

; _ADSetGroupManagerCanModify - Sets the Group manager to be able to modify the member list
; Takes a group DN
; Returns
; -1 if no manager is assigned
; 0 if the manager can already modify the list
; 1 if successful


Func _ADSetGroupManagerCanModify($groupdn)
    If _ADGroupManagerCanModify($groupdn) = 1 Then Return 0
    
    $ObjGroup = ObjGet("LDAP://" & $strHostServer & "/" & $groupdn)
    $managedBy = $ObjGroup.Get("managedBy")
    
    If $managedBy = "" Then Return -1
    
    $ObjUser = ObjGet("LDAP://" & $strHostServer & "/" & $managedBy)
    
    $arrUserDN = StringSplit($managedBy, "DC=", 1)
    $strDomain = StringTrimRight($arrUserDN[2], 1)
    $strSamAccountName = $ObjUser.Get("sAMAccountName")
    
    $objNTSecurityDescriptor = $ObjGroup.Get("ntSecurityDescriptor")
    
    $objNTSecurityDescriptor.Owner = $strDomain & "\" & @UserName
    $objDiscretionaryAcl = $objNTSecurityDescriptor.DiscretionaryAcl
    
    $objAce = ObjCreate("AccessControlEntry")
    $objAce.Trustee = $strDomain & "\" & $strSamAccountName
    $objAce.AccessMask = $ADS_RIGHT_DS_WRITE_PROP
    $objAce.AceFlags = 0
    $objAce.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $objAce.Flags = $ADS_FLAG_OBJECT_TYPE_PRESENT
    $objAce.ObjectType = $Member_SchemaIDGuid
    
    $objDiscretionaryAcl.AddAce($objAce)
    $objNTSecurityDescriptor.DiscretionaryAcl = $objDiscretionaryAcl
    $ObjGroup.Put("ntSecurityDescriptor", $objNTSecurityDescriptor)
    $ObjGroup.SetInfo
    If @error = 3 Then
        MsgBox(262144, "Error", "An error occurred assigning permissions on the group.")
        $ObjGroup = 0
        $objDiscretionaryAcl = 0
        $objNTSecurityDescriptor = 0
        $objAce = 0
        Return 0
    EndIf
    $ObjGroup = 0
    $objDiscretionaryAcl = 0
    $objNTSecurityDescriptor = 0
    $objAce = 0
    Return 1
EndFunc;==>_ADSetGroupManagerCanModify

; _ADGroupAssignManager
; Takes a group DN and a User DN, assigns the user as the manager of the group

Func _ADGroupAssignManager($groupdn, $userdn)
    $ObjGroup = ObjGet("LDAP://" & $strHostServer & "/" & $groupdn)
    
    $ObjGroup.Put("managedBy", $userdn)
    $ObjGroup.SetInfo
    $ObjGroup = 0
    Return 1
EndFunc;==>_ADGroupAssignManager

; _ADGroupRemoveManager
; Takes a group DN and deletes the group's manager
; arg $option -- 0 (default) removes the manager; 1 only removes manager's modify permission

Func _ADGroupRemoveManager($groupdn, $option = 0)
    $ObjGroup = ObjGet("LDAP://" & $strHostServer & "/" & $groupdn)
    
    $managedBy = $ObjGroup.Get("managedBy")
    
    If $managedBy = "" Then Return -1
    
    $ObjUser = ObjGet("LDAP://" & $strHostServer & "/" & $managedBy)
    
    $arrUserDN = StringSplit($managedBy, "DC=", 1)
    $strDomain = StringTrimRight($arrUserDN[2], 1)
    $strSamAccountName = $ObjUser.Get("sAMAccountName")
    
    $objNTSecurityDescriptor = $ObjGroup.Get("ntSecurityDescriptor")
    
    $objNTSecurityDescriptor.Owner = $strDomain & "\" & @UserName
    $objDiscretionaryAcl = $objNTSecurityDescriptor.DiscretionaryAcl
    $objTempAcl = ObjCreate("AccessControlList")
    
    $blnMatch = False
    For $objAce In $objDiscretionaryAcl
        If StringLower($objAce.Trustee) = StringLower($strDomain & "\" & $strSamAccountName) And _
                $objAce.ObjectType = $Member_SchemaIDGuid And _
                $objAce.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT And _
                $objAce.AccessMask = $ADS_RIGHT_DS_WRITE_PROP Then _
                $objDiscretionaryAcl.RemoveAce($objAce)
    Next
    
    $objNTSecurityDescriptor.DiscretionaryAcl = $objDiscretionaryAcl
    $ObjGroup.Put("ntSecurityDescriptor", $objNTSecurityDescriptor)
    If Not $option Then $ObjGroup.PutEx(1, "managedBy", 0)
    $ObjGroup.SetInfo
    
    $ObjGroup = 0
    $ObjUser = 0
    $objNTSecurityDescriptor = 0
    $objDiscretionaryAcl = 0
    
EndFunc;==>_ADGroupRemoveManager

; _ADEnableAccount
; Takes a DN of an object and enables it if the user has permissions
; Returns 1 if successful, @error otherwise

Func _ADEnableAccount($fqdn)
    $objAccount = ObjGet("LDAP://" & $strHostServer & "/" & $fqdn)
    
    $objAccount.AccountDisabled = False
    $objAccount.SetInfo
    $loc_error = @error
    $objAccount = 0
    If $loc_error = 0 Then
        Return 1
    Else
        Return $loc_error
    EndIf
EndFunc;==>_ADEnableAccount

; _ADDisableAccount
; Takes a DN of an object and disables it if the user has permissions
; Returns 1 if successful, @error otherwise

Func _ADDisableAccount($fqdn)
    $objAccount = ObjGet("LDAP://" & $strHostServer & "/" & $fqdn)
    
    $intUAC = $objAccount.Get("userAccountControl")
    
    $objAccount.Put("userAccountControl", BitOR($intUAC, $ADS_UF_ACCOUNTDISABLE))
    $objAccount.SetInfo
    $loc_error = @error
    $objAccount = 0
    If $loc_error = 0 Then
        Return 1
    Else
        Return $loc_error
    EndIf
EndFunc;==>_ADDisableAccount

; _ADGetLastLoginDate
; Takes a SamAccountName of a user account and returns the .lastlogin information for the current DC
Func _ADGetLastLoginDate($user)
    If _ADObjectExists($user) = 0 Then Return 0

    $strQuery = "<LDAP://" & $strHostServer & "/" & $strDNSDomain & ">;(sAMAccountName=" & $user & ");ADsPath;subtree"
    $objRecordSet = $objConnection.Execute($strQuery); Retrieve the FQDN for the object
    $ldap_entry = $objRecordSet.fields(0).value
    $oObject = ObjGet($ldap_entry); Retrieve the COM Object for the object
    $result = $oObject.LastLogin
    $oObject.PurgePropertyList
    
    If $result = "" Then
        Return ""
    Else
        Return $result
    EndIf
EndFunc;==>_ADGetLastLoginDate

; _ADAddAccountToMailboxRights
; Takes $mailbox as FQDN and $accountsam as "domain\username"
; Adds Full mailbox rights and 'send as' permission for $accountsam on $mailbox.
; Returns 2 if account already has rights, otherwise returns @error (should be 0 for success, 1 for failure)
Func _ADAddAccountToMailboxRights($mailbox, $accountsam)
    $obj_mailbox = ObjGet("LDAP://" & $strHostServer & "/" & $mailbox)
    If Not IsObj($obj_mailbox) Then
;MsgBox(0, "Error", "Mailbox was not a FQDN or was not found.")
        SetError(3)
        Return
    EndIf
    $obj_mailboxsecurity = $obj_mailbox.MailboxRights
    $mailbox_dacl = $obj_mailboxsecurity.DiscretionaryAcl
    
    For $ace In $mailbox_dacl
        If $ace.trustee = $accountsam Then
;MsgBox(0, "", "User already has full rights to mailbox")
            SetError(2)
            Return @error
        EndIf
    Next
    
    $obj_ace1 = ObjCreate("AccessControlEntry")
    $obj_ace1.Trustee = $accountsam
    $obj_ace1.AccessMask = 1
    $obj_ace1.AceType = 0
    $obj_ace1.AceFlags = 2
    $obj_ace1.ObjectType = 0
    $obj_ace1.InheritedObjectType = 0
    $obj_ace1.Flags = 0
    
    $mailbox_dacl.AddAce($obj_ace1)
    
    $obj_mailboxsecurity.DiscretionaryAcl = $mailbox_dacl
    $obj_mailbox.MailboxRights = $obj_mailboxsecurity
    
    $obj_ntsecurity = $obj_mailbox.Get("ntSecurityDescriptor")
    $ntsecurity_dacl = $obj_ntsecurity.DiscretionaryAcl
    
    $obj_ace2 = ObjCreate("AccessControlEntry")
    $obj_ace2.Trustee = $accountsam
    $obj_ace2.AccessMask = $ADS_RIGHT_DS_CONTROL_ACCESS
    $obj_ace2.AceFlags = 0
    $obj_ace2.AceType = $ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
    $obj_ace2.Flags = 1;$ADS_FLAG_OBJECT_TYPE_PRESENT
    $obj_ace2.ObjectType = $SEND_AS
    
    $ntsecurity_dacl.AddAce($obj_ace2)
    
    $obj_ntsecurity.DiscretionaryAcl = $ntsecurity_dacl
    $obj_mailbox.Put("ntSecurityDescriptor", $obj_ntsecurity)
    $obj_mailbox.SetOption($ADS_OPTION_SECURITY_MASK, $ADS_SECURITY_INFO_DACL)
    $obj_mailbox.SetInfo
    
    Return @error
EndFunc;==>_ADAddAccountToMailboxRights

Func _ADRemoveMailboxRights($mailbox, $accountsam)
    $obj_mailbox = ObjGet("LDAP://" & $strHostServer & "/" & $mailbox)
    If Not IsObj($obj_mailbox) Then
;MsgBox(0, "Error", "Mailbox was not a FQDN or was not found.")
        SetError(3)
        Return
    EndIf
    $obj_mailboxsecurity = $obj_mailbox.MailboxRights
    $mailbox_dacl = $obj_mailboxsecurity.DiscretionaryAcl
    
    For $ace In $mailbox_dacl
        If $ace.trustee = $accountsam Then
            $mailbox_dacl.RemoveAce($ace)
        EndIf
    Next
    
    $obj_mailboxsecurity.DiscretionaryAcl = $mailbox_dacl
    $obj_mailbox.MailboxRights = $obj_mailboxsecurity
    
    $obj_ntsecurity = $obj_mailbox.Get("ntSecurityDescriptor")
    $ntsecurity_dacl = $obj_ntsecurity.DiscretionaryAcl
    
    For $ace In $ntsecurity_dacl
        If $ace.trustee = $accountsam Then
            $ntsecurity_dacl.RemoveAce($ace)
        EndIf
    Next
    
    $obj_ntsecurity.DiscretionaryAcl = $ntsecurity_dacl
    $obj_mailbox.Put("ntSecurityDescriptor", $obj_ntsecurity)
    $obj_mailbox.SetOption($ADS_OPTION_SECURITY_MASK, $ADS_SECURITY_INFO_DACL)
    $obj_mailbox.SetInfo
    Return @error
    
EndFunc;==>_ADRemoveMailboxRights

; _ADGetMailboxPerms
; Takes a mailbox and an array.
; Returns all SamIDs for non-inherited ACEs on the mailbox (stored in the specified array as SamIds)
; Can be filtered on an accessmask value (default = 1, full permissions)
Func _ADGetMailboxPerms($mailbox, ByRef $outputarray, $filter = 1)
    $obj_mailbox = ObjGet("LDAP://" & $strHostServer & "/" & $mailbox)
    If Not IsObj($obj_mailbox) Then
;MsgBox(0, "Error", "Mailbox was not a FQDN or was not found.")
        SetError(3)
        Return
    EndIf
    $obj_mailboxsecurity = $obj_mailbox.MailboxRights
    $mailbox_dacl = $obj_mailboxsecurity.DiscretionaryAcl
    
    For $ace In $mailbox_dacl
        If $ace.AceFlags = 2 Then
            If BitAND($ace.AccessMask, 1) = 1 And $ace.AceType = 0 Then
                _ArrayAdd($outputarray, $ace.Trustee)
            EndIf
        EndIf
    Next
EndFunc;==>_ADGetMailboxPerms
Link to comment
Share on other sites

  • 2 months later...

Would you guys PUHLEEEZE use codebox tags vice code for long stuff like that? :)

The .LockoutTime property is a 64 bit time stamp just like some other time properties. It represents a count of 100nsec intervals since 00:00am 01 January, 1601.

I posted one way to convert it (for "LastLogon") in this topic: Active Directory - Pull All Users in OU "Last Logon" information and existence of a user

:)

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

Hi

My Solution for LastLogonTimeStamp

$attribute = "lastLogonTimeStamp"

$LastLogonTimeStamp = _ADGetObjectAttribute($UserName, $attribute)

$intLastLogonTime = $LastLogonTimeStamp.HighPart * (2 ^ 32) + $LastLogonTimeStamp.LowPart

$intLastLogonTime = $intLastLogonTime / (60 * 10000000)

$intLastLogonTime = $intLastLogonTime / 1440

$DayLastLogonTime = _DateAdd ( "d" , Int($intLastLogonTime) , "1601/01/01")

$DayLastLogonTime = StringMid($DayLastLogonTime, 9, 2) & "/" & StringMid($DayLastLogonTime, 6, 2) & "/" & StringMid($DayLastLogonTime, 1, 4)

$HrsLastLogonTime = converti_heure($intLastLogonTime)

$DateLastLoginFR = $DayLastLogonTime & " " & $HrsLastLogonTime

Func converti_heure ($valeur)

$valeur = $valeur - Int($valeur)

$heure = $valeur * 24

$min = $heure - Int($heure)

$min = $min * 60

$sec = $min - Int($min)

$sec = $sec * 60

$heure = Int($heure)

If $heure < 10 Then

$Heure = "0" & $Heure

EndIf

$min = Int($min)

If $min < 10 Then

$min = "0" & $min

EndIf

$sec = Int($sec)

If $sec < 10 Then

$sec = "0" & $sec

EndIf

$resultat = $heure & ":"& $min & ":" & $sec

Return $resultat

EndFunc

:) Thanks Julien for This Function

Yop

Link to comment
Share on other sites

  • 8 months later...

The last logon date you get using this method isn't always the "true" last logon date. The logon date isn't replicated between all Domain Controllers immediately. Please see this post. To get the "real" last logon date you have to query all DCs and take the most current date. I have posted a script returning the "true" last logon date on this forum. I'm on vacation so it will take some time for me to find my post - or you could have a look yourself.

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2022-02-19 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki
Task Scheduler (NEW 2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki

Standard UDFs:
Excel - Example Scripts - Wiki
Word - Wiki

Tutorials:
ADO - Wiki
WebDriver - Wiki

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...