banner.gif (5982 bytes)

mslogo.gif (666 bytes)

router.gif (3874 bytes)
rtk.gif (9440 bytes)
The ADSI Resource Tool Kit is a collection of ADSI components that may be useful to solve difficult tasks, or to resolve tasks that are impossible in the current implementation of ADSI.

These components are unsupported and should be treated as samples. You may ,however, use and redistributed them.

THE ADSI RESOURCE KIT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.


ADSI Resource Kit Components

  • ADsFactory
    Allows you to write a script on the Internet Explorer client script environment.
  • ADsSecurity and ADsSID
    Allows you to retrieve and modify a security descriptor on Exchange, File, FileShare, or Registry.
  • ADsError
    Allows you to display both standard Win32 errors and ADSI extended errors.

 


 

IADsFactory - Creating ADSI Objects in Internet Explorer Scripting

Since the VB GetObject function is not allowed in Internet Explorer clients because of security reasons, IADsFactory is designed to solve this problem.  The component allows you to create ADSI objects in Internet Explorer clients. You must, however, install this component on every client. You may have to create a signed CAB file which includes this component.

Location: /ResourceKit/ADsFactory.dll

Installation: regsvr32 adsfactory.dll

Requirement: ADSI 2.5 must be installed first.

IADsFactory
Interface Specification

interface IADsFactory : IDispatch
{
  HRESULT GetObject(BSTR bstrADsPath, [out,retval] IDispatch **pDisp);
  HRESULT OpenDSObject(BSTR bstrADsPath, BSTR bstrUser, BSTR bstrPassword, LONG lFlag,   [out,retval] IDispatch **pDisp );
};

Program ID: ADsFactory

HRESULT IADsFactory::GetObject( BSTR bstrADsPath, IDispatch **pDisp )
This is similar to GetObject in Visual Basic, or ADsGetObject in Visual C++.

Example:

<SCRIPT language="VBScript">

Dim oGetObj
Dim oCont

Set oGetObj = CreateObject("ADsFactory")
Set oCont = oGetObj.GetObject("WinNT://ARCADIABAY")

document.write "Container name = " & oCont.Name & " <P>"
document.write "Container path = " & oCont.ADsPath & " <P>&nbsp;<P>"

for each obj in oCont
  document.write "Object name = " & obj.Name & " <P>"
  document.write "Object path = " & obj.ADsPath & " <P>
Next

Set oGetObj = Nothing
Set oCont = Nothing

</SCRIPT>

 

HRESULT IADsFactory::OpenDSObject( BSTR bstrADsPath, BSTR bstrUser, BSTR bstrPassword, LONG lFlag, IDispatch **pDisp )
This is similar to IADsOpenDSObject::OpenDSObject or ADsOpenObject in Visual C++.

Example:

<SCRIPT language="VBScript">

Set dso = CreateObject("ADsFactory")
Set oProv = dso.OpenDSObject("LDAP://arcadiabay.com", "ARCADIABAY\JSmith", "password", 1)
document.write "Provider path = " & oProv.ADsPath & " <P>&nbsp;<P>"
Set dso = Nothing
Set oProv = Nothing

</SCRIPT>

 

IADsSecurity and IADsSID - Setting Permissions on File, Registry, Exchange

Location: /ResourceKit/ADsSecurity.dll

Platforms: Windows NT 4.0, Windows 2000

Installation: regsvr32 adssecurity.dll

Requirement: ADSI 2.5 must be installed first.


IADsSecurity  

interface IADsSecurity
{
HRESULT GetSecurityDescriptor( [in, optional] VARIANT varPath, [out, retval] VARIANT *pVariant);
HRESULT SetSecurityDescriptor([in] VARIANT varData, [in, optional] VARIANT varPath);
HRESULT GetSID([in] VARIANT varPath, [out, retval] VARIANT *pRet);
HRESULT GetSecurityDescriptorAs( long lFormat, [optional][in]  VARIANT varPath,[retval,out] VARIANT *pRet);
}
 

Program ID: ADsSecurity
Include: ADsSecurity.h
CLISID & IIDs : ADsSecurity_i.c


HRESULT GetSecurityDescriptor( [in, optional] VARIANT varPath, [out, retval] VARIANT *pVariant);
Getting Security Descriptor (IADsSecurityDescriptor) for a given path. Valid Paths are Exchange LDAP Path, Active Directory LDAP Path, Registry Path, File System Path, IFile and IADs. More detailed information below. If no path is specified, the IADsSecurity creates a new security descriptor.  

HRESULT SetSecurityDescriptor([in] VARIANT varData, [in, optional] VARIANT varPath);
Setting the security descriptor (IADsSecurityDescriptor) to a specified path. Valid paths are the same as in GetSecurityDescriptor. If no path is specified, IADsSecurity uses the path specified in GetSecurityDescriptor.

HRESULT GetSID([in] VARIANT varPath, [out, retval] VARIANT *pRet);
Get the IADsSID pointer for a given path. Valid Paths are WinNT, LDAP (Active Directory and Exchange) ADsPaths. 

HRESULT GetSecurityDescriptorAs( long lFormat, [optional][in]  VARIANT varPath,[retval,out] VARIANT *pRet);
Similar to GetSecurityDescriptor. Only you can also specify the format you want to get back. 
The valid lFormat are:

ADS_SD_RAW -  Returns as a variant array of bytes (VT_ARRAY | VT_I1 )

ADS_SD_HEXSTRING - Return as a security descriptor hex string. Example:
FFF36040000FFFFFFFF37040000FFFFFFFF38040000FFFFFFFF39040000FF0

ADS_SD_SDDL (Windows 2000 Only)  - Returns as a security descriptor description languange.  Example: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU)

ADS_SD_IID - Return the IADsSecurityDescritor 


The primary objective of this interface is to give you one common interface which allows you to retrieve and modify ADSI's IADsSecurityDescriptor on a given resource.  A resource can be either NTFS File, Registry, Exchange Directory, or Active Directory. 

It gives you the following benefits:

  • You don't need to deal with many different forms of security descriptor anymore (such as raw SD, Exchange's Hex String, SDDL, Variant Array of VT_I1, and so on).
  • You don't need to remember the security descriptor attribute name, such as "ntSecurityDescriptor" for Active Directory, or "NT-Security-Descriptor" for Exchange. 
  • You don't need to know APIs for retrieving and setting the security descriptor for a given resource (that is, GetFileSecurity, RegGetKeySecurity, NetSharexxx, and so on ). 

All you need to know is how to use ADSI's IADsSecurityDescriptor, IADsAccessControlList, IADsAccessControlEntry whether you need to manipulate Exchange's, File's, File Share's and other's security descriptor. The same programming model, same security descriptor object.

Setting file permission examples

FILE://[\\serverName\]FilePath

'----Visual Basic----

Dim sec As New ADsSecurity
Dim sd As IADsSecurityDescriptor
Dim dacl As IADsAccessControlList
Dim ace As IADsAccessControlEntry
Dim newAce As New AccessControlEntry

Set sd = sec.GetSecurityDescriptor("FILE://\\srv01\public")
Set dacl = sd.DiscretionaryAcl

'----Show the ACEs in the DACL----
For Each ace In dacl
  Debug.Print ace.Trustee
  Debug.Print ace.AccessMask
  Debug.Print ace.AceType
Next

Debug.Print dacl.AceCount

'----Add a new ace for Jsmith----
newAce.Trustee = "ARCADIABAY\jsmith"
newAce.AccessMask = ADS_RIGHT_GENERIC_READ Or ADS_RIGHT_GENERIC_EXECUTE
newAce.AceType = ADS_ACETYPE_ACCESS_ALLOWED

dacl.AddAce newAce
sd.DiscretionaryAcl = dacl
sec.SetSecurityDescriptor sd

'----VBS----

Const ADS_RIGHT_GENERIC_READ = &H80000000
Const ADS_RIGHT_GENERIC_EXECUTE = &H20000000
Const ADS_ACETYPE_ACCESS_ALLOWED = 0

Set sec = CreateObject("ADsSecurity")
Set sd = sec.GetSecurityDescriptor("FILE://c:\public\specs")
Set dacl = sd.DiscretionaryAcl

'-- Show the ACEs in the DACL ----
For Each ace In dacl
   wscript.echo ace.Trustee
   wscript.echo ace.AccessMask
   wscript.echo ace.AceType
Next

'--- Add a new ACE so that JSmith can read/execute this file
Set ace = CreateObject("AccessControlEntry")
ace.Trustee = "ARCADIABAY\jsmith"
ace.AccessMask = ADS_RIGHT_GENERIC_READ Or ADS_RIGHT_GENERIC_EXECUTE
ace.AceType = ADS_ACETYPE_ACCESS_ALLOWED

dacl.AddAce ace
sd.DiscretionaryAcl = dacl
sec.SetSecurityDescriptor sd

'----File System Object----
Const ADS_RIGHT_GENERIC_READ = &H80000000
Const ADS_RIGHT_GENERIC_EXECUTE = &H20000000
Const ADS_ACETYPE_ACCESS_ALLOWED = 0

Set sec = CreateObject("ADsSecurity")

‘Getting File System Security Descriptor from FSO
Set fso = CreateObject("Scripting.FileSystemObject")
Set fs = fso.GetFile(“c:\public\specs\movetree.doc”)

Set sd = sec.GetSecurityDescriptor(fs)
Set dacl = sd.DiscretionaryAcl

'----Show the ACEs in the DACL----
For Each ace In dacl
   wscript.echo ace.Trustee
  
wscript.echo ace.AccessMask
   wscript.echo ace.AceType
Next

'----Add a new ACE so that JSmith can read and execute this file----

Set ace = CreateObject("AccessControlEntry")
ace.Trustee = "ARCADIABAY\jsmith"
ace.AccessMask = ADS_RIGHT_GENERIC_READ Or ADS_RIGHT_GENERIC_EXECUTE
ace.AceType = ADS_ACETYPE_ACCESS_ALLOWED

dacl.AddAce ace
sd.DiscretionaryAcl = dacl
sec.SetSecurityDescriptor sd

Setting Registry Permission Examples

RGY://[serverName]/RegistryLocation

----Modifying the Local Registry Key's ACL----

Const ADS_RIGHTS_RGY_KEY_READ = &H20019

Set sec = CreateObject("ADsSecurity")
Set sd = sec.GetSecurityDescriptor("RGY://HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\MyKey")

'Displaying the ACE in the DACL --- it's the same you way you display aces for File, FileShare, Registry, Exchange, and Active Directory's ACL.

Set dacl = sd.DiscretionaryAcl

For Each ace In dacl
   Debug.Print ace.Trustee
   Debug.Print ace.AccessMask
   Debug.Print ace.AceType
Next

Debug.Print dacl.AceCount

 '----Allow James Smith to read this registry key:

Set newAce = CreateObject("AccessControlEntry")
newAce.Trustee = "ARCADIABAY\jsmith"
newAce.AccessMask = ADS_RIGHTS_RGY_KEY_READ
newAce.AceType = ADS_ACETYPE_ACCESS_ALLOWED

dacl.AddAce newAce
sd.DiscretionaryAcl = dacl
sec.SetSecurityDescriptor sd


'----You can also connect to a remote registry----
Set sd = sec.GetSecurityDescriptor("RGY://mycomp03/HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\MyKey"

 

IADsSID

IADsSID allows you to retrieve a different type of security principal format. It’s useful for converting and searching a security principal.

 

Interface Definition:
   

interface IADsSID : IDispatch

{

        HRESULT SetAs([in] long lFormat, [in] VARIANT varData);

        HRESULT GetAs([in] long lFormat, [out, retval] VARIANT *pVar);

};

Program ID: ADsSID
Include: ADsSecurity.h
CLISID & IIDs : ADsSecurity_i.c

 

HRESULT GetAs([in] long lFormat, [out, retval] VARIANT *pVar)

Get the SID as one of the supported formats. The return value depends on the specified format.

Parameters:

[in] long lFormat

lFormat it can be one of the following:

  • ADS_SID_RAW ( VT_ARRAY | VT_U1 )

  • ADS_SID_HEXSTRING (VT_BSTR), for example, 010500000000000515000000093A2A24358A021ADBEB0C508E040000

  • ADS_SID_SAM (VT_BSTR ), for example, ARCADIABAY\jsmith

  • ADS_SID_UPN (VT_BSTR), for example, jsmith@arcadiabay.com ( Windows 2000 Only )

  • ADS_SID_SDDL (VT_BSTR), for example, S-1-5-21-606747145-436374069-1343024091-1166  (Windows 2000 Only)

  • ADS_SID_WINNT_PATH (VT_BSTR), for example, WinNT://ARCADIABAY/jsmith

  • ADS_SID_ACTIVE_DIRECTORY_PATH (VT_BSTR), for example, LDAP://CN=John Smith,OU=NTDSys,DC=ArcadiaBay,DC=com

  • ADS_SID_SID_BINDING (VT_BSTR), for example, GC://<SID=010500000000000515000000093A2A24358A021ADBEB0C508E040000>

 

[out, retval] VARIANT *pVar

Return value, its variant type depends on the specified format.

Exchange Mailbox Creation Sample

'--------------------------------------------------------
' Security object for SD manipulation
'(REQUIRED ADSI TOOL KIT - REGSVR32 ADSSECURITY.DLL )
'---------------------------------------------------------  

Dim sid As New ADsSID  'You can also use -- Set sid = CreateObject("ADsSID") for late binding
Dim sec As New ADsSecurity 'You can also use -- Set sec = CreateObject("ADsSecurity") for late binding

'-------------------------------------
'- The rest uses ADSI Interfaces
'-------------------------------------

Dim sd As IADsSecurityDescriptor
Dim dacl As IADsAccessControlList
Dim ace As New AccessControlEntry

'----------------------------------------------------------------------------
'--- If you don't include the ADSI 2.5 Security Type Library as you reference
'--- you must manually declare the following constants
'-----------------------------------------------------------------------------
Const ADS_SID_HEXSTRING = 1
Const ADS_SID_WINNT_PATH = 5
Const ADS_RIGHT_EXCH_MODIFY_USER_ATT = &H2
Const ADS_RIGHT_EXCH_MAIL_SEND_AS = &H8
Const ADS_RIGHT_EXCH_MAIL_RECEIVE_AS = &H10

'-------------------------------------------------------
'-----CREATING A MAILBOX  ----------------------
'--------------------------------------------------------

'---- Server, Org and Site information

server = "jsmith11"
Org = "ARCADIABAY"
Site = "INDEPENDENCE"
domain = "INDEPENDENCE"

userName = "jsmith"
password = "passwordHere"

'--- MailBox Parameters -----

strDisplayName = "John Smith"
strFirstName = "John"
strLastName = "Smith"

strAlias = userName
strMTA = "cn=Microsoft MTA,cn=" & server & ",cn=Servers,cn=Configuration,ou=" & Site & ",o=" & Org
strMDB = "cn=Microsoft Private MDB,cn=" & server & ",cn=Servers,cn=Configuration,ou=" & Site & ",o=" & Org

strSMTPAddr = "jsmith@microsoft.com"

'------ Creating an NT user to be associated with the mail box
Set dom = GetObject("WinNT://" & domain)
Set usr = dom.Create("user", userName)
usr.SetInfo
usr.SetPassword password  

'--- Build Recipient container's adsPath that looks like this: LDAP://myserver/CN=Recipients, OU=Site, O=Org

ADsPath = "LDAP://" + server
ADsPath = ADsPath + "/cn=Recipients,OU="
ADsPath = ADsPath + Site
ADsPath = ADsPath + ",O="
ADsPath = ADsPath + Org  

Set objCont = GetObject(ADsPath)

'Create a new MailBox
Set mailBox = objCont.Create("organizationalPerson", "cn=" & strAlias)
mailBox.Put "mailPreferenceOption", 0
mailBox.Put "givenName", strFirstName
mailBox.Put "sn", strLastName
mailBox.Put "cn", strDisplayName
mailBox.Put "uid", strAlias
mailBox.Put "Home-MTA", strMTA
mailBox.Put "Home-MDB", strMDB
mailBox.Put "mail", strSMTPAddr
mailBox.Put "MAPI-Recipient", True
mailBox.Put "rfc822Mailbox", strSMTPAddr

'--------------------------------------------------------
'  ASSOCIATING TO NT PRIMARY ACCOUNT
' (REQUIRED ADSI TOOL KIT - REGSVR32 ADSSECURITY.DLL )
'---------------------------------------------------------

sid.SetAs ADS_SID_WINNT_PATH, "WinNT://" & domain & "/" & strAlias & ",user"
sidHex = sid.GetAs(ADS_SID_HEXSTRING)
mailBox.Put "Assoc-NT-Account", sidHex

' Commit the property cache to the directory service
mailBox.SetInfo

'-------------------------------------------------
'--- SET THE MAIL BOX SECURITY ------------------

'-- To allow the user to modify user attribute, send mail and receive mail
'-------------------------------------------------
Set sd = sec.GetSecurityDescriptor(mailBox.ADsPath)
Set dacl = sd.DiscretionaryAcl
ace.Trustee = domain & "\" & strAlias
ace.AccessMask = ADS_RIGHT_EXCH_MODIFY_USER_ATT Or ADS_RIGHT_EXCH_MAIL_SEND_AS Or ADS_RIGHT_EXCH_MAIL_RECEIVE_AS
ace.AceType = ADS_ACETYPE_ACCESS_ALLOWED
dacl.AddAce ace
sd.DiscretionaryAcl = dacl
sec.SetSecurityDescriptor sd

 

 

IADsRas-WinNT ADSI Extension: RAS Permission

IADsRas is an WinNT Extension on a user object. You need to install ADSI 2.5 first, before installing this component.

Location: /resourcekit/adsras.dll

Installation:  regsvr32 adsras.dll

Sample Client: /resourcekit/adsras

IADsRas

Interface definition

interface IADsRas : IDispatch
{
   HRESULT DialinPrivilege([out, retval] BOOL *pVal);
    HRESULT DialinPrivilege([in] BOOL newVal);
    HRESULT SetRasCallBack([in] long lCallBack, [in, optional] BSTR szPhoneNumber);
    HRESULT GetRasCallBack([out,retval] long *lPrivilege);
    HRESULT GetRasPhoneNumber([out,retval] BSTR *pszPhoneNumber);
};

 

Enumeration definition

  enum ADS_RAS_CALLBACK_ENUM
  {
               ADS_RAS_NOCALLBACK = 0x01,
               ADS_RAS_ADMIN_SETCALLBACK = 0x2,
               ADS_RAS_CALLER_SETCALLBACK = 0x4
  };

 

Examples

'-------------------------------
'----Viewing Ras Permissions----
'-------------------------------

  Set x = GetObject("WinNT://REDMOND/jsmith,user")
 if (  x.DialinPrivilege = True ) then
   Debug.Print "Grant Dialin Permission"
 end if

   lFlag = x.GetRasCallBack

  If (lFlag And ADS_RAS_NOCALLBACK) Then
      Debug.Print "No Callback"
  ElseIf (lFlag And ADS_RAS_CALLER_SETCALLBACK) Then
     Debug.Print "Ras Caller SetCallback"
 ElseIf (lFlag And ADS_RAS_ADMIN_SETCALLBACK) Then
     Debug.Print "Admin SetCallBack"
     Debug.Print  x.GetRasPhoneNumber   
End If  

'-------------------------------
'----Setting Ras Permissions----
'-------------------------------
'--Enabled Ras Permission

   Set x = GetObject("WinNT://REDMOND/jsmith,user")
    x.DialinPrivilege = True

    '---- Choose one of three settings ( optional)
    x.SetRasCallBack ADS_RAS_NOCALLBACK  '-- For setting no callback

   '---- OR -----
    x.SetRasCallBack ADS_RAS_CALLER_SETCALLBACK  '-- For setting caller setcallback

   '---- OR -----
   x.SetRasCallBack ADS_RAS_ADMIN_SETCALLBACK, phoneNumber '--- For setting Admin Call back

 

IADsVersion - Checking ADSI version number

You can check the ADSI version number both locally or remotely.

IADsVersion 

ProgID:  ADsVersion

interface IADsVersion : IDispatch
{
   HRESULT GetVersion([retval,out] BSTR *pbstrVersion );
   HRESULT GetMajorVersion([out,retval] LONG *plMajor);
   HRESULT GetMinorVersion([out,retval] LONG *plMinor);
   HRESULT GetLocale([out,retval] BSTR *pbstrLocale);
  HRESULT Connect([in] BSTR bstrComputer);
};
   

---VBScript example

  Set oArgs = wscript.Arguments
  Set vs = CreateObject("ADsVersion")

'-------------------------------------------------------------------
'You can also connect remotely to find out the ADSI version number
'vs.Connect "mycomputer"
'-------------------------------------------------------------------

if oArgs.Count = 1 Then
   wscript.echo "Connecting to " & oArgs(0) & "..."
   vs.Connect oArgs(0)
end if

'--- Get the version number
wscript.echo "ADSI Version : " & vs.GetVersion
wscript.echo "Major Version: " & vs.GetMajorVersion
wscript.echo "Minor Version: " & vs.GetMinorVersion
wscript.echo "Locale:            " & vs.GetLocale

----VB example 

Sub Main()
   Set vs = CreateObject("ADsVersion")

  '-------------------------------------------------------------------
  'You can also connect remotely to find out the ADSI version number
  'vs.Connect "mycomputer"
  '-------------------------------------------------------------------
  Debug.Print vs.GetVersion
  Debug.Print vs.GetMajorVersion
  Debug.Print vs.GetMinorVersion
  Debug.Print vs.GetLocale
End Sub

 

IADsError - Getting ADSI Error Messages

Location: /resourcekit/adserror.dll

Installation:  regsvr32 adserror.dll

Sample Client: /resourcekit/adserror

IADsError

Interface definition:

IADsError : public IDispatch
{
public:
  HRESULT GetErrorMessage(  /* [in] */ long hResult, /* [retval][out] */ BSTR __RPC_FAR *pbMsg) = 0;
};

Program ID: ADsError

Example:

Set adsErr = CreateObject("ADsError")
On Error GoTo ReportErr
Set rec = GetObject("LDAP://DC=ArcadiaBay, DC=Com")

'.... more code here....'

Exit Sub

ReportErr:
Debug.Print Err.Number
MsgBox adsErr.GetErrorMessage(Err.Number)