Главная > Программирование, системное > Пишем собственную утилиту для администрирования. Часть 1.

Пишем собственную утилиту для администрирования. Часть 1.

Как я не однократно упоминал, любой программист должен знать, или хотя бы представлять себе как работает та или иная программа и уж тем более системная утилита. Это в первую очередь помогает понимать сам процесс взаимодействия операционной системы и программы. И следовательно создавать для себя, в качестве удобства администрирования свои собственные утилиты. Ну не пользоваться же в конце концов встроенными? Оо

В этой статье и в последующих я рассмотрю разработку собственной утилиты для администрирования под управлением операционных систем Windows 2000/XP., которая позволит создавать пользователей, удалять их, редактировать профиль, изменять пароль и много другое.
А теперь приступим. Начнем с того, как научить нашу прогу получать список зарегистрированных пользователей. Для этого рассмотрим такую системную API-функцию как NetUserEnum. В MSDN’е она описана таким образом:


NET_API_STATUS NetUserEnum(
__in LPCWSTR servername,
__in DWORD level,
__in DWORD filter,
__out LPBYTE *bufptr,
__in DWORD prefmaxlen,
__out LPDWORD entriesread,
__out LPDWORD totalentries,
__inout LPDWORD resume_handle
);

Где первый параметр указывает на компьютер в сети. Если в качестве этого параметра указать nil, то система определит локальное имя компьютера.
Параметр level указывает системе о том какого уровня требуется информация об акаунте, более подробно их мы рассмотрим позже, но кому не терпится, могут почитать на MSDN’e. Но в примере мы рассмотрим уровень – 10. Он нам вернет имя акаунта, информацию об акаунте.
Далее используется параметр в котором нужно указать по какому признаку фильтровать системную информацию. Как гласит справка MSDN их всего 6:


FILTER_TEMP_DUPLICATE_ACCOUNT
FILTER_NORMAL_ACCOUNT
FILTER_PROXY_ACCOUNT
FILTER_INTERDOMAIN_TRUST_ACCOUNT
FILTER_WORKSTATION_TRUST_ACCOUNT
FILTER_SERVER_TRUST_ACCOUNT

Подробней о них в следующей статье, а в примере мы будем использовать FILTER_NORMAL_ACCOUNT.
В следующий параметр будет возвращен результат работы функции.
В следующем параметре указываем размер буфера.
В entriesread будет возвращено количество актуальных прочтенных записей, а в параметре totalentries – общее количество записей(зарегистрированных пользователей).
В последнем параметре будет возвращен указатель, для возможности продолжения работы.
В лсдучае успешной отработки данной функции будет возвращено нулевое значение. В случае же ошибки будет возвращен один из следующих кодов ошибок:

ERROR_ACCESS_DENIED
NERR_InvalidComputer
ERROR_MORE_DATA

В связи с выбранным уровнем 10, будем исследовать следующую структуру, которая описана в справке MSDN:


typedef struct _USER_INFO_10 {
LPWSTR usri10_name;
LPWSTR usri10_comment;
LPWSTR usri10_usr_comment;
LPWSTR usri10_full_name;
} USER_INFO_10, *PUSER_INFO_10, *LPUSER_INFO_10;

Так как наш язык программирования Delphi. Все выше описанное следует переделать под него, ну и не долго тянув кота за яйки, рассмотрим исходник получения списка пользователей в ОС Windows:

Delphi

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,Stdctrls, Comctrls;

{$EXTERNALSYM NetUserEnum}
function NetUserEnum(servername: LPWSTR;
  level,
  filter: DWORD;
  bufptr: Pointer;
  prefmaxlen: DWORD;
  entriesread,
  totalentries,
  resume_handle: LPDWORD): DWORD; stdcall;
external 'NetApi32.dll' Name 'NetUserEnum';
function NetApiBufferFree(Buffer: Pointer): DWORD; stdcall;
external 'NetApi32.dll' Name 'NetApiBufferFree';

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
     private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
const
  NERR_SUCCESS = 0;
  FILTER_TEMP_DUPLICATE_ACCOUNT = $0001;
  FILTER_NORMAL_ACCOUNT = $0002;



  FILTER_PROXY_ACCOUNT = $0004;
  FILTER_INTERDOMAIN_TRUST_ACCOUNT = $0008;
  FILTER_WORKSTATION_TRUST_ACCOUNT = $0010;
  FILTER_SERVER_TRUST_ACCOUNT = $0020;
type
  TUSER_INFO_10 = record
    usri10_name,
      usri10_comment,
      usri10_usr_comment,
      usri10_full_name: PWideChar;
  end;
  PUSER_INFO_10 = ^TUSER_INFO_10;
var
  dwERead, dwETotal, dwRes, res: DWORD;
  inf: PUSER_INFO_10;
  info: Pointer;
  p: PChar;
  i: Integer;
begin
  info := nil;
  dwRes := 0;
  res := NetUserEnum(nil,
    10,
    FILTER_NORMAL_ACCOUNT,
    @info,
    65536,
    @dwERead,
    @dwETotal,
    @dwRes);
  if (res <> NERR_SUCCESS) or (info = nil) then
    Exit;
  p := PChar(info);
  for i := 0 to dwERead - 1 do
  begin
    inf := PUSER_INFO_10(p + i * SizeOf(TUSER_INFO_10));
    memo1.Lines.Add(WideCharToString(PWideChar((inf^).usri10_name)));
    memo1.Lines.Add(WideCharToString(PWideChar((inf^).usri10_comment)));
    memo1.Lines.Add(WideCharToString(PWideChar((inf^).usri10_usr_comment)));
    memo1.Lines.Add(WideCharToString(PWideChar((inf^).usri10_full_name)));
  end;
  NetApiBufferFree(info);
end;

Когда вы взгляните на результат работы функции, у вас появиться вопрос, а зачем нам нужны технические пользователи созданные системой автоматически для своих нужд? Абсолютно с вами соглашусь, возвращенный результат содержит много побочной и не нужной инфы, однако, стоит знать все, что известно о пользователе, зарегистрированном в системе, все может пригодиться ;). А в следующей статье мы рассмотрим более подробно используемые структуры, другие системные функции для работы с пользователями и естественно возможность отсеивания не нужной инфы.Ну а пока, предлагаю вам возможность поковырять исходник =).

Пожалуйста, оцените полезность и качество данной статьи. Одна звезда - плохо, 5 - хорошо.
1/5. Мы будем признательны, если вы напишете комментарий с причиной низкой оценки.2/5. Мы будем признательны, если вы напишете комментарий с причиной низкой оценки.3/5. Мы будем признательны, если вы напишете комментарий с причиной низкой оценки.4/5.5/5. (3 голосов, средний: 4,67 из 5)
Загрузка...
  1. Пока что нет комментариев.
  1. Пока что нет уведомлений.