1

Тема: ResolveIPAddr(пример использования библиотеки network.obj)

В примере выводится IP-адрес в текстовое поле.
misc.php?action=pun_attachment&item=119&download=0
Сеть, разумеется, должна быть подключена.

program ResolveIPAddr;

uses
  KolibriOS;

function MemoryAllocate(Bytes: LongWord): Pointer; stdcall;
asm
        push ecx
        push ebx
        mov eax, 68
        mov ebx, 12
        mov ecx, Bytes
        int 64
        pop ebx
        pop ecx
end;

function MemoryReallocate(MemPtr: Pointer; Bytes: LongWord): Pointer; stdcall;
asm
        push ebx
        push ecx
        push edx
        mov eax, 68
        mov ebx, 20
        mov ecx, Bytes
        mov edx, MemPtr
        int 64
        pop edx
        pop ecx
        pop ebx
end;

function MemoryFree(MemPtr: Pointer): LongWord; stdcall;
asm
        push ecx
        push ebx
        mov eax, 68
        mov ebx, 13
        mov ecx, MemPtr
        int 64
        pop ebx
        pop ecx
end;

type
  Proc = procedure;

procedure InitLibrary(LibInit: Proc); stdcall;
const
  LIB_PATH = '/sys/lib/';

type
  PNameAddr = ^TNameAddr;
  TNameAddr = packed record
    Name: PAnsiChar;
    Addr: Pointer;
  end;

  PAddrName = ^TAddrName;
  TAddrName = packed record
    Addr: Pointer;
    Name: PAnsiChar;
  end;

  function StrEqual(Str1, Str2: PAnsiChar): Boolean;
  begin
    while (Str1^ = Str2^) and (Str1^ <> #0) do
    begin
      Inc(Str1);
      Inc(Str2);
    end;
    Result := Str1^ = Str2^;
  end;

  procedure StrCopy(StrFrom, StrTo: PAnsiChar);
  begin
    while (StrFrom^ <> #0) do
    begin
      StrTo^ := StrFrom^;
      Inc(StrFrom);
      Inc(StrTo);
    end;
  end;

  function DLLLoad(ImportTable: PAddrName): LongInt; stdcall;
  var
    ExportTable: PNameAddr;
    ProcAddr: Pointer;
    Name: PPAnsiChar;
    LibPath: array [0..32] of AnsiChar;
  begin
    Result := 1;
    StrCopy(LIB_PATH, LibPath);
    while ImportTable.Addr <> nil do
    begin
      StrCopy(ImportTable.Name, Pointer(LongInt(@LibPath) + Length(LIB_PATH)));
      ExportTable := LoadLibrary(LibPath);
      if ExportTable = nil then
        Exit;
      Name := PPAnsiChar(ImportTable.Addr);
      while Name^ <> nil do
      begin
        ProcAddr := GetProcAddress(ExportTable, Name^);
        if ProcAddr <> nil then
          Pointer(Name^) := ProcAddr
        else
          Exit;
        Inc(Name);
      end;
      if StrEqual(ExportTable.Name, 'lib_init') then
        InitLibrary(ExportTable.Addr);
      Inc(ImportTable);
    end;
    Result := 0;
  end;
asm
  pushad
  mov eax, offset MemoryAllocate
  mov ebx, offset MemoryFree
  mov ecx, offset MemoryReallocate
  mov edx, offset DLLLoad
  call LibInit
  popad
end;

const
  WINDOW_BORDER_SIZE = 5;

type
  // SizeOf(TEditBoxFlags) должен быть равен 4 байта(в данный момент это так),
  // иначе поле flags в структуре edit_box(ниже) будет определено неправильно
  TEditBoxFlags = set of (edfPassword, edfFocus, edfShift, edfShiftOn, edfShiftBac,
    edfLeft, edfOffset, edfInsert, edfMouse, edfCtrl, edfAlt, edfDisabled,
    edfReserved1, edfReserved2, edfAlwaysFocus, edfNumeric, edfReserved3);

  PEditBox = ^TEditBox;
  TEditBox = packed record
    width              : LongInt;
    left               : LongInt;
    top                : LongInt;
    color              : LongInt;
    shift_color        : LongInt;
    focus_border_color : LongInt;
    blur_border_color  : LongInt;
    text_color         : LongInt;
    max                : LongInt;
    text               : PAnsiChar;
    mouse_variable     : Pointer;
    flags              : TEditBoxFlags;
    size               : LongInt;
    pos                : LongInt;
    offset             : LongInt;
    cl_curs_x          : SmallInt;
    cl_curs_y          : SmallInt;
    shift              : SmallInt;
    shift_old          : SmallInt;
    height             : LongInt;
    char_width         : LongInt;
  end;

// структура определена в файле programs\network.inc
  PSockAddr = ^TSockAddr;
  TSockAddr = packed record
    sin_family: Word;                // sa_family_t
    sin_port:   Word;                // in_port_t
    sin_addr:   LongWord;            // struct in_addr
    sin_zero:   array[0..7] of Byte; // zero
  end;

// структура определена в файле programs\network.inc
  PAddrInfo = ^TAddrInfo;
  TAddrInfo = packed record
    ai_flags:     LongWord;  // bitmask of AI_*
    ai_family:    LongWord;  // PF_*
    ai_socktype:  LongWord;  // SOCK_*
    ai_protocol:  LongWord;  // 0 or IPPROTO_*
    ai_addrlen:   LongWord;  // length of ai_addr
    ai_canonname: PAnsiChar; // char*
    ai_addr:      PSockAddr; // struct sockaddr*
    ai_next:      PAddrInfo; // struct addrinfo*
  end;

const
  BUTTON_RESOLVE = 100;
  EDIT1_MAX_TEXT_BUFFER = 256;
  EDIT2_MAX_TEXT_BUFFER = Length('XXX.XXX.XXX.XXX') + 2;

var
  WndLeft, WndTop: LongInt;
  WndWidth: LongWord = 312 + WINDOW_BORDER_SIZE * 2;
  WndHeight: LongWord;

  SC: TStandardColors;
  ThreadInfo: TThreadInfo;

  BoxLib: Pointer;
  edit_box_draw:     procedure(var EditBox: TEditBox); stdcall;
  edit_box_key:      procedure(var EditBox: TEditBox); stdcall;
  edit_box_mouse:    procedure(var EditBox: TEditBox); stdcall;
  edit_box_set_text: procedure(var EditBox: TEditBox; Text: PAnsiChar); stdcall;

  Edit2TextBuffer: array [0..EDIT2_MAX_TEXT_BUFFER - 1] of AnsiChar;
  Edit1TextBuffer: array [0..EDIT1_MAX_TEXT_BUFFER - 1] of AnsiChar;

  Edit1: TEditBox = (
    width: 129;
    left: 8;
    top: 40;
    color: $00FFFFFF;
    shift_color: $00A4C4E4;
    text_color: 0 + DT_CP866_8X16;
    max: SizeOf(Edit1TextBuffer) - 2;
    text: Edit1TextBuffer;
    flags: [edfFocus]);

  Edit2: TEditBox = (
    width: 124;
    left: 94;
    top: 72;
    color: $00FFFFFF;
    shift_color: $00A4C4E4;
    text_color: 0 + DT_CP866_8X16;
    max: SizeOf(Edit2TextBuffer) - 2;
    text: Edit2TextBuffer);

  EditMV: LongWord;

  LibNetwork: Pointer;
  LibNetworkLibInit: procedure;
  getaddrinfo: function(HostName, ServName: PAnsiChar; Hints: PAddrInfo; var Res: PAddrInfo): LongInt; stdcall;
  freeaddrinfo: procedure(AddrInfo: PAddrInfo); stdcall;
  inet_ntoa: function(Address: LongWord): PAnsiChar; stdcall;

procedure EditBoxKey(var EditBox: TEditBox; Key: TKeyboardInput);
begin
  // код клавиши должен быть в eax перед вызовом edit_box_key
  asm mov eax, Key end;
  edit_box_key(EditBox);
end;

procedure On_Redraw;
begin
  BeginDraw;
  GetStandardColors(SC, SizeOf(TStandardColors));
  GetThreadInfo($FFFFFFFF, ThreadInfo);
  WndHeight := 100 + GetSkinHeight + WINDOW_BORDER_SIZE;
  DrawWindow(WndLeft, WndTop, WndWidth, WndHeight, 'Определить IP адрес', SC.Work,
    WS_SKINNED_SIZABLE + WS_CLIENT_COORDS + WS_CAPTION, CAPTION_MOVABLE);
  DrawButton(144, 32, 161, 33, SC.WorkButton, 0, BUTTON_RESOLVE);
  DrawText(150, 40, 'Определить IP адрес', SC.WorkButtonText, 0, DT_CP866_8X16 + DT_TRANSPARENT_FILL + DT_ZSTRING, 0);
  DrawText(8, 8, 'Введите имя хоста(например, yandex.ru)', SC.WorkText, 0, DT_CP866_8X16 + DT_TRANSPARENT_FILL + DT_ZSTRING, 0);
  Edit1.blur_border_color := not SC.Work and $00FFFFFF;
  Edit1.focus_border_color := SC.WorkGraph;
  Edit2.blur_border_color := not SC.Work and $00FFFFFF;
  Edit2.focus_border_color := SC.WorkGraph;
  edit_box_draw(Edit1);
  edit_box_draw(Edit2);
  EndDraw;
end;

procedure TryResolveIP;
var
  AddrInfo: PAddrInfo;
begin
  Edit1.flags := Edit1.flags + [edfDisabled];
  edit_box_draw(Edit1);
  if getaddrinfo(Edit1.text, nil, nil, AddrInfo) = 0{success} then
    edit_box_set_text(Edit2, inet_ntoa(AddrInfo.ai_addr.sin_addr))
  else
    edit_box_set_text(Edit2, '    Ошибка!    ');
  Edit1.flags := Edit1.flags - [edfDisabled];
  edit_box_draw(Edit1);
  edit_box_draw(Edit2);
  freeaddrinfo(AddrInfo);
end;

var
  Key: TKeyboardInput;

begin
  BoxLib            := LoadLibrary('/sys/lib/box_lib.obj');
  edit_box_draw     := GetProcAddress(BoxLib, 'edit_box');
  edit_box_key      := GetProcAddress(BoxLib, 'edit_box_key');
  edit_box_mouse    := GetProcAddress(BoxLib, 'edit_box_mouse');
  edit_box_set_text := GetProcAddress(BoxLib, 'edit_box_set_text');

  LibNetwork        := LoadLibrary('/sys/lib/network.obj');
  LibNetworkLibInit := GetProcAddress(LibNetwork, 'lib_init');
  getaddrinfo       := GetProcAddress(LibNetwork, 'getaddrinfo');
  freeaddrinfo      := GetProcAddress(LibNetwork, 'freeaddrinfo');
  inet_ntoa         := GetProcAddress(LibNetwork, 'inet_ntoa');

  InitLibrary(LibNetworkLibInit);

  with GetScreenSize do
  begin
    WndHeight := 100 + GetSkinHeight + WINDOW_BORDER_SIZE;
    WndLeft := (Width - WndWidth) div 2;
    WndTop := (Height - WndHeight) div 2;
  end;

  Edit1.text := Edit1TextBuffer;
  Edit2.text := Edit2TextBuffer;
  Edit1.mouse_variable := @EditMV;
  Edit2.mouse_variable := @EditMV;

  SetEventMask(EM_REDRAW + EM_KEY + EM_BUTTON + EM_MOUSE);

  while True do
    case WaitEvent of
      REDRAW_EVENT:
        On_Redraw;
      KEY_EVENT:
        begin
          Key := GetKey;
          EditBoxKey(Edit1, Key);
          EditBoxKey(Edit2, Key);
        end;
      MOUSE_EVENT:
        if GetActiveWindow = GetSlotById(ThreadInfo.Identifier) then
        begin
          edit_box_mouse(Edit1);
          edit_box_mouse(Edit2);
        end;
      BUTTON_EVENT:
        case GetButton.ID of
          BUTTON_RESOLVE:
            TryResolveIP;
        else
          Break;
        end;
    end;
end.

Прикладываю уже готовое приложение ResolveIPAddr.kex.

Post's attachments

Иконка вложений ResolveIPAddr.kex 1.41 Кб, 58 скачиваний с 2021-12-26 

ResolveIPAddr.PNG, 4.7 Кб, 323 x 130
ResolveIPAddr.PNG 4.7 Кб, 62 скачиваний с 2021-12-26