Привет. Это моя первая прога на асме. SendMail-заглушка на локальный сервер. Консольный ввод переправляет в файл. Две проблемы, которые, я не могу решить: 1. Файл создается не больше 4096 байт. Надо без ограничений на размер. 2. В начало файла вставляется 4 00 (символ 00h четыре штуки . Проблема _НЕ_ в сервере, а в коде проги. Пожалуйста, помогите. Вот код программы: Код (Text): ;======== ;SendMail ;======== .386 .model flat, stdcall option casemap:none include \masm32\include\windows.inc include \masm32\m32lib\masm32.inc include \masm32\include\kernel32.inc include \masm32\macros\Macros.asm includelib \masm32\m32lib\masm32.lib includelib \masm32\lib\kernel32.lib .data GetDateTime SYSTEMTIME <> timeformat DB "HH-mm-ss", 0 dateformat DB "yyyy-MM-dd_", 0 time DB 16 dup (0) date DB 64 dup (0) bRead DD 0 .data? hInput HANDLE ? hFile HANDLE ? InputBuffer DW 8192 dup(?) .code start: invoke GetStdHandle, STD_INPUT_HANDLE mov hInput, eax invoke SetConsoleMode, hInput, ENABLE_LINE_INPUT or ENABLE_ECHO_INPUT or ENABLE_PROCESSED_INPUT invoke ReadFile, hInput, ADDR InputBuffer, LENGTHOF InputBuffer, ADDR bRead, NULL mov ebx, bRead mov eax, 0 invoke GetLocalTime, ADDR GetDateTime invoke GetTimeFormat, LOCALE_USER_DEFAULT, NULL, ADDR GetDateTime, ADDR timeformat, ADDR time, SIZEOF time invoke GetDateFormat, LOCALE_USER_DEFAULT, NULL, ADDR GetDateTime, ADDR dateformat, ADDR date, SIZEOF date invoke szCatStr, ADDR date, ADDR time invoke szCatStr, ADDR date, SADD (".eml") invoke CreateFile, ADDR date, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL mov hFile, eax invoke WriteFile, hFile, ADDR InputBuffer, ebx, ADDR InputBuffer, NULL invoke CloseHandle, hFile invoke ExitProcess, NULL end start Объясните пжл, почему это происходит
Код (Text): invoke WriteFile, hFile, ADDR InputBuffer, ebx, ADDR InputBuffer, NULL надо: invoke WriteFile, hFile, ADDR InputBuffer, bRead, ADDR bWrite, NULL PS: регистры ebx, esi, edi лучше не менять при работе с WinAPI, а то такие глюки могут пойти, что не поймешь
yureckor Да нет, просто нужно понимать, что делаешь. В Win API callback-функциях эти регистры нужно сохранять и восстанавливать, если изменяешь.
IceStudent ага, до выхода следующей версии винды. лучше стараться следовать спецификации, иначе о долгой жизни проги можно забыть. А вообще несоответствий между версиями дохрена. Например (не очень давно нашел, когда писАл программку, убивающую определенный процесс) CreateToolhelp32Snapshot/Process32First/Process32Next на XP в PROCESSENTRY32.szExeFile выдает имя экзешника, а на 98 полный путь к нему и имя.
yureckor Ну вот. Ты ставишь под сомнение основу основ Win32 API? Вот-вот, а что в спецификации? Читаем соглашение STDCALL. Если мы вызываем stdcall-функцию, то она гарантирует, что сохранит в первоначальном состоянии ebx/esi/edi и некоторые флаги из EFLAGS (DF например), если вызывают нашу stdcall-функцию (при callback например), то мы должны гарантировать то же.
ОК. yureckor Пасиб, кое в чем помог. проблема №2 решена. Код выглядит так Код (Text): .386 .model flat, stdcall option casemap :none include \masm32\include\windows.inc include \masm32\include\kernel32.inc include \masm32\include\masm32.inc includelib \masm32\lib\kernel32.lib includelib \masm32\lib\masm32.lib include \masm32\macros\Macros.asm Main PROTO .data GetDateTime SYSTEMTIME <> timeformat DB "HH-mm-ss", 0 dateformat DB yyyy-MM-dd_", 0 time DB 16 dup (0) date DB 32 dup (0) .code start: invoke Main invoke ExitProcess, NULL Main proc LOCAL InputBuffer[4096] :BYTE LOCAL hInput :DWORD LOCAL bRead :DWORD LOCAL hFile :DWORD LOCAL bWrite :DWORD invoke GetLocalTime, ADDR GetDateTime invoke GetTimeFormat, LOCALE_USER_DEFAULT, NULL, ADDR GetDateTime, ADDR timeformat, ADDR time, SIZEOF time invoke GetDateFormat, LOCALE_USER_DEFAULT, NULL, ADDR GetDateTime, ADDR dateformat, ADDR date, SIZEOF date invoke szCatStr, ADDR date, ADDR time invoke szCatStr, ADDR date, SADD (".eml") invoke GetStdHandle, STD_INPUT_HANDLE mov hInput, eax invoke SetConsoleMode, hInput,ENABLE_LINE_INPUT or ENABLE_ECHO_INPUT or ENABLE_PROCESSED_INPUT invoke ReadFile, hInput, ADDR InputBuffer, LENGTHOF InputBuffer, ADDR bRead, NULL mov eax, bRead invoke CloseHandle, hInput invoke CreateFile, ADDR date, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL mov hFile, eax invoke WriteFile, hFile, ADDR InputBuffer, bRead, ADDR bWrite, NULL mov eax, bWrite invoke CloseHandle, hFile ret Main endp end start Ограничение на 4096 байт осталось. Думаю надо пользовать SetEndOfFile. Нет ли у кого-нибудь толкового примера? PS. Вот это: Код (Text): LOCAL InputBuffer[4096] :BYTE тут не причем. (Ну то есть... понятно, да?)
klakens Хех. Это может и не при чём, а вот это причём: Ты читаешь из Input максимум 4096 байт. Нужно организовать цикл и в нём читать весь буфер. Кстати, не знаю, как насчёт STD_INPUT_HANDLE, но при чтении из выхода другой проги очень просто зависнуть, ожидая эти пресловутые 4096 байт (если она отдала меньше). Нужно узнавать размер данных, подлежащих прочтению, через PeekConsoleInput.
Не-не именно ни причем: сначала было 65536, потом 16384, теперь 4096. А PeekConsoleInput щас поковыряю Пасиб.
Ага, я уже почитал )) Теперь размер письма неограничен (наверное) Отправил себе письмецо ~600 Мб )) peekconsoleinput здесь не нужен. readconsole и readconsoleinput тоже. Всем пасиб )) ЗЫ. Надо купить себе хорошую книгу по асму. А этим пользовался.
invoke WriteFile, hFile, ADDR InputBuffer, bRead, ADDR bWrite, NULL Сделай так: invoke WriteFile, hFile, ADDR InputBuffer, SIZEOF InputBuffer, ADDR bWrite, NULL То есть забей на bRead и bWrite, а InputBuffer помести в секцию data? : .data? InputBuffer db ого-го dup(?)