Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Программирование в сетях Windows

.pdf
Скачиваний:
538
Добавлен:
11.03.2015
Размер:
3.02 Mб
Скачать

448

ЧАСТЬ II Интерфейс прикладного программирования Winsock

/

ствующий сокетным входным параметрам вызовов socket и WSASocket (таким как семейство адреса, тип сокета и протокол) Как только подходящая запись найдена, Ws2_32 dll загружает соответствующую DLL-библиотеку поставщика службы, определенную в каталоге

По существу, для успешных установки и управления записью поставщика службы в БД поставщиков необходимы четыре функции конфигурации SPI Каждая функция начинается с префикса WSC WSCEnumProtocols, WSCInstallProvider, WSCWnteProviderOrder, WSCDelnstallProvider

Эти функции работают с базой данных, используя структуру WSAPROTOCOLJNFOW (см главу 5) При установке поставщика транспортной службы нас прежде всего интересуют поля Providerld, dwCatalogEntryld и ProtocolCham этой структуры Поле Providerld — GUID, позволяющий уникально определять и устанавливать поставщик в любой системе Поле dwCatalogEntryld просто определяет каждую структуру WSAPROTOCOLJNFOW записи каталога в БД по уникальному числовому значению Поле ProtocolChain определяет, является ли структура WSAPROTOCOLJNFOW записью каталога для базового, многоуровневого или цепочки протоколов поставщика Поле ProtocolChain — структура WSAPROTOCOLCHAIN

typedef struct { int ChainLen,

DWORDChainEntnes[MAX_PR0TOCOL_CHAIN], } WSAPROTOCOLCHAIN, FAR * LPWSAPROTOCOLCHAIN,

Поле ChainLen определяет, представляет ли запись каталога многоуровневый (ChamLen = 0), основной (ChainLen = 1) поставщик, или цепочку протоколов поставщика (ChamLen > 1) Цепочка протоколов (protocol chain) — специальная запись каталога, задающая, как поместить многоуровневый поставщик служб между Winsock и другими поставщиками службы (рис 14-2) Многоуровневые и основные поставщики имеют только по одной записи каталога в БД Последнее поле — ChamEntnes, представляет собой массив идентификаторов каталога, используемых для описания порядка загрузки поставщиков в цепочке протоколов Когда в ходе создания сокета Ws2_32 dll ищет в каталоге соответствующий поставщик, она просматривает только записи цепочек протоколов и базовых поставщиков Записи многоуровневых поставщиков (ChamLen - 0) игнорируются — они существуют только для сопоставления многоуровневого поставщика цепочке протоколов в записях этих цепочек.

Установка базового поставщика

Чтобы установить основной поставщик, создайте структуру WSAPROTOCOL_ INFOW записи каталога, которая представляет этот поставщик Заполните поля в этой структуре информацией об атрибутах протокола Не забудьте присвоить значение 1 полю ChainLen структуры ProtocolChain Когда структура определена, поместите ее в каталог, используя функцию WSClnstallProvider

int WSCInstallProvider(

const LPGUID lpProviderld,

const LPWSTR lpszProviderDllPath,

Г Л А В А 14 Интерфейс Winsock 2 SPI

449

const LPWSAPROTOCOL_INFOW lpProtocolInfoList, DWORDdwNumberOfEntries,

LPINT lpErrno

).

Параметр ipProviderld — GUID, позволяющий идентифицировать поставщик для каталога Winsock Параметр ipszProviderDllPath — строка, содержащая загрузочный путь к DLL поставщика Строка может включать переменные окружения, такие как %SystemRoot% Параметр lpProtocolInfoList представляет массив структур данных WSAPROTOCOLJNFOWдля помещения в каталог Устанавливая основного поставщика, вы можете просто назначить структуре WSAPROTOCOLJNFOWпервый элемент массива Параметр dwNumberOfEntnes содержит количество записей в массиве lpProtocolInfoList, параметр IpErmo — код ошибки, если выполнение этой функции не удалось Тогда возвращается SOCKETERROR

Установка многоуровневого поставщика

Чтобы установить многоуровневый поставщик службы, создайте две структуры WSAPROTOCOLJNFOW записей в каталоге Одна будет представлять ваш многоуровневый поставщик (например, длина цепочки протоколов, равная 0), а другая — цепочку протоколов (например, длина цепочки протоколов, большая 1), соединяющую многоуровневый поставщик с основным Эти две структуры следует инициировать со свойствами структуры WSAPROTOCOL_ INFOW записи каталога существующего поставщика службы Запись вы можете найти с помощью функции WSCEnumProtocols

int WSCEnumProtocols(

 

LPINT lpiProtocols,

 

LPWSAPROTOCOL.INFOW

lpProtocolBuffer,

LPDWORD lpdwBufferLength,

LPINT lpErrno

r(>v

),

Параметр lpiProtocols — необязательный массив значений Если lpiProtocols содержит NULL, возвращается информация по всем доступным протоколам, если нет — только по протоколам, перечисленным в массиве Параметр lpProtocolBuffer — предоставленный приложением буфер, заполненный структурами WSAPROTOCOLJNFOW из каталога Winsock 2 Входящий параметр lpdwBufferLength содержит количество байт в переданном функцией WSCEnumProtocols буфере lpProtocolBuffer При выходе в этот параметр заносится минимальный размер буфера, который можно передать WSCEnumProtocols для определения всей запрошенной информации Параметр lpErrno содержит информацию об ошибке, если выполнение функции неудачно и возвращено SOCKET_ERROR Располагая записью в каталоге для поставщика, который вы собираетесь поместить сверху, скопируйте свойства структуры

WSAPROTOCOLJNFOW поставщика, во вновь созданные структуры

После инициализации поместите в каталог запись многоуровневого поставщика, используя функцию WSCInstallProvider Затем найдите идентифи-

450

ЧАСТЬ II Интерфейс прикладного программирования Winsock

катор каталога, который присваивается этой структуре после установки, перебрав записи в каталоге с помощью WSCEnumProtocols. Эта запись может затем использоваться при помещении в каталог записи цепочки протоколов, связывающей ваш многоуровневый поставщик с другим поставщиком. Затем для установки включенного в цепочку поставщика вызывается функция WSCInstallProvider. Этот процесс иллюстрирует следующий псевдокод:

WSAPROTOCOL_NIFOW LayeredProtocolInfoBuff,

ProtocolChainProtoInfo,

BaseProtocolInfoBuff;

// Получение BaseProtooolInfoBuff с помощью WSCEnumProtocolsO

memcpy (&LayeredProtocolInfoBuff , &BaseProtocolInfoBuff, sizeof(WSAPROTOCOL_INFO));

LayeredProtocolInfoBuff.dwProviderFlags = PFL_HIDDEN; LayeredProtocolInfoBuff.Providerld = LayeredProviderGuid;

// Эта запись будет заполнена системой LayeredProtocolInfoBuff.dwCatalogEntryld = 0;

LayeredProtocolInfoBuff.ProtocolChain.ChainLen =

LAYERED_PROTOCOL;

WSCInstallProvider(&LayeredProviderGuid,

L"lsp.dll",

 

JLayeredProtocolInfoBuff, 1, & install error);

tot

 

 

 

// Определение

идентификатора каталога многоуровневого поставщика с

' '

// использованием функции WSCEnumProtocolsO

 

for ( 1 = 0 ; 1 < TotalProtocols; 1++)

 

 

if (memcmp

(&ProtocolInfo[l].Providerld, &ProviderGuid,

r-

sizeof

(GUID))==O)

 

 

{

 

 

 

LayeredCatalogld = Protocollnfo[i].dwCatalogEntryld; break;

Memcpy(&protocolChainProtoInfo, &BaseProtocolInfoBuff,

sizeof(WSAPR0T0C0L_INF0));

ProtocolChainProtoInfo.ProtocolChain.ChainLen = 2;

ProtocolChainProtoInfo.ProtocolChain.ChainEntries[0] =

LayeredProvideProtocolInfo.dwCatalogEntryld;

ProtocolChalnProtoInfo.ProtocolChain.ChainEntries[1] =

BaseProtooolInfoBuff.dwCatalogEntryld;

WSCInstallProvider(

iChainedProviderGuid,

L"lsp.dll", // lpszProviderDHPath &ProtooolChainProtoInfo, // lpProtocolInfoList

 

 

Г Л А В А 14 Интерфейс Winsock 2 SPI

451

1,

//

dwNumberOfEntries

 

&install error

//

lpErrno

 

Обратите внимание на флаг PFLHIDDENв структуре WSAPROTOCOLJNFOW. Благодаря ему функция WSAEnumProtocols (см. главу 5) не включает каталог для многоуровневого поставщика в возвращаемый ею буфер.

Другой важный флаг, которым должна управлять программа установки — XP1JFS_ HANDLES. Любой He-IFS-поставщик службы, использующий WPUCreateSocketHandle для создания своих описателей сокета, не должен задавать флаг XP1_IFS_HANDLES в структуре WSAPROTOCOLJNFOW. Для приложений Winsock отсутствие флага ХР1JFSJiANDLES — указание избегать использования функций ReadFile и WriteFile из-за потенциального снижения производительности.

Упорядочение поставщиков

Теперь вы должны решить, как Winsock 2 будет искать поставщиков служб в БД. Большинство приложений Winsock определяют нужный протокол с помощью параметров вызова функций socket и WSASocket. Например, если приложение создает сокет, используя семейство адресов AFJNET и тип SOCK_STREAM, Winsock 2 ищет заданный по умолчанию протокол TCP/IP, запись включенного в цепочку или базового поставщика в БД. Когда вы устанавливаете поставщик службы, используя WSCInstallProvider, запись в каталоге автоматически становится последней в БД. Чтобы сделать поставщик службы стандартным поставщиком TCP/IP, упорядочите записи о поставщиках в базе данных и поместите запись цепочки протоколов перед другими поставщиками TCP/ IP. Для этого вызовите функцию WSCWriteProviderOrder.

int WSCWriteProviderOrder( LPDWORD lpwdCatalogEntryld, DWORD dwNumberOfEntries

Параметр lpwdCatalogEntryld принимает массив идентификаторов каталога, определяющих порядок его сортировки. Вы можете задать идентификаторы каталога, вызвав WSCEnumProtocols, как описано ранее. Параметр dwNumberOfEntries — счетчик записей каталога в массиве. Эта функция возвращает ERROR_SUCCESS (0), если выполнена успешно, и код ошибки Winsock — если нет.

Функция WSCWriteProviderOrder не входит в библиотеку Ws2_32.dll. Чтобы использовать ее, приложение должно быть скомпоновано с библиотекой Sporder.lib. Модуль Sporder.dll не является частью ОС Windows, ищите DLL поддержки в библиотеке Microsoft Developer Network (MSDN). Если вы используете этот модуль, распространяйте его вместе с приложением.

Библиотека MSDN также предлагает удобную программную утилиту Sporder.exe, которая позволяет просматривать и переупорядочивать записи каталога в БД Winsock 2 (рис. 14-3)-

452

ЧАСТЬ II Интерфейс прикладного программирования Wmsock

 

Senfleeptovtdws|tameResatutronj

LayeredTCP/IPovei|MSAFDТсрир[TCP/IP])

MSAFDTcpp[TCP/IP]

MSAFDTcpip[UDP/IP]

MSAFDTcpip[RAW/IP]

RSVPUDPServiceProvider

RSVPTCPServiceProvider

MSAFD NetBIOS [\Device\NetBT TcpipJ28O1SCC0DOAA11D28A538EE7542C0OOE}

MSAFDNetBIOS[\DevKe\NetBTlTcpipJ28D19Ci:0DOAA11D28A538EE7542C000E}

MSAFDNetBIOS[SDeviceSNetBT_Tcp«>J28O13CC2-D(»A11D2-8A53«E7542COOOE)

MSAFDNetBIOS[\DevrceSNetBT_TcppJ28O19CC2D0AA11D28AS38EE7542C000E)

MSAFDNetBIOS[\Device\NetBT_TcppJ49213832DOAB11D2I3A53-00105424E14A)]

MSAFONetBIOS|\Devce\NetBT TcpipJ49213832DOAB11D28А53-О01ОЕА24Е14АЦ

MSAFDNetBIOS[\Device\NefflTlTcr4> {49213831DOAB11D28A53OO1O5A24E14A(]

MSAFONetBIOS|\Device\NetBT_Tcpip~<49213831DOAB11D28A5300105A24E14A!]

MSAFDNetBIOS(\DevrceWetBTTcpipI(49213830DQAB11D28A530010SA24E14A)]

MSAFDNetBIOS[\Devce\NelBT~TcpipJ49213830DQAB11D2-8A5300105A24E14AI]

Рис. 14-3. Конфигурация Winsock2 послеустановки многоуровневого поставщика на компьютерсWindows2000

Удаление поставщика службы

Удалить поставщик службы из каталога Wmsock 2 не сложно Вызовите функцию WSCDeinstallProvider

int WSCDeinstallProvider( LPGUID lpProviderld, LPINT lpErrno

Параметр lpProviderld представляет GUID удаляемого поставщика службы Параметр lpErrno получает код ошибки Wmsock, если функция возвращаетSOCKET_ERROR

При удалении поставщика службы вы должны учитывать один важный момент Всегда есть возможность, что многоуровневый поставщик службы включил идентификатор каталога вашего поставщика службы в свою цепочку протокола Если это так, вы должны удалить идентификатор каталога из любых цепочек протоколов, которые ссылаются на ваш поставщик

Проблемы при установке многоуровневых поставщиков

Многоуровневые поставщики службы имеют огромный потенциал Однако нынешняя спецификация Winsock 2 не отвечает на важный вопрос как многоуровневый поставщик службы может узнать, в каком месте вставить себя в цепочку протоколов, если находит другой многоуровневый поставщик

Например, если вы хотите установить поставщик шифрования данных в системе, которая уже содержит поставщик фильтрации URL, оче-

Г Л А ВА 14 Интерфейс Winsock 2 SPI

453

видно, что первый должен быть вставлен ниже второго в сущест вующей цепочке протоколов Но проблема в том, что программа установки поставщика не может выяснить, какую службу обеспечивает существующий поставщик, и поэтому не знает, куда вставить новый Это не приносит больших осложнений для управляемой сетевой среды, в которой администраторы решают, какие поставщики и в каком порядке устанавливать Но широкому распространению многоуровневых поставщиков службы препятствует то, что безопасной может быть только установка многоуровневого поставщика службы непосредственно поверх основного и задание новой цепочки поставщиком протокола по умолчанию Такой подход гарантирует службу нового поставщика, но удаляет существующий многоуровневый поставщик как заданную по умолчанию цепочку поставщиков

Есть еще одна проблема, которую не разрешает спецификация Winsock 2 Она связана с первой, хотя и не столь серьезна Как существующие многоуровневые поставщики могут защитить себя от изменений в цепочке или узнать, что такие изменения происходят' Если цепочка протоколов многоуровневого поставщика не должна меняться, его разработчик может жестко запрограммировать порядок цепочки в рамках функции WSPStartup и определить поставщик как базовый, указав значение 1 для параметра ProtocolChmn ChamLen структуры WSAP-

ROTOCOLJNFOWдля LSP

Поставщики службы пространства имен

В главе 10 мы рассмотрели, как приложение регистрирует и разрешает службы в пространстве имен, что особенно важно для служб, которые можно динамически создавать в сети К сожалению, полезность существующих доступных пространств имен ограничена Спецификация Winsock 2, однако, предлагает вам метод создания собственных пространств имени, где вы сможете регистрировать и разрешать имена любым удобным для себя способом

Это можно сделать с помощью DLL, реализующей девять функций пространства имен Все функции начинаются с префикса NSP и соответствуют функциям RNR (см главу 10) Например, эквивалент функции пространства имени WSASetSeruice — функцияNSPSetService После создания DLL она устанавливается в системный каталог с GUID, идентифицирующим пространство имен Затем приложения могут регистрировать и запрашивать службы в вашем пространстве имен

Сначала мы расскажем, как установить поставщик пространства имен, а затем опишем функции, которые он должен реализовать Наконец, рассмотрим типовой поставщик пространства имен, а также типовое приложение, регистрирующее и разрешающее службы

Установка поставщика пространства имен

Поставщик пространства имен — это просто DLL, осуществляющая функции поставщика пространства имен Чтобы приложения могли использовать

4 54

ЧАСТЬ II Интерфейс прикладного программирования Winsock

пространство имен, уведомите о нем систему с помощью функции WSCInstallNameSpace. Установленный поставщик вы можете отключить или удалить из системного каталога с помощью функций WSAEnableNSProvider и WSAUnlnstallNameSpace.

ФункцияWSCInstallNameSpace

j

Эта функция используется для установки поставщика в системный катался]

Она определена так: > t

int WSCInstallNameSpace ( LPWSTRlpszldentifier, LPWSTRlpszPathName, DWORDdwNameSpace, DWORDdwVersion, LPGUID lpProviderld

);

Сразу бросается в глаза, что все строковые параметры представлены широкими символами. На самом деле, с использованием строк широких символов реализованы все поставщики пространства имен.

Параметр lpszldentifier — имя поставщика пространства имен, возвращаемое функцией WSAEnumNameSpaceProviders (см. главу 10). Параметр lpszPathName — расположение DLL Строка может включать системные переменные, такие как %SystemRoot%. Параметр dwNameSpace — числовой идентификатор пространства имен. Например, в заголовочном файле Nspapi.h определены константы других известных пространств имен, типа NS_SAP, для IPX SAP. Параметр dwVersion задает номер версии пространства имен. Наконец, параметр lpProviderld — GUID, идентифицирующий поставщик пространства имен.

В случае удачного выполнения WSCInstallNameSpace возвращает 0, иначе — SOCKET_ERROR. Чаще всего это WSAEINVAL (пространство имен с данным GUID уже существует) или WSAEACCESS (процесс вызова не имеет достаточных полномочий). Задавать пространство имен могут только члены группы Administrators.

ФункцияWSCEnableNSProvider

Эта функция используется для изменения состояния (включения или выключения) поставщика пространства имен:

int WSCEnableNSProvider ( LPGUID lpProviderld, BOOL fEnable

);

Параметр lpProviderld — идентификатор GUID пространства имен, которое вы хотите изменить. Параметр fEnable содержит булево значение, указывающее, следует ли включить или выключить поставщик. Выключенный поставщик не может обрабатывать запросы или регистрацию.

Г Л А ВА 14 Интерфейс Winsock 2 SPI

455

При удачном выполнении WSCEnableNSProvider возвращает 0, иначе — SOCKET_ERROR. Если GUID поставщика не действителен, возвращается ошибкаWSAEINVAL.

ФункцияWSCUnlnstallNameSpace

г

Эта функция удаляет поставщик пространства имен из каталога: int WSCUnlnstallNameSpace ( LPGUID lpProviderld );

Параметр lpProviderld — GUID удаляемого пространства имен. Если GUID не действителен, выполнение возвращается ошибка WSAEINVAL.

Реализация пространства имен

Пространство имен должно реализовать все девять функций, соответствующих функциям RNR. Кроме того, следует разработать метод для постоянного сохранения данных, то есть поддерживать данные вне экземпляра DLL Каждый загружающий DLL процесс получает свой собственный сегмент данных — это означает, что сохраненные в рамках DLL данные не могут быть разделены между экземплярами (на самом деле, совместное использование информации загрузившими DLL приложениями возможно, но не одобряется).

Дополнительную информацию по библиотекам DLL можно найти в книге «Windows для профессионалов» Джеффри Рихтера (М.: «Русская Редакция». 2001). Как упоминалось в главе 10, существуют три типа пространства имен: динамическое, постоянное и статическое. Очевидно, реализовать статическое пространство не стоит, так как оно не допускает программную регистрацию служб. Далее мы рассмотрим некоторые аспекты поддержки данных, которые пространство имен должно сохранить.

Очень важно использовать строки широких символов во всех функциях поставщика пространства имен: не только строковых параметров функций, нотакжеистроквRNR-структурах,типаWSAQUERYSETиWSASERVICECLASS- INFO. Вы можете спросить, возможно ли это — ведь когда приложение регистрирует или разрешает имя, оно вправе использовать и обычную версию (ASCII), и версию с широкими символами (UNICODE) функций и RNR-струк- тур. На самом деле, работает любая версия, так как все запросы ASCII проходят промежуточный уровень, преобразующий все строки в строки широких символов.

Это верно и для вызова функции, и для ее возвращения. То есть если вызывающемуприложениювозвращаетсяWSAQUERYSET(спомощьюфункции WSALookupServiceNexf), то любые данные, возвращенные поставщиком пространства имен, изначально находятся в виде UNICODE и преобразуются в ASCII перед возвратом из функции. Так что если ваши приложения используют RNR-функции, вызов версий с широкими символами будет быстрее, так как не требует никаких преобразований.

Из девяти функций, которые должен реализовать поставщик пространства имен, только семь соответствуют RNR-функциям Winsock 2 (табл. 14-2).

456

ЧАСТЬ II Интерфейс прикладного программирования Winsock

 

Табл. 14-2. Соответствие функций регистрации и разрешения имен

 

в Winsock 2 функциям поставщика пространства имен

 

функция Winsock

Эквивалентная функция поставщика пространства имен

WSAInstallServiceClass

NSPInstallServtceClass

 

WSARemoveServiceClass

NSPRemoveServiceClass

 

WSAGetServiceClassInfo

NSPGetServiceClassInfo

! T*"

WSASetService

NSPSetService

}$1

WSALookupServiceBegm

NSPLookupServiceBegm

 

WSALookupServiceNext

NSPLookupServiceNext

э г

WSALookupServiceEnd

NSPLookupServiceEnd

 

Оставшиеся две функции применяются для инициализации и очистки. Когда пространство имен указано в системе, приложения могут использовать его, определяя соответствующий GUID или идентификатор пространства имен. Тогда приложение вызывает стандартную RNR-функцию Winsock 2, как описано в главе 10. При этом вызывается эквивалентная функция поставщика пространства имен Например, при вызове из приложения функции WSAInstallServiceClass, которая ссылается на GUID пользовательского пространства имен, вызывается функция NSPInstallServiceClass для этого поставщика

Далее мы рассмотрим все функции пространства имен.

ФункцияNSPStartup

NSPStartup вызывается каждый раз, когда загружается DLL поставщика пространства имен. Ваша реализация пространства имен должна включать эту функцию, экспортируемую из DLL. При этом можно выделить для каждой DLL все структуры данных, которые требуются для работы поставщика. Прототип NSPStartup выглядит так:

int NSPStartup (

LPGUID lpProviderld, LPNSP_ROUTINE lpnspRoutines

);

Первый параметр — lpProviderld, является GUID для этого поставщика пространства имен. Параметр lpnspRoutines — структура NSP_ROUTINE, которую должна заполнить ваша реализация этой функции. Эта структура обеспечивает указатели функции для восьми других функций пространства имен поставщика. Объект NSP_ROUTINE определен так:

typedef struct _NSP_ROUTINE

 

{

 

DWORD

cbSize;

DWORD

dwMajorVersion;

DWORD

dwMinorVersion;

LPNSPCLEANUP

NSPCleanup;

LPNSPLOOKUPSERVICEBEGIN

NSPLookupServiceBegin;

LPNSPLOOKUPSERVICENEXT

NSPLookupServiceNext;

LPNSPLOOKUPSERVICEEND

NSPLookupServiceEnd;

Г Л А ВА 14 Интерфейс Winsock 2 SPI

457

LPNSPSETSERVICE NSPSetService; LPNSPINSTALLSERVICECLASS NSPInstallServiceClass; LPNSPREMOVESERVICECLASS NSPRemoveServiceClass; LPNSPGETSERVICECLASSINFO NSPGetServiceClassInfo;

} NSP_ROUTINE, FAR * LPNSP_ROUTINE;

Первое поле структуры — cbSize, указывает размер структуры NSP_ROUTINE Следующие два поля — dwMajorVersion и dwMinorVersion, включены для управления версиями поставщика. Управление версиями произвольно и не служит никакой другой цели Поставщик присваивает остальным записям соответствующие указатели на функции Например, свой адрес функции NSPSetService (независимо от того, что скрывается под этим именем) — NSPSetService. Имена функций поставщика могут быть произвольными, но их параметры и возвращаемые типы должны соответствовать определению поставщика

Единственное действие, требуемое NSPStartup^ — заполнить структуру NSP_ROUTINE. Когда поставщик успешно завершает эту и любые другие процедуры инициализации, он возвращает NO_ERROR Если произошла ошибка, NSPStartup возвращает SOCKETJERROR и выясняет код ошибки Winsock Например, если ошибка связана с распределением памяти, поставщик вызывает WSASetLastError с параметром WSA_NOT_ENOUGH_MEMORYu затем возвращает SOCKET_ERROR

Сейчас, наверное, самое время обсудить обработку ошибок в DLL поставщика. Все функции, которые вы должны реализовать для поставщика, возвращают NOERROR в случае успеха и SOCKETERROR — при неудаче. Если вы видите, что вызов возвращает ошибку, назначьте соответствующий код ошибки Winsock Иначе любое приложение, пытающееся регистрировать или вызывать службы, используя ваш поставщик пространства имен, сообщит о неудаче функции RNR, но WSAGetLastError вернет 0 Это вызовет проблемы у приложений, которые пытаются корректно обрабатывать ошибки, 0 — безусловно не то значение, которое ожидается при ошибке

ФункцияNSPCIeanup

Эта процедура вызывается при выгрузке DLL поставщика. С ее помощью вы можете освобождать любую память, выделенную процедурой NSPStartup Функция NSPCIeanup определена так-

int NSPCIeanup ( LPGUID lpProviderld );

Единственный параметр — GUID вашего поставщика пространства имен От вас требуется лишь очистка всей динамически выделенной памяти

ФункцияNSPInstallServiceClass

Функция NSPInstallServiceClass соответствует WSAInstallServiceClass и отвечает за регистрацию класса служб

int NSPInstallServiceClass ( LPGUID lpProviderld,