Раньше никогда не сталкивался с необходимостью осваивать WinAPI в части работы с COM-портами, другие способы коммуникации как-то больше волновали. А теперь вот не могу справится с простейшей на мой первоначальный взгляд задачей - реализация асинхронного обмена через "банальный" COM-порт. К COM-порту подключен модем, "понимающий" стандартный набор AT-команд. Вот и решил я далеко не ходить и не разгребать глюки готовых классов и модулей, реализованных другими разработчиками. Лицензионные продукты для своей простой задачи не вижу смысла покупать. Вот пал выбор на WinAPI. Вроде бы и информации в сети валом и msdn внимательно почитал, но у меня то ли неправильно выстроился алгоритм программы то ли дядюшка билли со своими извращенными алгоритмами всевозможных ограничений прав доступа к памяти мешает. Прошу помощи.
Успешно открываю порт
Код
-- kernel32 - подгружаемая библиотека WinAPI-функций
-- comid - номер открываемого порта
-- handle - итоговый указатель на порт
handle = kernel32.CreateFileA("\\\\.\\COM" .. comid, GENERIC_READ+GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0)
Далее я создаю и заполняю структуры BCD и COMMTIMEOUTS. Сохраняю настройки с помощью функций SetCommState, SetCommTimeouts - обе возвращают TRUE.
Код
DCB.BaudRate = CBR_9600;
DCB.ByteSize = 8;
DCB.Parity = NOPARITY;
DCB.StopBits = ONESTOPBIT;
DCB.fBinary = 1;
DCB.fOutxCtsFlow = 0;
DCB.fOutxDsrFlow = 0;
DCB.fDtrControl = DTR_CONTROL_DISABLE;
DCB.fDsrSensitivity = 0;
DCB.fNull = 0;
DCB.fRtsControl = RTS_CONTROL_DISABLE;
DCB.fAbortOnError = 0;
COMMTIMEOUTS.ReadIntervalTimeout = 10;
COMMTIMEOUTS.ReadTotalTimeoutMultiplier = 1;
COMMTIMEOUTS.ReadTotalTimeoutConstant = 100;
COMMTIMEOUTS.WriteTotalTimeoutMultiplier = 0;
COMMTIMEOUTS.WriteTotalTimeoutConstant = 0;
Далее пытаюсь отправить данные в порт
Код
-- data - массив с данными
-- b - указатель на переменную типа DWORD "счетчик байт"
-- t - указатель на буфер с данными
-- n - кол-во данных в массиве data
local n = Table.Count(data);
local b = MemoryEx.Allocate(4);
local t = MemoryEx.Allocate(n);
if (b and t) then
-- сброс счетчика байт
MemoryEx.Fill(b, 4, 0, MEMEX_BYTE);
-- заполнение буфера данными из массива data
local c = 1;
repeat
MemoryEx.Byte(t + c - 1, data[c]);
c = c + 1;
until c > n;
-- запись в порт
if (kernel32.WriteFile(handle, t, n, b, 0) == 0) then
local e = kernel32.GetLastError();
Dialog.Message("error", e);
end
end
После попытки записать что-либо в порт функция возвращает 5, т.е. ACCESS DENIED. Что я упустил?