Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.15.156.140] |
|
Сообщ.
#1
,
|
|
|
FTP–клиент с помощью библиотеки Wininet Для использования ftp протокола в качестве посредника для общения с ftp сервером, в данной статье я буду использовать функции библиотеки WinInet Исходник, предназначен, для соединения с ftp сервером, отображения папок и файлов, перемещения по текущим директориям и скачивания и заливки файлов. Основные функции библиотеки WinInet для общения с ftp сервером, я не буду описывать, а прокомментирую в ниже приведённом коде. Только упомяну, что вместо функций FtpPutFile и FtpGetFile, я использовала InternetWriteFile и InternetReadFile – соответственно, для подсчёта и отображения, залитых и скачанных байт. Итак, FtpClient: .386 .model flat,stdcall option casemap:none include \masm32\include\windows.inc include \masm32\include\user32.inc include \masm32\include\kernel32.inc include \masm32\include\wininet.inc includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib includelib \masm32\lib\wininet.lib _T macro p1, p2 ;макрос обработки строк local l ifb <p2>; Строка без имени .data l db p1, 0 .code exitm <addr l> else ; Строка с именем .data p1 db p2, 0 .code exitm <addr p1> endif endm IDC_Glav equ 1000 ;окно данных IDC_GETHOST equ 1001 ;host IDC_Dir equ 1002 ;dir IDC_User equ 1003 ;user IDC_Pass equ 1004 ;pass IDC_Connect equ 1005 ;connect IDC_Setdir equ 1006 ;setdir IDC_Disconnect equ 1007 ;disconnect IDC_EXIT equ 1008 ;exit IDC_PutFileName equ 1009 ;putfile IDC_GetFilename equ 1010 ;nameputfile SizeGetPutFile equ 1011 ;statictext для отображени процесса Write/Read - byte ObshiySize equ 1012 ;размер файлов ;------------------------------------------------------------------------- treadftpfind PROTO ;поток для поиска файлов threadprocdownloadfile PROTO ;поток для скачивания файла threadprocputfile PROTO ;поток для заливки файла ;оконная процедура WndProc PROTO :DWORD, :DWORD, : DWORD,:DWORD ;процедура поиска директорий и файлов FindFTPFiles PROTO :DWORD, :DWORD ;сообщение в лист бокс MESSG PROTO :HWND, :DWORD ;обработка клика по строчке в листбоксе ListBoxProc PROTO :HWND, :UINT, :WPARAM, :LPARAM .data ;------------------------------------------------------------------------- pdwNumberOfBytesWritten dd 0 ;для записи файла ObshiyBuffer dd 0 ;подсчёта байт при скачивании ObshiyBufferPut dd 0 ;и залвики wNumberOfBytesToRead dd 0;сколько считали байт ReadByteFilePut dd 0 CountBytesWrite dd 0;сколько записали байт AgetUser db 'FtpClient',0;название клиент-программы hInstance dd 0 ;декрипторы соединений hInternet dd 0 hConnect dd 0 ;декрипторы файлов FileOpenchtobPut dd 0;хандл файла для чтения и размера с диска hInetFileHandle dd 0;хандл файла для скачивания и размера FileOpenPut dd 0;созданный файл на сервере для заливки hFile dd 0;для записи на диск hFileConnection dd 0;файл для поиска FIND_DATA WIN32_FIND_DATA <?>;структура файла ;для потоков jdownftp dd 0 jputfile dd 0 jfindftp dd 0 ;размеры файлов lpdwFileSizeHigh dd 0 lpFileSizeHigh dd 0 ;---------------------------------------------------------------------------------- .data? ;---------------------------------------------------------------------------------- User db 1024 dup (?);Логин Pass db 1024 dup (?);Пароль StrokaIz db 1024 dup (?);Хост BufferReadPut db 1024 dup (?) BufferFile db 1024 dup (?) NameFilePut db 1024 dup (?) BufferDir db 1024 dup (?) lpfnEditProc HWND ? hDlg HWND ? .code start: ;-------------------------------------------------------------------------------- invoke GetModuleHandle, NULL mov hInstance, eax invoke DialogBoxParam, hInstance, _T("MAINDIALOG"), 0, addr WndProc, 0 invoke ExitProcess, eax ;-------------------------------------------------------------------------------- WndProc proc hWnd :DWORD, uMsg :DWORD, wParam :DWORD, lParam :DWORD .if uMsg == WM_INITDIALOG invoke SendMessage, hWnd, WM_SETTEXT, NULL, _T("FTP клиент") mov eax, hWnd mov hDlg, eax ; хэндл окна нам еще понадобится :) ; сабклассируем контрол EDIT invoke GetDlgItem, eax, IDC_Glav ; для кликанья в лист боксе ;) invoke SetWindowLong,eax, GWL_WNDPROC, addr ListBoxProc mov lpfnEditProc, eax ; сохраняем адрес предыдущей функции .elseif uMsg==WM_COMMAND mov eax, wParam mov edx, eax;нажатие кнопок shr edx, 16 .if edx == BN_CLICKED ;--------------------------------------------------------------------------------------- .if ax == IDC_Connect;подключаемся к серверу и выводи все папки и файлы invoke InternetOpen,addr AgetUser,INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0 mov hInternet, eax ;берём ip, login, pass invoke GetDlgItemText, [hWnd], IDC_User, addr User,-1 invoke GetDlgItemText, [hWnd], IDC_Pass, addr Pass,-1 invoke GetDlgItemText, [hWnd], IDC_GETHOST,addr StrokaIz,-1 ;заполняем данными для подключенияи вперёд ;) invoke InternetConnect, [hInternet],\;Дескриптор, полученный вызовом предыдущей функции. addr StrokaIz,\;хост INTERNET_DEFAULT_FTP_PORT,\; 21 addr User,addr Pass,\;логин , пароль INTERNET_SERVICE_FTP,\;Тип сервиса 0,\ 0 mov hConnect, eax;сохраняем дескриптор ;берём директорию из контрола "/" invoke GetDlgItemText, [hWnd],IDC_Dir,addr BufferDir,-1 invoke FindFTPFiles,[hConnect] ,addr BufferDir ;ищем все файлы и папки .endif ;----------------------------------------------------------------------------------------- ;смена директории .if ax == IDC_Setdir;берём название директориииз контрола invoke GetDlgItemText, hWnd,IDC_Dir, addr BufferDir,-1 invoke FindFTPFiles, [hConnect] , addr BufferDir ;ищем все файлы и папки .endif ;----------------------------------------------------------------------------------------------- .if ax == IDC_Disconnect invoke InternetCloseHandle, hConnect .endif ;------------------------------------------------------------------------------------------- ;закачиваем файл на сервер .if ax == IDC_PutFileName ;берём название файла invoke GetDlgItemText, hWnd,IDC_GetFilename,addr NameFilePut,-1 ;спрашиваем этот файл залить, малоли вдруг ошиблись ;) invoke MessageBox,[hWnd],offset NameFilePut,_T('Залить файл?'), MB_OKCANCEL .if ax == TRUE;если пользователь действительно хочет скачать выбранный файл invoke CreateFile,ADDR NameFilePut,\;открываем файл для чтения GENERIC_READ,\ FILE_SHARE_READ,\ NULL,\ OPEN_ALWAYS,\ 0,\ NULL; mov FileOpenchtobPut, eax;сохраняем хэндл ;узнаём размер файла invoke GetFileSize,[FileOpenchtobPut],addr lpFileSizeHigh mov lpFileSizeHigh, eax ;корректный размер invoke SetDlgItemInt,[hDlg],ObshiySize,lpFileSizeHigh ,1 ;создаём файл на сервере с соответствующим названием, для записи invoke FtpOpenFile,[hConnect],offset NameFilePut,GENERIC_WRITE ,\ FTP_TRANSFER_TYPE_UNKNOWN,\;выбран как бинарь ;) INTERNET_FLAG_NEED_FILE mov FileOpenPut , eax;сохраняем дескриптор для заливки файла ;открываем поток для заливки файла, отображения залитых байт и чтобы не тормозило ;) invoke CreateThread,0,0, offset threadprocputfile,0,0,offset jputfile .else .endif .endif ;------------------------------------------------------------------------- .if ax == IDC_EXIT;выход invoke InternetCloseHandle,hConnect invoke SendMessage, hWnd, WM_CLOSE, 0, 0 .endif .endif .elseif uMsg == WM_CLOSE invoke InternetCloseHandle,hConnect invoke EndDialog,hWnd,0 .else mov eax, FALSE ret .endif mov eax, TRUE ret WndProc endp ;------------------------------------------------------------------------------------------------ ;процедура поиска файлов и папок FindFTPFiles proc FConnect:DWORD, Dir:DWORD ;хэндл и выбранная директория invoke GetDlgItem, hDlg, IDC_Glav ;отчищаем листбокс invoke SendMessage, eax, LB_RESETCONTENT, 0, 0 ;смена директории invoke FtpSetCurrentDirectory, [FConnect], Dir ;поиск всего ;) invoke FtpFindFirstFile, [FConnect],_T('*.*'),addr FIND_DATA,INTERNET_FLAG_NEED_FILE , 0 mov hFileConnection ,eax ;обнуляем структуру invoke RtlZeroMemory, addr FIND_DATA, SizeOf(WIN32_FIND_DATA) .repeat ;функции поиска и заполнения данными структуры ВИНДАТ и добавления в листбокс invoke MESSG , [hDlg], addr (FIND_DATA.cFileName) invoke InternetFindNextFile,[hFileConnection],offset FIND_DATA .until eax==FALSE invoke InternetCloseHandle,hFileConnection;закрываем поюзанный хэндл :) ret FindFTPFiles endp ;-------------------------------------------------------------------------------------------- ;обработка двойного нажатия клика мыши на строчку в листбоксе ListBoxProc proc hCtl: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM LOCAL IndexItem :DWORD;номер строки mov eax, wParam ;двойной клик по строчке в листбоксе .if ( uMsg == WM_LBUTTONDBLCLK ) ;номер строчки invoke SendMessage,hCtl,LB_GETCURSEL,0,0 mov IndexItem, eax ;извлекаем текст из кликнутой строчке :)) invoke SendMessage,hCtl,LB_GETTEXT,IndexItem,ADDR BufferDir ;обнуляем структуру invoke RtlZeroMemory, addr FIND_DATA, SizeOf(WIN32_FIND_DATA) invoke FtpFindFirstFile, [hConnect],ADDR BufferDir, offset FIND_DATA,INTERNET_FLAG_RESYNCHRONIZE , 0 mov hFileConnection ,eax .if FIND_DATA.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY invoke InternetCloseHandle,hFileConnection ;поток поиска файлов в директории invoke CreateThread,0,0, offset treadftpfind ,0,0,offset jfindftp jmp EXITPROC .else .endif ;спрашиваем действительно ли пользователь хочет скачать файл invoke MessageBox,[hCtl], ADDR BufferDir,_T('Скачать файл?'), MB_OKCANCEL .if ax == TRUE ;открываем файл на сервере для чтения invoke FtpOpenFile,[hConnect],ADDR BufferDir,GENERIC_READ ,\ FTP_TRANSFER_TYPE_UNKNOWN,\ NULL mov [hInetFileHandle], eax ;запрашиваем размер файла с сервера invoke FtpGetFileSize,[hInetFileHandle] ,\ offset lpdwFileSizeHigh mov lpdwFileSizeHigh,eax invoke SetDlgItemInt,[hDlg],ObshiySize, lpdwFileSizeHigh ,1 ;создаём файл для записи закачанных байт invoke CreateFile,ADDR BufferDir,\ GENERIC_WRITE,\ FILE_SHARE_WRITE,\ NULL,\ OPEN_ALWAYS,\ 0,\ NULL mov hFile , eax ;поток скачивания invoke CreateThread,0,0, offset threadprocdownloadfile ,0,0,offset jdownftp .else EXITPROC: .endif .endif ; нажата любая другая клавиша, вызываем старую функцию контрола invoke CallWindowProc, lpfnEditProc, hCtl, uMsg, wParam, lParam ret ListBoxProc endp ;-------------------------------------------------------------------------------------------- ;посылка сообщения в лист бокс MESSG proc hWnd: HWND, message: DWORD invoke GetDlgItem, hDlg, IDC_Glav push eax invoke SendMessage, eax, LB_ADDSTRING, 0, message pop ecx invoke SendMessage, ecx, LB_SETTOPINDEX, eax, 0 ret MESSG endp ;---------------------------------------------------------------------------------------------- ;поток входа в папку на ftp и поиска всех файлов и папок в текущей директории treadftpfind proc invoke SetDlgItemText, [hDlg] ,IDC_Dir, addr BufferDir;смена названия директории в Edit invoke FindFTPFiles, [hConnect] , addr BufferDir ;ищем все файлы и папки ret treadftpfind endp ;---------------------------------------------------------------------------------------------- ;поток скачивания файла с ftp - сервера threadprocdownloadfile proc ;обнуляем общий буфер, который играет немаловажную роль для подсчёта скачанных байт :) mov ObshiyBuffer, 0h .repeat;цикл закачки с постусловием invoke InternetReadFile,[hInetFileHandle],\;функция считывает в буфер байтики addr BufferFile,\;буфер для чтения sizeof BufferFile ,\;размер буфера addr wNumberOfBytesToRead;считаных байт ;считаем сколько всего закачалось из файла в каждый момент времени 1024 буф. mov eax, ObshiyBuffer;общий буфер в регистр для сложения add eax, CountBytesWrite mov ObshiyBuffer , eax ;результат в общий буфер ;выводим в контрол сколько же мы уже скачали invoke SetDlgItemInt,[hDlg],SizeGetPutFile, ObshiyBuffer , 1 ;запись файла на диск; дескриптор созданного файла, буфер, размер буфера, записанных байт invoke WriteFile, [hFile],addr BufferFile ,wNumberOfBytesToRead, addr CountBytesWrite , NULL .until wNumberOfBytesToRead == 0 ;качаем файл пока не закончится ^ всё равно запишется ноль ;) ;закрываем дескриптор скачиваемого и сзданного файла invoke CloseHandle, hFile invoke InternetCloseHandle, hInetFileHandle ret threadprocdownloadfile endp ;--------------------------------------------------------------------------------------------- ;поток, чтобы положить файл на сервант ;) threadprocputfile proc mov ObshiyBufferPut, 0h;обнуляем ;читаем файл пока не закончится .repeat ;функция чтения файла с диска invoke ReadFile,[FileOpenchtobPut],\ addr BufferReadPut,\ ;буфер для данных sizeof BufferReadPut,\ ;его размер addr ReadByteFilePut,\ ;сколько считали NULL ;считаем сколько считали и поидеи должны отправить ;) mov eax, ObshiyBufferPut add eax, ReadByteFilePut mov ObshiyBufferPut , eax ;заливаем invoke InternetWriteFile,[FileOpenPut],\;хэндл вернувшийся после гуляния с фун-ей FtpOpenFile addr BufferReadPut,\;буфер записывания :) ReadByteFilePut,\;размер addr pdwNumberOfBytesWritten;сколько положили ;выводим так как очень интересно :) invoke SetDlgItemInt,[hDlg],SizeGetPutFile, ObshiyBufferPut , 1 ;когда-нибудь да он закончится .until ReadByteFilePut==0 ;закрываем теперь уже не нужные дескрипторы invoke CloseHandle, FileOpenchtobPut invoke InternetCloseHandle, FileOpenPut ret threadprocputfile endp end start #define IDD_DLG1 MAINDIALOG #define IDC_EDT1 1001 #define IDC_LST1 1000 #define IDC_STC1 10003 #define IDC_EDT2 1003 #define IDC_EDT3 1004 #define IDC_EDT4 1002 #define IDC_BTN1 1009 #define IDC_BTN2 1005 #define IDC_BTN3 1006 #define IDC_STC2 10010 #define IDC_STC3 10011 #define IDC_STC4 10012 #define IDC_STC5 10013 #define IDC_EDT5 1010 #define IDC_STC6 10014 #define IDC_STC7 1011 #define IDC_BTN4 1007 #define IDC_BTN5 1008 #define IDC_STC8 1013 #define IDC_STC9 1012 IDD_DLG1 DIALOGEX 6,5,397,240 CAPTION "IDD_DLG" FONT 8,"MS Sans Serif",0,0 STYLE 0x10CF0000 BEGIN CONTROL "127.0.0.1",IDC_EDT1,"Edit",0x50010000,298,12,54,13,0x00000200 CONTROL "",IDC_LST1,"ListBox",0x50010141,2,1,256,235,0x00000200 CONTROL "NamePutFile",IDC_STC1,"Static",0x50000000,300,84,54,9 CONTROL "",IDC_EDT2,"Edit",0x50010000,264,40,54,13,0x00000200 CONTROL "",IDC_EDT3,"Edit",0x50010000,334,40,54,13,0x00000200 CONTROL "/",IDC_EDT4,"Edit",0x50010000,300,68,56,13,0x00000200 CONTROL "PutFile",IDC_BTN1,"Button",0x50010000,300,116,54,13 CONTROL "Connect",IDC_BTN2,"Button",0x50010000,270,204,54,13 CONTROL "SetDir",IDC_BTN3,"Button",0x50010000,270,221,54,13 CONTROL "Host",IDC_STC2,"Static",0x50000000,298,0,54,9 CONTROL "Login",IDC_STC3,"Static",0x50000000,266,27,54,9 CONTROL "Pass",IDC_STC4,"Static",0x50000000,336,27,54,9 CONTROL "Dir",IDC_STC5,"Static",0x50000000,302,55,54,9 CONTROL "LINK.EXE",IDC_EDT5,"Edit",0x50010000,300,99,54,13,0x00000200 CONTROL "SizeProc",IDC_STC6,"Static",0x50000000,300,169,54,9 CONTROL "0",IDC_STC7,"Static",0x50000000,300,182,54,9 CONTROL "Disconnect",IDC_BTN4,"Button",0x50010000,328,204,54,13 CONTROL "Exit",IDC_BTN5,"Button",0x50010000,328,221,54,13 CONTROL "Размер",IDC_STC8,"Static",0x50000000,300,142,54,11 CONTROL "0",IDC_STC9,"Static",0x50000000,300,156,54,9 END rc.exe Dlg.rc E:\masm32\BIN\FTPConnect\ml /c /coff FtpC.asm E:\masm32\BIN\FTPConnect\Link /SUBSYSTEM:WINDOWS FtpC.obj Dlg.RES pause Если вы пожертвуете в фонд проекта возможно я добавлю докачку и скачивание папок. ( шучу ) |