Использование протоколов IPX, SPX, NETBIOS

       

Точка входа 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; };


Содержание раздела