Тема: ResolveIPAddr(пример использования библиотеки network.obj)
В примере выводится IP-адрес в текстовое поле.
Сеть, разумеется, должна быть подключена.
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.