Ok, here is the latest. It includes all of Christophe's and my features. For some reason, I couldn't get Christophe's version to work for me so I just incorporated his features into mine.

Code:

; 
;Function:
; fnLDAPQuery()
;
;Authors:
; Christopher Shilt (christopher.shilt@relizon.com)
; Christophe Melin (christophe.melin@cus-strasbourg.net)
;
;Version:
; 1.0 (May 12, 2005)
;
;Version History:
;
;Action:
; Uses ADODB to retrieve information from Active Directory.
;
;Syntax:
; fnLDAPQuery(WHAT, FROM, Optional FILTER, Optional ORDER BY, Optional SCOPE,
; Optional USER, Optional PASSWORD)
;
;Parameters:
; WHAT : Required. Attribute (or array of attributes) to retrieve For
; each object. If you specify *, the query retrieves only the
; ADsPath of each object.
;
; FROM : Required. Specifies the ADsPath of the base of the search.
; For example, the ADsPath of the Users container in an Active
; Directory domain might be 'LDAP://CN=Users,DC=Fabrikam,DC=COM'.
;
; FILTER : Optional. Specifies the query filter. You can also add wildcards
; and conditions to an LDAP search filter. The following examples
; show substrings that can be used to search the directory.
;
; Get all users:
; "(objectClass=Users)"
; Get all users with a common name equal to "bob":
; "(&(objectClass=Users)(cn=bob))"
; Get all users with a common name beginning with "bob":
; "(&(objectClass=Users)(cn=bob*))"
; Get all users containing "bob" somewhere in the common name:
; "(&(objectClass=Users)(cn=*bob*))"
; Get all users with "bob" as the common name and "dull" as the surname:
; "(&(objectClass=Users)(cn=bob)(sn=dull))"
;
; ORDER BY : Optional. An optional statement that generates a server-side
; sort. Active Directory supports the sort control, but it can
; impact server performance if the results set is large. Active
; Directory supports only a single sort key. You can use the
; optional ASC and DESC keywords to specify ascending or descending
; sort order; the default is ascending.
;
; Order by surname with a ascending sort order:
; "sn"
; Order by surname with a descending sort order:
; "sn DESC"
;
; SCOPE : Optional. Specifies the scope of a directory search.
;
; BASE
; Limits the search to the base object. The result contains,
; at most, one object.
; ONELEVEL
; Searches one level of the immediate children, excluding
; the base object.
; SUBTREE (DEFAULT)
; Searches the whole subtree, including all the children and
; the base object itself.
;
; USER : Optional. Specifies the user to connect to the directory.
;
; PASSWORD : Optional. Specifies the password to connect to the directory.
;
;Remarks:
;
;
;Returns:
;
; An array of attributes entered in the order specified in the WHAT parameter. If
; only one attribute is specified each element in the array will contain the result
; of the query. If an array of attributes is specified in the WHAT parameter Each
; element in the array will contain an array of the results of the query.
;
; Sets the value of @ERROR based on success/failure.
;
;Dependencies:
;
;
;Example:
;
; ; == Return the Name and AdsPath of all users ===================
; $aAttributes = "Name", "AdsPath"
; $sADsPath = "LDAP://"+GetObject("LDAP://rootDSE").Get("defaultNamingContext")
; $strFilter = "(&(objectClass=User)(Name=*))"
;
; $aResults = fnLDAPQuery($aAttributes,$sADsPath,$strFilter,"Name")
; @ERROR " | " @SERROR ?
;
; For Each $Result in $aResults
; If VarType($Result)>8192
; For Each $R in $Result
; $R ?
; Next
; Else
; $Result ?
; EndIf
; Next
;
; ; == Return the Name, AdsPath and members of all groups =========
; $aAttributes = "Name", "AdsPath", "member"
; $sADsPath = "LDAP://"+GetObject("LDAP://rootDSE").Get("defaultNamingContext")
; $strFilter = "(&(objectClass=group)(Name=relizon_t*))"
;
; $aResults = fnLDAPQuery($aAttributes,$sADsPath,$strFilter)
; @ERROR " | " @SERROR ?
;
; For Each $Result in $aResults
; "=============================" ?
; If VarType($Result)>8192
; For Each $R in $Result
; If VarType($R)>8192
; for each $rr in $r
; " " $rr ?
; next
; else
; $R ?
; endif
; Next
; Else
; $Result ?
; EndIf
; Next
;
;
Function fnLDAPQuery($What,$From,Optional $Filter,Optional $OrderBy,Optional $Scope,Optional $User,Optional $Pswd)
Dim $oCon,$oCMD,$oRS,$sQ,$sF,$sGV,$R,$vP,$aR[0],$nul

If $Scope <> "base" AND $Scope <> "onelevel" AND $Scope <> "subtree" $Scope = "subtree" EndIf

$sQ = "<"+$From+">;"+$Filter+";"+Iif(VarType($What)>8192,Join($What,','),$What)+";"+$Scope

If VarType($What)>8192
For Each $sF in $What $sGV=$sGV+'$'+'oRS.Fields("'+$sF+'").Value,' Next
$sGV=Substr($sGV,1,Len($sGV)-1)
Else
$sGV='$'+'oRS.Fields("'+$What+'").Value'
EndIf

$oCon=CreateObject("ADODB.Connection")
$oCon.Provider = "ADsDSOObject"
$oCon.Properties("Encrypt Password").Value=1
$oCon.Properties("ADSI Flag").Value=1
If $User AND $Pswd
$oCon.Properties("User ID").Value=$User
$oCon.Properties("Password").Value=$Pswd
EndIf
$oCon.Open("Active Directory Provider")

$oCMD=CreateObject("ADODB.Command")
$oCMD.ActiveConnection=$oCon
$oCMD.CommandText=$sQ
$oCMD.Properties("Page Size").Value=1000
$oCMD.Properties("Timeout").Value=30
$oCMD.Properties("Cache Results").Value=0

If $OrderBy="distinguishedName"
$oRS = CreateObject("ADODB.Recordset")
$oRS.CursorLocation=3
$oRS.Sort=$OrderBy
$oRS.Open($sQ,$oCon,0,1,1)
Else
If $OrderBy
$oCMD.Properties("Sort On").Value=$OrderBy
EndIf
$oRS = $oCMD.Execute
EndIf
If @ERROR Exit @ERROR EndIf
If $oRS.BOF AND $oRS.EOF Exit @ERROR EndIf

Do
$nul=Execute('$'+'vP='+$sGV)
$aR[$R]=$vP
$oRS.MoveNext
$R=$R+1
ReDim Preserve $aR[$R]
Until $oRS.EOF
ReDim Preserve $aR[$R-1]
$fnLDAPQuery=$aR
EndFunction