Определение доступных портов
Драйвер асинхронного последовательного адаптера VCD предоставляет приложениям Windows программный интерфейс через точку входа, адрес которой можно определить, вызвав мультиплексное прерывание INT 2Fh.
Реализация этих функций зависит от конкретного драйвера VCD. Если у вас установлен драйвер, не совместимый с драйвером VCD из DDK, то эти функции могут не работать.
В листинге 7.3. мы приводим исходный текст приложения FINDPORT, которое определяет порты асинхронного последовательного адаптера, доступные приложениям Windows, посредством вызова функции драйвера VCD.
Листинг 7.3. Файл FINDPORT.CPP
#define STRICT
#include <windows.h>
#include <bwcc.h>
// Прототип функции
BYTE FAR FindCOMPorts( void );
// =========================================================
// Функция WinMain
// =========================================================
#pragma argsused
int PASCAL
WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow )
{
char szMsg[ 60 ] = "";
BYTE bFindPort;
// Определяем работает ли Windows в расширенном режиме
if(GetWinFlags() & WF_ENHANCED)
{
bFindPort = FindCOMPorts();
for (int i = 0; i < 8; i++)
{
if (bFindPort & (BYTE) (1 << (BYTE)i))
wsprintf( szMsg, "%sCOM%d ", (LPSTR) szMsg, i + 1 ) ;
}
BWCCMessageBox(NULL,
szMsg, "Обнаружены COM-порты:",
MB_OK | MB_ICONINFORMATION);
}
else
BWCCMessageBox(NULL,
"Зпустите Windows в расширенном режиме", "Сообщение",
MB_OK | MB_ICONSTOP);
return 0;
}
После запуска приложения, WinMain вызывает функцию GetWinFlags для определения режима работы Windows. Если Windows работает в стандартном режиме, приложение выводит соответствующее сообщение и завершает свою работу.
Если Windows работает в расширенном режиме, выполняется вызов функции FindCOMPorts, определяющей список доступных COM-портов. Затем полученный список доступных портов отображается на экране.
Функция FindCOMPorts возвращает байт, каждый бит которого отвечает за свой COM-порт. Младший бит соответствует порту COM1, а старший COM8. Исходный текст функции FindCOMPorts представлен в листинге 7.4.
Листинг 7.4. Файл COMM_DRV.CPP
#include <windows.h>
#include "comm_drv.h"
// Идентификатор драйвера асинхронного последовательного
// адаптера
#define VCD_Device_ID 0x0E
// ===========================================================
// Функция FindCOMPorts вызывает драйвер асинхронного адаптера
// и определяет какие COM-порты установлены в компьютере и
// доступны для использования
// ===========================================================
BYTE FAR FindCOMPorts( void )
{
BYTE bResult;
FARPROC lpCOMM;
asm {
// Определяем адрес точки входа программного интерфейса
// драйвера асинхронного последовательного адаптера
mov ax, 1684h
mov bx, VCD_Device_ID
xor di, di
mov es, di
int 2Fh
// Проверяем значение регистров ES:DI
mov ax, es
or ax, di
// Если в регистрах ES:DI записаны нулевые значения,
// драйвер не имеет программного интерфейса и не доступен
jz FunctionFailed
// Драйвер доступен, сохраняем адрес его интерфейса в
// переменной lpCOMM
mov word ptr lpCOMM, di
mov word ptr lpCOMM+2, es
// Вызываем функцию из драйвера COM-порта
mov dx, 1
call dword ptr lpCOMM
// Сохраняем результат, полученный в регистре AL
mov bResult, al
// Завершаем выполнение функции
jmp FunctionQuit
}
FunctionFailed:
asm {
// В случае возникновения ошибки возвращаем нулевое
// значение
mov bResult, 0
}
FunctionQuit:
return( bResult ) ;
}
В исходном тексте функции FindCOMPorts нет ни вызова функции OpenComm, ни вызовов других телекоммуникационных функций, она содержит только десяток строк на языке ассемблера. Рассмотрим функцию FindCOMPorts подробней.
Сначала вызывается функция 1684h мультиплексного прерывания INT 2Fh. Для нее в регистре BX передается константа VCD_Device_ID, означающая, что необходимо получить точку входа для драйвера VCD.
mov ax, 1684h
mov bx, VCD_Device_ID
xor di, di
mov es, di
int 2Fh
Если после вызова мультиплексного прерывания в регистрах ES:DI сохраняются нулевые значения, значит драйвер VCD не поддерживает программный интерфейс и, следовательно, мы не можем получить к нему доступ. В этом случае возвращаем нулевое значение.
Если содержимое регистров ES:DI не равно нулю, значит драйвер VCD доступен. Сохраняем адрес точки входа его интерфейса в переменной lpCOMM:
mov word ptr lpCOMM, di
mov word ptr lpCOMM+2, es
Затем вызываем функцию из драйвера VCD, предварительно записав в регистр DX значение 1.
mov dx, 1
call dword ptr lpCOMM
После возвращения из этой функции по содержимому регистра AL можно определить, какие из портов асинхронного последовательного адаптера доступны для использования.
Затем мы завершаем выполнение функции FindCOMPorts и возвращаем значение регистра AL.
Файл определения модуля приложения FINDPORT приведен в листинге 7.5.
Листинг 7.5. Файл FINDPORT.DEF
; =============================================================
; Файл определения модуля
; =============================================================
NAME OPENCOMM
DESCRIPTION 'Приложение FINDPORT, (C) 1994, Frolov G.V.'
EXETYPE windows
STUB 'winstub.exe'
STACKSIZE 5120
HEAPSIZE 1024
CODE preload moveable discardable
DATA preload moveable multiple