Modifying Properties of a Directory Object with DAPIWrite

I have shown how attributes of a MS Exchange Directory item may be retrieved with DAPI functions, and dumped to the screen. Let us examine whether we could modify some attributes and write them to the directory.

The following two items are important when dealing with the DAPIWrite function.

  • You need to take care about proper initialization of the base point and the container - two members of DAPI_PARMS structure, which you pass to the DAPIStart. If these members are not initialized, the DAPIWrite function is likely to fail with "object class violation" message, which in this case means that you can't create objects of a particular type in the (default) location.
  • Nil terminators of DAPI_ENTRY arrays. The DAPIWrite function takes two pointers to DAPI_ENTRY arrays. One arrays specifies attribute names and the other - their values to be written into the directory. It appears that the last entry in each array must be set to Nil . Obviously, Nil entries identify array ends. During my original research, when I was not aware of it, the DAPIWrite function failed with C0000081 error code (DAPI_E_BAD_HANDLE) when I once supplied these arrays without terminators. Apparently, it was trying to read what was following my last entry and make use of it.

Creating a New Mailbox with DAPIWrite

The following sample code illustrates how you can create a new Windows NT user account and associate it with MS Exchange mailbox with help of the DAPIWrite function:

procedure TfrmMain.btStartClick(Sender: TObject);
var
   
ObjectToRead:Array [0..255] of Char;
    TempStr:String;
    userprop:TStrings;
    i,ct:Integer;
    p:PCHAR;

    deAttributes,
    deValues:PDAPI_ENTRY;

    rgEntryAttributes,
    rgEntryValues:PATT_VALUE;

    pAccount,
    pPassword:PChar;

   
ulUSN:ULONG;

    FlagRandPass:DWORD;
begin 
    TempStr:=Trim(ebMailbox.Text);

    if cbCP.Checked then FlagRandPass:=
DAPI_CREATE_RANDOM_PASSWORD else
        FlagRandPass:=0;

FlagRandPass:=FlagRandPass or
DAPI_CREATE_NT_ACCOUNT;  


if TempStr=EmptyStr then
begin 
    ShowMessage('Please, type some value!');
    Exit;
end

if Assigned(SiteInfo) then SiteInfo.Free;
SiteInfo:=TSiteInfo.Create(Trim(ebESName.Text));

if SiteInfo.GetInfo then
begin 
// Check for started DAPI Session
    if DSession=DAPI_INVALID_HANDLE then
        begin 
            DAPIParms.dwDAPISignature:=DAPI_SIGNATURE;

       
DAPIParms.dwFlags := DAPI_EVENT_ALL or //Logs start...
                                           
FlagRandPass

DAPIParms.pszDSAName:=PChar(SiteInfo.SrvName);

// Initialize base point and container
DAPIParms.pszBasePoint := PChar(SiteInfo.SiteDNString);
DAPIParms.pszContainer := '/cn=Recipients';


ct:=3; //Number of Params

deAttributes:=DAPIAllocBuffer(SizeOf(DAPI_ENTRY), nil);
ZeroMemory(deAttributes, SizeOf(DAPI_ENTRY));


deAttributes.unAttributes := ct; //# of attributes
deAttributes.ulEvalTag := TEXT_VALUE_ARRAY;

rgEntryAttributes:=DAPIAllocBuffer(SizeOf(ATT_VALUE)*ct,nil);
ZeroMemory(rgEntryAttributes, SizeOf(ATT_VALUE)*ct);

PATT_VALUE(ULONG(rgEntryAttributes)+ULONG(SizeOf(ATT_VALUE)*(ct-3)))^:=
PATT_VALUE(ToAttValue('Object-Class',DAPI_TEXT))^;

PATT_VALUE(ULONG(rgEntryAttributes)+ULONG(SizeOf(ATT_VALUE)*(ct-2)))^:=
PATT_VALUE(ToAttValue('Common-Name',DAPI_TEXT))^;

PATT_VALUE(ULONG(rgEntryAttributes)+ULONG(SizeOf(ATT_VALUE)*(ct-1)))^:=
PATT_VALUE(ToAttValue('Home-Server',DAPI_TEXT))^;

deAttributes.rgEntryValues:=DAPIAllocBuffer(SizeOf(ATT_VALUE)*(ct), deAttributes);
ZeroMemory(deAttributes.rgEntryValues, SizeOf(ATT_VALUE)*(ct));

deAttributes.rgEntryValues:=rgEntryAttributes;

deValues:=DAPIAllocBuffer(sizeof(DAPI_ENTRY), nil);
ZeroMemory(deValues, sizeof(DAPI_ENTRY));

deValues.unAttributes := ct; //# of attributes
deValues.ulEvalTag := VALUE_ARRAY;

rgEntryValues:=DAPIAllocBuffer(SizeOf(ATT_VALUE)*ct,nil);
ZeroMemory(rgEntryValues, SizeOf(ATT_VALUE)*ct);

PATT_VALUE(ULONG(rgEntryValues)+ULONG(SizeOf(ATT_VALUE)*(ct-3)))^:=
PATT_VALUE(ToAttValue('Mailbox',DAPI_TEXT))^;

PATT_VALUE(ULONG(rgEntryValues)+ULONG(SizeOf(ATT_VALUE)*(ct-2)))^:=
PATT_VALUE(ToAttValue(TempStr,DAPI_TEXT))^;

PATT_VALUE(ULONG(rgEntryValues)+ULONG(SizeOf(ATT_VALUE)*(ct-1)))^:=
PATT_VALUE(ToAttValue('~SERVER',DAPI_TEXT))^;

deValues.rgEntryValues:=DAPIAllocBuffer(sizeof(ATT_VALUE)*(ct), deValues);
ZeroMemory(deValues.rgEntryValues, sizeof(ATT_VALUE)*(ct));

deValues.rgEntryValues:=rgEntryValues;


pAccount := Nil;
pPassword := Nil;
ulUSN := 0;


//Initialize DAPI   

(*
The DAPIStart function initializes a directory operation session.
*)

pDAPIEvent:=
DAPIStart(@DSession,@DAPIParms);

if Assigned(pDAPIEvent) then
begin 
    RaiseDAPIError(pDAPIEvent);
    DAPIFreeMemory(pDAPIEvent);
end 
else
// We have DAPI session. We can use it here...
begin 

pDAPIEvent :=
DAPIWrite(DSession,
DAPI_WRITE_CREATE,
deAttributes,
deValues,
@ulUSN,
@pAccount,
// Account
@pPassword); // Password

if Assigned(pDAPIEvent) then
    RaiseDAPIError(pDAPIEvent)
else
    ShowMessage('Account is Created!' + #13+#10+
                            'NT Account is: ' + StrPas(pAccount) + #13+#10+
                            'with Password: ' +StrPas(pPassword));

... etc....

Compiled DELPHI 5 example

 

 


Copyright © 2012 IMIBO
Send mail to webmaster@imibo.com with questions or comments.
Privacy Statement