Точка входа API драйвера IPX/SPX
Для того чтобы проверить, загружен ли драйвер IPX, необходимо загрузить в регистр AX значение 7A00h и вызвать мультиплексное прерывание INT 2Fh.
Если после возврата из прерывания в регистре AL будет значение FFh, драйвер IPX загружен. Адрес точки входа для вызова API драйвера при этом будет находиться в регистровой паре ES:DI.
Если же содержимое регистра AL после возврата из прерывания INT 2Fh будет отлично от FFh, драйвер IPX/SPX не загружен. Это означает, что на данной рабочей станции не загружены резидентные программы ipx.exe или ipxodi.exe, обеспечивающие API для работы с протоколами IPX и SPX.
Для вызова API в регистр BX необходимо загрузить код выполняемой функции. Значения, загружаемые в другие регистры, зависят от выполняемой функции.
Например, функция с кодом 10h используется для проверки присутствия в системе протокола SPX (может быть такая ситуация, когда протокол IPX присутствует, а SPX - нет). Для того, чтобы определить наличие SPX, необходимо загрузить в BX значение 10h, в AX значение 00h и вызвать API драйвера IPX. Если после возврата регистр AX будет содержать значение FFh, протокол SPX присутствует и может быть использован. В регистрах CX и DX передаются параметры SPX - максимальное число каналов связи, которое данная станция может установить с программами, работающими на других станциях, и количество каналов, доступное в настоящее время. О назначении этих параметров мы будем говорить в главе, посвященной протоколу SPX.
Приведем текст программы, определяющей наличие драйвера протоколов IPX и SPX (листинг 1). Программа вызывает функции ipx_init() и ipxspx_entry(), тексты которых находятся в листинге 2. Текст сокращенного варианта include-файла ipx.h представлен в листинге 3.
Вы можете попробовать запустить эту программу на рабочей станции сети Novell NetWare под управлением MS-DOS или на виртуальной машине MS Windows, работающей в расширенном (Enchanced) режиме.
// =================================================== // Листинг 1.
Программа для обнаружения драйвера // протокола IPX/SPX и определения его версии // // Файл ipxver.c // // (C) A. Frolov, 1993 // ===================================================
#include <stdio.h> #include <stdlib.h> #include "ipx.h"
void main(void) {
// Точка входа в IPX/SPX API, переменная находится // в файле ipxdrv.asm и инициализируется функцией ipx_init().
extern far char *ipxspx_drv_entry;
// Структура для вызова API IPX
struct IPXSPX_REGS iregs;
unsigned error; unsigned spx_ver; unsigned spx_max_connections, spx_avail_connections;
printf("\n*Детектор IPX/SPX*, (C) Фролов А., 1993\n\n");
// Проверяем наличие драйвера IPX и определяем // адрес точки входа его API
if(ipx_init() == 0xff) printf("IPX загружен! "); else { printf("IPX не загружен!\n"); exit(-1); } printf("Точка входа в IPX API - %Fp\n",ipxspx_drv_entry);
// Проверяем доступность протокола SPX
error = NO_ERRORS;
// Вызываем функцию проверки доступности SPX // Здесь мы вызываем API драйвера IPX/SPX
iregs.bx = SPX_CMD_INSTALL_CHECK; iregs.ax = 0; ipxspx_entry( (void far *)&iregs );
if(iregs.ax == 0x00) error = ERR_NO_SPX; if(iregs.ax != 0xff) error = UNKNOWN_ERROR;
if(error != NO_ERRORS) { printf("SPX не загружен!\n"); exit(-1); }
// Запоминаем параметры IPX/SPX
spx_ver = iregs.bx; spx_max_connections = iregs.cx; spx_avail_connections = iregs.dx;
printf("SPX загружен! "); printf("Версия SPX: %d.%d\n", (spx_ver>>8) & 0xff, spx_ver & 0xff); printf("Всего соединений: %d, ", spx_max_connections); printf("из них доступно: %d\n", spx_avail_connections);
exit(0); }
Далее расположен исходный текст модуля инициализации IPX (листинг 2).
В этом модуле находится функция ipxspx_entry(), необходимая для вызова драйвера IPX/SPX. Ее имя начинается с символа "_", что необходимо для выполнения соглашения об именах в языке Си.
Здесь же имеется функция ipx_init(), которая проверяет наличие драйвера в системе, получает адрес API драйвера и сохраняет его в области памяти _ipxspx_drv_entry.
; =================================================== ; Листинг 2. Инициализация и вызов драйвера IPX/SPX ; Файл ipxdrv.asm ; ; (C) A. Frolov, 1993 ; ===================================================
.286 .MODEL SMALL ; --------------------------------------- ; Структура для вызова драйвера IPX/SPX ; ---------------------------------------
IPXSPX_REGS struc rax dw ? rbx dw ? rcx dw ? rdx dw ? rsi dw ? rdi dw ? res dw ? IPXSPX_REGS ends
.DATA
; Точка входа в драйвер IPX/SPX
_ipxspx_drv_entry dd ?
.CODE
PUBLIC _ipxspx_entry, _ipx_init PUBLIC _ipxspx_drv_entry
; --------------------------------------- ; Процедура, вызывающая драйвер IPX/SPX ; ---------------------------------------
_ipxspx_entry PROC FAR
; Готовим BP для адресации параметра функции
push bp mov bp,sp
; Сохраняем регистры, так как драйвер IPX/SPX ; изменяет содержимое практически всех регистров
push es push di push si push dx push cx push bx push ax
; Загружаем регистры из структуры, ; адрес которой передается как параметр
push ds mov bx, [bp+6] ; смещение mov ds, [bp+8] ; сегмент mov es, ds:[bx].res mov di, ds:[bx].rdi mov si, ds:[bx].rsi mov dx, ds:[bx].rdx mov cx, ds:[bx].rcx mov ax, ds:[bx].rax mov bx, ds:[bx].rbx pop ds
; Вызываем драйвер IPX/SPX
call [dword ptr _ipxspx_drv_entry]
; Сохраняем регистры
push ds push dx mov dx, bx
; Записываем в структуру содержимое регистров после вызова драйвера
mov bx, [bp+6] ; смещение mov ds, [bp+8] ; сегмент mov ds:[bx].rax, ax mov ds:[bx].rcx, cx mov ds:[bx].rbx, dx pop dx mov ds:[bx].rdx, dx pop ds
; Восстанавливаем регистры
pop ax pop bx pop cx pop dx pop si pop di pop es
pop bp retf _ipxspx_entry ENDP
; --------------------------------------------- ; Процедура инициализации драйвера IPX/SPX ; ---------------------------------------------
_ipx_init PROC NEAR push bp mov bp,sp
; Определяем наличие драйвера в системе и его точку входа
mov ax, 7a00h int 2fh
; Если драйвера нет, завершаем процедуру
cmp al, 0ffh jne _ipx_init_exit
; Сохраняем адрес точки входа
mov word ptr _ipxspx_drv_entry+2, es mov word ptr _ipxspx_drv_entry, di
_ipx_init_exit:
; В регистре AX - код завершения процедуры
mov ah, 0 pop bp ret _ipx_init ENDP end
Описания типов и констант, а также прототипы функций для программы ipxver.c находятся в файле ipx.h (листинг 3).
// =================================================== // Листинг 3. Include-файл для работы с IPX // Сокращенный вариант для программы ipxver.c // Файл ipx.h // // (C) A. Frolov, 1993 // ===================================================
// ----------------------- // Команды интерфейса IPX // -----------------------
#define IPX_CMD_OPEN_SOCKET 0x00 #define IPX_CMD_CLOSE_SOCKET 0x01 #define IPX_CMD_GET_LOCAL_TARGET 0x02 #define IPX_CMD_SEND_PACKET 0x03 #define IPX_CMD_LISTEN_FOR_PACKET 0x04 #define IPX_CMD_SCHEDULE_IPX_EVENT 0x05 #define IPX_CMD_CANCEL_EVENT 0x06 #define IPX_CMD_GET_INTERVAL_MARKER 0x08 #define IPX_CMD_GET_INTERNETWORK_ADDRESS 0x09 #define IPX_CMD_RELINQUISH_CONTROL 0x0a #define IPX_CMD_DISCONNECT_FROM_TARGET 0x0b
// ----------------------- // Команды интерфейса SPX // -----------------------
#define SPX_CMD_INSTALL_CHECK 0x10
// ----------------------- // Коды ошибок // -----------------------
#define NO_ERRORS 0 #define ERR_NO_IPX 1 #define ERR_NO_SPX 2 #define NO_LOGGED_ON 3 #define UNKNOWN_ERROR 0xff
// ----------------------- // Константы // -----------------------
#define SHORT_LIVED 0 #define LONG_LIVED 0xff #define IPX_DATA_PACKET_MAXSIZE 546
// Внешние процедуры для инициализации и вызова драйвера IPX/SPX
void far ipxspx_entry(void far *ptr); int ipx_init(void);
// Структура для вызова драйвера IPX/SPX
struct IPXSPX_REGS { unsigned int ax; unsigned int bx; unsigned int cx; unsigned int dx; unsigned int si; unsigned int di; unsigned int es; };
Содержание раздела