To the main page...The list of my products...Some texts...Sample applications, tips, tricks...If you need support...
 

 
The SID and what to do with it
Step 3. List of users

Each time you configure the access rights to file or directory you use the Windows dialog that allows you to select users from the list. This dialog looks like picture below (Russian version :-)

With this step we shall create a light version of this dialog. Of course we could implement all features of this dialog but it is not our purpose. Our example will be based on SIDCenter component to obtain a list of well-known users for of given computer or domain. This application will be used in future as a dialog for selecting users and groups. You can download this application from here (zip,2.5Kb).

Well, let's do it. Create a new application and place the following components on its form:

  • TLabel with caption 'Get names from'
  • TLabel with caption 'User name'
  • TEdit with name 'EdDomain'
  • TEdit with name 'EdUserName'
  • TTimer with name 'Timer'
  • TsvSidCenter with name 'SidC'
  • TListView with name 'LV'
  • Label with caption 'SID'
  • Label with name 'LbSID' and empty caption

Set ListView.ViewStyle property to vsReport and add one column to it. The resulting form should look like shown below

Now we shall add events and methods to these components. The common idea is to show the SID of currently selected user as a string in the LbSD.Caption. So we should track the changes of both edits. But immediate reaction on edit changes is not a good behaviour. It is too annoying and to avoid it we shall do the following. We shall activate timer when changes occur and the timer will do all necessary actions. After that timer will deactivate itself.

Let's implement it. Add the OnChange handlers to both edits and add code to them. As usually all necessary changes are marked by background color.



 
 
 


 
 
 

procedure TUsersListForm.EdUserNameChange(Sender: TObject);
begin
    Timer.Enabled:=True;
end;

procedure TUsersListForm.EdDomainChange(Sender: TObject);
begin
    Timer.Enabled:=True;
end;

Then add the OnTimer event handler to timer and modify it as shown below:



 
 
 
 
 

 
 

 

procedure TUsersListForm.TimerTimer(Sender: TObject);
begin
    if _IsBusy then exit;
    _IsBusy:=True;
    try
        {We shall place essential code here}
    finally
        _IsBusy:=False;
        Timer.Enabled:=False;
    end;
end;

This skeleton will do the following actions. At first it will be entered only once per timer activation. The _IsBusy variable changes to True when handler starts and prevents re-entering of our code. Then, at the end of the handler this variable becomes False again but timer deactivates. So the next call of this handler will mean that one of edit's was changed.

Do not forget to add the declaration of the boolean variable _IsBusy to the private section of our form.







 

  private
    { Private declarations }
    _IsBusy: Boolean;
  public
    { Public declarations }
  end;

Now we shall add the essential code to the OnTimer handler.





 
 
 
 
 
 
 

 
 

 
 
 
 
 
 
 
 

 
 

 

procedure TUsersListForm.TimerTimer(Sender: TObject);
var wn : TsvWellKnownSid;
    LI: TListItem;
begin
    if _IsBusy then exit;
    _IsBusy:=True;
    try
        SidC.Domain:=EdDomain.Text;
        SidC.UserName:=EdUserName.Text;
        LbSID.Caption:=SidC.SidString;
        
        LV.Items.Clear;
        for wn:=Low(TsvWellKnownSid) to High(TsvWellKnownSid) do
        begin
            if wn in [wkCurrentUser,wkOther] then continue;
            SidC.Domain:=EdDomain.Text;
            SidC.WellKnown:=wn;
            if SidC.UserName = '' then continue;
            LI:=LV.Items.Add;
            LI.Caption:=SidC.Domain+'\'+SidC.UserName;
            LI.Data:=SidC.GetSidCopy;
        end;
    finally
        _IsBusy:=False;
        Timer.Enabled:=False;
    end;
end;

The first lines of this code illustrate the main xxxCenter components idea: Set What You Have and Get What You Need. In our case we set the Domain and UserName properties of SidCenter and get what we need which is Sid in the string form.

The second portion shows how to create the list of well-known users for the given domain or computer. At first we clear the list view. Then we iterate through all TsvWellKnownSid items and for each item (except wkOther and wkCurrentUser :-) try to obtain the name of user that corresponds to the given SID. Note that not all combinations will result to valid SID. Some of this SIDs are computer-relative, others are domain-relative and you will see that exceptions occur inside SvCom units. Ignore these exceptions. They will be catched inside of SvCom and you will not see them without debugger. To check whether the current SID is valid we use a very simple approach that is we test the UserName property. If it is empty it means that system does not know this SID and it is not valid. If so we shall skip it. In other case we shall add it to the list view.

The last line of our code does work that is very important for future. We remember the SID in its native form in the Data property of ListItem. There are two important notes: we use GetSidCopy function instead of Sid property. The thing is that the Sid property will change each time we re-assign other SidCenter properties. On the contrary the GetSidCopy returns a permanent copy of SID structure. This copy will be freed only the SidCenter component will be freed or its Cleanup method will be called. So the second important note is that we should not care about pointer returned by GetSidCopy and of course we should not free this memory.

Well, let's now add code that will handle changes in the list view. When user clicks on it and selects an item we shall show the SID that corresponds to the selected item. Add OnClick handler the list view and modify it as shown below.



 
 
 
 
 
 
 
 

procedure TUsersListForm.LVClick(Sender: TObject);
begin
    if LV.Selected = nil then exit;
    SidC.SID:=LV.Selected.Data;
    EdDomain.Text:=SidC.Domain;
    EdUserName.Text:=SidC.UserName;
    Timer.Enabled:=False;
    LbSID.Caption:=SidC.SidString;
end;

As you can see this handler does nothing if the selection is nil. In other case we set the SID property of SidCenter using pointer stored in the ListItem.Data. After that we read domain and user name. It is another illustration of xxxCenters idea: Set What You Have and Get What You Need.

Two last lines of this handler prevent the listview flickering due to edits change and set the LbSid caption to reflect the selection.

Save our project and compile it. Now it is ready for tests.

<< | Index | Step 1 | Step 2 | Step 3 | Step 4 | >>
Add your comment | Read comments


 
© 1998-2001 Alexey Dynnikov
My ICQ # is 18267212