ChainEntries: array[0..MAX_PROTOCOL_CHAIN - 1] of DWORD;
end;
//Структура на C++ содержит тип TCHAR, который, как мы
// говорили в главе 1, может означать как Char,
// так и WideChar, т.е. структура должна иметь
// два варианта описания: TWSAProtocolInfoA для
// однобайтной кодировки и TWSAProtocolInfo для
// двухбайтной. Соответственно, все функции
// использующие эту структуру, реализованы
// в системных библиотеках в двух вариантах.
// Здесь мы приводим только ANSI-вариант.
PWSAProtocolInfo = ^TWSAProtocolInfo;
TWSAProtocolInfo = packed record
dwServiceFlags1: DWORD;
dwServiceFlags2: DWORD;
dwServicsFlags3: DWORD;
dwServiceFlags4: DWORD;
dwProviderFlags: DWORD;
ProviderId: GUID;
dwCatalogEntryId: DWORD;
ProtocolChain: TWSAProtocolChain;
iVersion: Integer;
iAddressFamily: Integer;
iMaxSockAddr: Integer;
iMinSockAddr: Integer;
iSocketType: Integer;
iProtocol: Integer;
iProtocolMaxOffset: Integer;
iNetworkByteOrder: Integer;
iSecurityScheme: Integer;
dwMessageSize: DWORD;
dwProviderReserved: DWORD;
szProtocol: array [0..WSAPROTOCOL_LEN] of Char;
end;
Расшифровка полей типа
TWSAProtocolInfo
есть в MSDN, мы здесь не будем ее приводить.
Сама функция
WSAEnumProtocols
, которая позволяет получить список всех протоколов, провайдеры которых установлены на компьютере, приведена в листинге 2.37.
Листинг 2.37. Функция
WSAEnumProtocols
// ***** описание на C++ *****
int WSAEnumProtocols(LPINT lpiProtocols, LPWSAPROTOCOL_INFO lpProtocolBuffer, LPDWORD lpdwBufferLength);
// ***** Описание на Delphi *****
function WSAEnumProtocols(lpiProtocols: PInteger; lpProtocolBuffer: PWSAProtocolInfo; var BufferLength: DWORD): Integer;
Примечание
В старых версиях MSDN в описании этой функции есть небольшая опечатка: тип параметра
lpdwBufferLength
назван
LLPDWORD
вместо
LPDWORD
.
Библиотека WS2_32.dll придерживается тех же правил насчет ANSI- и Unicode-вариантов функций, что и другие системные библиотеки (см. разд. 1.1.12), поэтому в ней нет функции с именем
WSAEnumProtocols
, а есть
WSAEnumProtocolsA
и
WSAEnumProtocolsW
. Эти функции работают с разными вариантами структуры
WSAPROTOCOL_INFO
, которые различаются типом элементов в последнем массиве —
CHAR
или
WCHAR
.
Параметр
lpiProtocols
указывает на первый элемент массива, содержащего список протоколов, информацию о которых нужно получить. Если этот указатель равен
nil
, то возвращается информация обо всех доступных протоколах. Параметр
lpProtocolBuffer
содержит указатель на начало массива структур типа
TWSAProtocolInfo
. Программа должна заранее выделить память под этот массив. Параметр
BufferLength
при вызове должен содержать размер буфера
lpProtocolBuffer
в байтах (именно размер в байтах, а не количество элементов). После завершения функции сюда помешается минимальный размер буфера, необходимый для размещения информации обо всех запрошенных протоколах. Если это значение больше переданного, функция завершается с ошибкой.
Если параметр
lpiProtocols
не равен нулю, он должен содержать указатель на массив, завершающийся нулем. Следовательно, если количество протоколов, запрашиваемых программой, равно N, этот массив должен состоять из N+1 элементов, и первые N элементов должны содержать номера протоколов, а последний элемент — ноль.
В системе может быть установлено несколько провайдеров для одного протокола. В этом случае информация о каждом провайдере будет помещена в отдельный элемент массива. Из-за этого число задействованных элементов в массиве
lpProtocolBuffer
может превышать количество протоколов, определяемых параметром
lpiProtocols
.
К сожалению, полную информацию о том, каким протоколам какие номера соответствуют, в документации найти не удалось. Можно только сказать, что для получения информации о протоколе TCP в массив
lpiProtocols
необходимо поместить константу
IPPROTO_TCP
, о протоколе UDP — константу
IPPROTO_UDP
.
Возвращаемое функцией значение равно числу протоколов, информация о которых помещена в массив, если функция выполнена успешно, и
SOCKET_ERROR
, если при ее выполнении возникла ошибка. Конкретная ошибка определяется стандартным методом, с помощью
WSAGetLastError
. Если массив
lpProtocolBuffer
слишком мал для хранения всей требуемой информации, функция завершается с ошибкой
WSAENOBUFS
.
WinSock 1 содержит аналогичную по возможности функцию
EnumProtocols
, возвращающую массив структур
PROTOCOL_INFO
. Эта структура содержит меньше информации о протоколе, чем
WSAPROTOCOL_INFO
и, в отличие от последней, не используется никакими другими функциями WinSock. Несмотря на то, что функция
EnumProtocols
и структура
PROTOCOL_INFO
описаны в первой версии WinSock, модуль WinSock их не импортирует, при необходимости их нужно импортировать самостоятельно. Но функция
EnumProtocols
считается устаревшей, использовать ее в новых приложениях не рекомендуется, поэтому практически всегда, за исключением редких случаев, требующих совместимости с WinSock 1, лучше выбрать более современную функцию