slesh
23.06.2007, 20:38
Вот както писал для себя маленькую прогу на FASM.
Прога предназначенна для трассировки прохождения данных между серверами. Почти аналог стандартной виндовой, за одним исключением:
1) Не показывает время прохождения пакетов
2) Имеет графический интерфейс
3) после компила прога весит 4 кила.
Вот хорошо откоментированный исходник:
От туда можно взять функцию пингования сервера и работу с диалогами. Раньше там был еще и XP манифест, чтобы красиво выглядело все, но я его потом убрал (т.к. программа от него слегка жирноватая становится :) )
Компилить как всегда через стандартный FASM
format PE GUI 4.0
entry _start
include 'd:\coding\fasm\include\win32ax.inc'
include 'd:\coding\fasm\include\encoding\win1251.inc'
section '.code' code readable writable executable
_start:
jmp realstart ; переход на начало кода
; необходимые структуры
struct IP_OPTION_INFORMATION
Ttl db 0
Tos db 0
Flags db 0
OptionsSize db 0
OptionsData dd 0
ends
struct ICMP_ECHO_REPLY
Address dd 0
Status dd 0
RoundTripTime dd 0
DataSize dw 0
Reserved dw 0
Data dd 0
Options IP_OPTION_INFORMATION
PingBuf db 32 dup (0)
ends
struct TInAddr
b1 db 0
b2 db 0
b3 db 0
b4 db 0
ends
hwnd_g dd 0 ; дискриптор окна
memo_buf dd 0 ; буфер в котором хранится отображаемый в мемо текст
Optionss IP_OPTION_INFORMATION
InAddr TInAddr
Reply ICMP_ECHO_REPLY
PingBuf db 32 dup (0)
IP_BUF db 256 dup (0) ; буфер для IP адреса или DNS
REMOTE_IP db 16 dup (0) ; удаленный IP
handle dd 0
WSData WSADATA ; для работы с сокетами
SOCKADDR sockaddr_in ; для работы с сокетами
HostEnt hostent ; для определения IP<-->DNS
small_buf dd 0 ; малый (временный) буфер
num_buf db 10 dup (0) ; буфер для числа
schet dd 0 ; счетчик серверов
hwndg dd 0 ; дискриптор окна
formats db "%d",0 ; формат приобразования числа в строку
crlf db 13,10,0 ; для перехода на слудующую строку в мемо
realstart: ; начало проги
invoke GetProcessHeap ; получаем адрес кучи процесса
invoke HeapAlloc,eax,0,65535 ; выделяем 65 килобайт в куче под буфер для мемо
mov [memo_buf],eax ; сохраняем адрес памяти буфера
mov [eax],dword 0
invoke GetProcessHeap ; получаем адрес кучи процесса
invoke HeapAlloc,eax,0,10240 ; выделяем малый буфер
mov [small_buf],eax ; сохраняем адрес памяти буфера
mov [eax],dword 0
invoke GetModuleHandle,0 ; получение дискриптора
invoke DialogBoxParam,eax,100,HWND_DESKTOP,MainProc,0 ; вызвать диалог
proc Ping InetAddress,ttl ; пингование передается адрес сервера и ТТЛ
invoke IcmpCreateFile ;
cmp eax,INVALID_HANDLE_VALUE ; если не удалось создать "ICMP файл"
je exitp
mov [handle],eax ;сохраним дискриптор
invoke gethostbyname,[InetAddress] ; попытка отпределяни IP адреса
cmp eax,0 ; если не удалось
je exitp ; то
mov eax,[eax+0ch] ; заполение необходимой струкуры
mov eax,[eax]
mov cl,[eax]
mov [InAddr.b1],cl
mov cl,[eax+1]
mov [InAddr.b2],cl
mov cl,[eax+2]
mov [InAddr.b3],cl
mov cl,[eax+3]
mov [InAddr.b4],cl
mov eax,PingBuf
mov [Reply.Data],eax
mov [Reply.DataSize],32
mov al,byte [ttl]
mov [Optionss.Ttl],al
mov eax,[InAddr]
invoke IcmpSendEcho,[handle],eax,PingBuf,32,Optionss,Reply,92,3000 ; пинг
cmp eax,0
je exitp
mov eax,1
ret
exitp:
xor eax,eax
ret
endp
proc memo_add texts,hwnd_g ; процедура добавления и вывода текста на экран (в мемо)
invoke lstrcat,[memo_buf],[texts] ; добавить текст к буферу
invoke lstrcat,[memo_buf],crlf ; добавить символ конца строки
invoke GetDlgItem,[hwnd_g], 105 ; получить адрес мемо
invoke SendMessage,eax, WM_SETTEXT, 3, [memo_buf] ; вывести буфер
ret ; возврат из процедуры
endp ; конец процедуры
proc trace
push eax ecx
invoke WSAStartup,$101, WSData ; инит
stdcall memo_add,'Трассировка начата',[hwndg] ; Вывести данные
stdcall memo_add,'------------------',[hwndg] ; о начале трасировки
invoke GetDlgItem,[hwndg], 104 ; адрес edit'a
invoke GetWindowText,eax,IP_BUF,255 ; считать что там введено
mov [schet],1 ; счетчик серверов
traces:
mov ecx,[schet]
stdcall Ping,IP_BUF,ecx ; пропинговать
cmp eax,0 ; если не пингуется
je trace_err ; то
mov eax,[small_buf] ; очистить временный буфер
mov [eax],dword 0
invoke wsprintf,num_buf,formats,[schet] ; типа inttostr
add esp,12 ; для очистки стека. т.к. wsprintf почемуто за собой не очищает его
invoke lstrcat,[small_buf],num_buf ; добавить к малому буферу номер сервера
invoke lstrcat,[small_buf],') ['
invoke inet_ntoa,[Reply.Address] ; определить адрес сервера
invoke lstrcat,[small_buf],eax ; добавить к малому буферу IP адрес сервера
invoke lstrcat,[small_buf],'] '
invoke gethostbyaddr,Reply.Address, 4, AF_INET ; определить имя сервера
cmp eax,0 ; еси имя удалось определить
jne mmmm ; то
invoke lstrcat,[small_buf],'---not host name---' ; добавить в буфер инфу о том что неудалось определить имя сервера
jmp mmmm1
mmmm:
mov eax,[eax]
invoke lstrcat,[small_buf],eax ; добавить к малому буферу имя сервера
mmmm1:
stdcall memo_add,[small_buf],[hwndg] ; вывести малый буфер на экран
inc [schet] ; увеличить счетчик серверов
cmp [Reply.Status],0 ;если это не последний сервер
jne traces ; то
; иначе
stdcall memo_add,'------------------',[hwndg] ;дабовать в мемо инфу
stdcall memo_add,'Трассировка закончена',[hwndg] ; о том что трасировка закончена
pop ecx eax
ret ; возврат из процедуры
trace_err: ; Если истекло время
stdcall memo_add,'Истечение времени ответа',[hwndg] ; вывести ошибку
pop ecx eax
ret ; возврат из процедуры
endp
proc MainProc hwnd,msg,wparam,lparam ; главная диалоговая процедура
push ebx esi edi
; ---------обработка сообщений-----
cmp [msg],WM_COMMAND ; если получина команда
je main_wmcommand
cmp [msg],WM_CLOSE ; если выход
je main_close
xor eax,eax ; еах=0
jmp main_finish ; переход на конец процедуры
main_wmcommand: ; команды
cmp [wparam],BN_CLICKED shl 16+101
je main_go
cmp [wparam],BN_CLICKED shl 16+102
je main_clear
jmp main_processed ; продолжение
main_go: ; начать трассировку
mov eax,[hwnd]
mov [hwndg],eax ; сохранить дискриптор окна (пригодится)
invoke CreateThread,0, 0, trace, 0, 0, handle ; создать поток трассировки (чтобы не вешать прогу)
jmp main_processed ; продолжение
main_clear: ; очистка мемо
mov eax,[memo_buf]
mov [eax],dword 0 ; записть первым символом - 0x00
invoke GetDlgItem,[hwnd], 105
invoke SendMessage,eax, WM_SETTEXT, 3, [memo_buf] ; вывести на экран пустой буфер
jmp main_processed ; продолжение
main_close: ; выход и программы
invoke EndDialog,[hwnd],0 ; закрыть диалог
invoke ExitProcess,0 ; завершить процесс
main_processed: ; продолжение
mov eax,1 ; возврат удачности
main_finish:
pop edi esi ebx
ret
endp
; таблица импорта
section '.idata' import data readable writeable
library kernel32,'KERNEL32.DLL',user32,'USER32.DLL',wsock3 2,'WSOCK32.DLL',icmp,'icmp.dll'
include 'd:\coding\fasm\include\apia\kernel32.inc'
include 'd:\coding\fasm\include\apia\user32.inc'
include 'd:\coding\fasm\include\apia\WSOCK32.inc'
import icmp,IcmpCreateFile,'IcmpCreateFile',\
IcmpSendEcho,'IcmpSendEcho'
; секция ресурсов
section '.rsrc' resource data readable
directory RT_DIALOG,dialogs
resource dialogs,100,LANG_RUSSIAN+SUBLANG_DEFAULT,mainform
dialog mainform,'SLESH TraceRoute for Windows',70,70,447,171,DS_MODALFRAME+WS_MINIMIZEBO X+WS_POPUP+WS_CAPTION+WS_SYSMENU
dialogitem 'BUTTON','TRACE', 101, 353, 2, 45, 14, BS_PUSHBUTTON+BS_FLAT+WS_POPUP+WS_VISIBLE+WS_TABST OP
dialogitem 'BUTTON','CLEAR', 102, 400, 2, 45, 14, BS_PUSHBUTTON+BS_FLAT+WS_POPUP+WS_VISIBLE+WS_TABST OP
dialogitem 'STATIC','Введите IP / HOST:', 103, 6, 4, 81, 11, SS_CENTER+WS_CHILD+WS_VISIBLE+WS_GROUP
dialogitem 'EDIT','', 104, 91, 2, 259, 14, ES_LEFT+WS_CHILD+WS_VISIBLE+WS_BORDER+WS_TABSTOP
dialogitem 'EDIT','', 105, 4, 18, 440, 150, ES_LEFT+ES_MULTILINE+ES_AUTOVSCROLL+ES_AUTOHSCROLL +ES_READONLY+WS_CHILD+WS_VISIBLE+WS_BORDER+WS_VSCR OLL+WS_HSCROLL+WS_TABSTOP
enddialog
Прога предназначенна для трассировки прохождения данных между серверами. Почти аналог стандартной виндовой, за одним исключением:
1) Не показывает время прохождения пакетов
2) Имеет графический интерфейс
3) после компила прога весит 4 кила.
Вот хорошо откоментированный исходник:
От туда можно взять функцию пингования сервера и работу с диалогами. Раньше там был еще и XP манифест, чтобы красиво выглядело все, но я его потом убрал (т.к. программа от него слегка жирноватая становится :) )
Компилить как всегда через стандартный FASM
format PE GUI 4.0
entry _start
include 'd:\coding\fasm\include\win32ax.inc'
include 'd:\coding\fasm\include\encoding\win1251.inc'
section '.code' code readable writable executable
_start:
jmp realstart ; переход на начало кода
; необходимые структуры
struct IP_OPTION_INFORMATION
Ttl db 0
Tos db 0
Flags db 0
OptionsSize db 0
OptionsData dd 0
ends
struct ICMP_ECHO_REPLY
Address dd 0
Status dd 0
RoundTripTime dd 0
DataSize dw 0
Reserved dw 0
Data dd 0
Options IP_OPTION_INFORMATION
PingBuf db 32 dup (0)
ends
struct TInAddr
b1 db 0
b2 db 0
b3 db 0
b4 db 0
ends
hwnd_g dd 0 ; дискриптор окна
memo_buf dd 0 ; буфер в котором хранится отображаемый в мемо текст
Optionss IP_OPTION_INFORMATION
InAddr TInAddr
Reply ICMP_ECHO_REPLY
PingBuf db 32 dup (0)
IP_BUF db 256 dup (0) ; буфер для IP адреса или DNS
REMOTE_IP db 16 dup (0) ; удаленный IP
handle dd 0
WSData WSADATA ; для работы с сокетами
SOCKADDR sockaddr_in ; для работы с сокетами
HostEnt hostent ; для определения IP<-->DNS
small_buf dd 0 ; малый (временный) буфер
num_buf db 10 dup (0) ; буфер для числа
schet dd 0 ; счетчик серверов
hwndg dd 0 ; дискриптор окна
formats db "%d",0 ; формат приобразования числа в строку
crlf db 13,10,0 ; для перехода на слудующую строку в мемо
realstart: ; начало проги
invoke GetProcessHeap ; получаем адрес кучи процесса
invoke HeapAlloc,eax,0,65535 ; выделяем 65 килобайт в куче под буфер для мемо
mov [memo_buf],eax ; сохраняем адрес памяти буфера
mov [eax],dword 0
invoke GetProcessHeap ; получаем адрес кучи процесса
invoke HeapAlloc,eax,0,10240 ; выделяем малый буфер
mov [small_buf],eax ; сохраняем адрес памяти буфера
mov [eax],dword 0
invoke GetModuleHandle,0 ; получение дискриптора
invoke DialogBoxParam,eax,100,HWND_DESKTOP,MainProc,0 ; вызвать диалог
proc Ping InetAddress,ttl ; пингование передается адрес сервера и ТТЛ
invoke IcmpCreateFile ;
cmp eax,INVALID_HANDLE_VALUE ; если не удалось создать "ICMP файл"
je exitp
mov [handle],eax ;сохраним дискриптор
invoke gethostbyname,[InetAddress] ; попытка отпределяни IP адреса
cmp eax,0 ; если не удалось
je exitp ; то
mov eax,[eax+0ch] ; заполение необходимой струкуры
mov eax,[eax]
mov cl,[eax]
mov [InAddr.b1],cl
mov cl,[eax+1]
mov [InAddr.b2],cl
mov cl,[eax+2]
mov [InAddr.b3],cl
mov cl,[eax+3]
mov [InAddr.b4],cl
mov eax,PingBuf
mov [Reply.Data],eax
mov [Reply.DataSize],32
mov al,byte [ttl]
mov [Optionss.Ttl],al
mov eax,[InAddr]
invoke IcmpSendEcho,[handle],eax,PingBuf,32,Optionss,Reply,92,3000 ; пинг
cmp eax,0
je exitp
mov eax,1
ret
exitp:
xor eax,eax
ret
endp
proc memo_add texts,hwnd_g ; процедура добавления и вывода текста на экран (в мемо)
invoke lstrcat,[memo_buf],[texts] ; добавить текст к буферу
invoke lstrcat,[memo_buf],crlf ; добавить символ конца строки
invoke GetDlgItem,[hwnd_g], 105 ; получить адрес мемо
invoke SendMessage,eax, WM_SETTEXT, 3, [memo_buf] ; вывести буфер
ret ; возврат из процедуры
endp ; конец процедуры
proc trace
push eax ecx
invoke WSAStartup,$101, WSData ; инит
stdcall memo_add,'Трассировка начата',[hwndg] ; Вывести данные
stdcall memo_add,'------------------',[hwndg] ; о начале трасировки
invoke GetDlgItem,[hwndg], 104 ; адрес edit'a
invoke GetWindowText,eax,IP_BUF,255 ; считать что там введено
mov [schet],1 ; счетчик серверов
traces:
mov ecx,[schet]
stdcall Ping,IP_BUF,ecx ; пропинговать
cmp eax,0 ; если не пингуется
je trace_err ; то
mov eax,[small_buf] ; очистить временный буфер
mov [eax],dword 0
invoke wsprintf,num_buf,formats,[schet] ; типа inttostr
add esp,12 ; для очистки стека. т.к. wsprintf почемуто за собой не очищает его
invoke lstrcat,[small_buf],num_buf ; добавить к малому буферу номер сервера
invoke lstrcat,[small_buf],') ['
invoke inet_ntoa,[Reply.Address] ; определить адрес сервера
invoke lstrcat,[small_buf],eax ; добавить к малому буферу IP адрес сервера
invoke lstrcat,[small_buf],'] '
invoke gethostbyaddr,Reply.Address, 4, AF_INET ; определить имя сервера
cmp eax,0 ; еси имя удалось определить
jne mmmm ; то
invoke lstrcat,[small_buf],'---not host name---' ; добавить в буфер инфу о том что неудалось определить имя сервера
jmp mmmm1
mmmm:
mov eax,[eax]
invoke lstrcat,[small_buf],eax ; добавить к малому буферу имя сервера
mmmm1:
stdcall memo_add,[small_buf],[hwndg] ; вывести малый буфер на экран
inc [schet] ; увеличить счетчик серверов
cmp [Reply.Status],0 ;если это не последний сервер
jne traces ; то
; иначе
stdcall memo_add,'------------------',[hwndg] ;дабовать в мемо инфу
stdcall memo_add,'Трассировка закончена',[hwndg] ; о том что трасировка закончена
pop ecx eax
ret ; возврат из процедуры
trace_err: ; Если истекло время
stdcall memo_add,'Истечение времени ответа',[hwndg] ; вывести ошибку
pop ecx eax
ret ; возврат из процедуры
endp
proc MainProc hwnd,msg,wparam,lparam ; главная диалоговая процедура
push ebx esi edi
; ---------обработка сообщений-----
cmp [msg],WM_COMMAND ; если получина команда
je main_wmcommand
cmp [msg],WM_CLOSE ; если выход
je main_close
xor eax,eax ; еах=0
jmp main_finish ; переход на конец процедуры
main_wmcommand: ; команды
cmp [wparam],BN_CLICKED shl 16+101
je main_go
cmp [wparam],BN_CLICKED shl 16+102
je main_clear
jmp main_processed ; продолжение
main_go: ; начать трассировку
mov eax,[hwnd]
mov [hwndg],eax ; сохранить дискриптор окна (пригодится)
invoke CreateThread,0, 0, trace, 0, 0, handle ; создать поток трассировки (чтобы не вешать прогу)
jmp main_processed ; продолжение
main_clear: ; очистка мемо
mov eax,[memo_buf]
mov [eax],dword 0 ; записть первым символом - 0x00
invoke GetDlgItem,[hwnd], 105
invoke SendMessage,eax, WM_SETTEXT, 3, [memo_buf] ; вывести на экран пустой буфер
jmp main_processed ; продолжение
main_close: ; выход и программы
invoke EndDialog,[hwnd],0 ; закрыть диалог
invoke ExitProcess,0 ; завершить процесс
main_processed: ; продолжение
mov eax,1 ; возврат удачности
main_finish:
pop edi esi ebx
ret
endp
; таблица импорта
section '.idata' import data readable writeable
library kernel32,'KERNEL32.DLL',user32,'USER32.DLL',wsock3 2,'WSOCK32.DLL',icmp,'icmp.dll'
include 'd:\coding\fasm\include\apia\kernel32.inc'
include 'd:\coding\fasm\include\apia\user32.inc'
include 'd:\coding\fasm\include\apia\WSOCK32.inc'
import icmp,IcmpCreateFile,'IcmpCreateFile',\
IcmpSendEcho,'IcmpSendEcho'
; секция ресурсов
section '.rsrc' resource data readable
directory RT_DIALOG,dialogs
resource dialogs,100,LANG_RUSSIAN+SUBLANG_DEFAULT,mainform
dialog mainform,'SLESH TraceRoute for Windows',70,70,447,171,DS_MODALFRAME+WS_MINIMIZEBO X+WS_POPUP+WS_CAPTION+WS_SYSMENU
dialogitem 'BUTTON','TRACE', 101, 353, 2, 45, 14, BS_PUSHBUTTON+BS_FLAT+WS_POPUP+WS_VISIBLE+WS_TABST OP
dialogitem 'BUTTON','CLEAR', 102, 400, 2, 45, 14, BS_PUSHBUTTON+BS_FLAT+WS_POPUP+WS_VISIBLE+WS_TABST OP
dialogitem 'STATIC','Введите IP / HOST:', 103, 6, 4, 81, 11, SS_CENTER+WS_CHILD+WS_VISIBLE+WS_GROUP
dialogitem 'EDIT','', 104, 91, 2, 259, 14, ES_LEFT+WS_CHILD+WS_VISIBLE+WS_BORDER+WS_TABSTOP
dialogitem 'EDIT','', 105, 4, 18, 440, 150, ES_LEFT+ES_MULTILINE+ES_AUTOVSCROLL+ES_AUTOHSCROLL +ES_READONLY+WS_CHILD+WS_VISIBLE+WS_BORDER+WS_VSCR OLL+WS_HSCROLL+WS_TABSTOP
enddialog