Инициализация и регистрация модуля поставщика

Модуль поставщика должен инициализировать ряд структур данных, прежде чем он сможет зарегистрировать себя в регистраторе сетевых модулей (NMR). Эти структуры включают структуру NPI_MODULEID , структуру NPI_PROVIDER_CHARACTERISTICS , структуру NPI_REGISTRATION_INSTANCE (содержащуюся в структуре NPI_PROVIDER_CHARACTERISTICS) и структуру, определяемую модулем поставщика, которая используется для контекста регистрации модуля поставщика.

Если модуль поставщика регистрирует себя в NMR в качестве поставщика сетевого интерфейса программирования (NPI), который определяет характеристики поставщика NPI, модуль поставщика должен также инициализировать экземпляр структуры характеристик поставщика, определяемой NPI.

Все эти структуры данных должны оставаться действительными и находиться в памяти до тех пор, пока модуль поставщика зарегистрирован в NMR.

Например, предположим, что NPI "EXNPI" определяет следующее в файле заголовка Exnpi.h:

// EXNPI NPI identifier
const NPIID EXNPI_NPIID = { ... };

// EXNPI provider characteristics structure
typedef struct EXNPI_PROVIDER_CHARACTERISTICS_
{
  .
  . // NPI-specific members
  .
} EXNPI_PROVIDER_CHARACTERISTICS, *PEXNPI_PROVIDER_CHARACTERISTICS;

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

// Include the NPI specific header file
#include "exnpi.h"

// Structure for the provider module's NPI-specific characteristics
const EXNPI_PROVIDER_CHARACTERISTICS NpiSpecificCharacteristics =
{
  .
  . // The NPI-specific characteristics of the provider module
  .
};

// Structure for the provider module's identification
const NPI_MODULEID ProviderModuleId =
{
  sizeof(NPI_MODULEID),
  MIT_GUID,
  { ... }  // A GUID that uniquely identifies the provider module
};

// Prototypes for the provider module's callback functions
NTSTATUS
  ProviderAttachClient(
    IN HANDLE NmrBindingHandle,
    IN PVOID ProviderContext,
    IN PNPI_REGISTRATION_INSTANCE ClientRegistrationInstance,
    IN PVOID ClientBindingContext,
    IN CONST VOID *ClientDispatch,
    OUT PVOID *ProviderBindingContext,
    OUT PVOID *ProviderDispatch
    );

NTSTATUS
  ProviderDetachClient(
    IN PVOID ProviderBindingContext
    );

VOID
  ProviderCleanupBindingContext(
    IN PVOID ProviderBindingContext
    );

// Structure for the provider module's characteristics
const NPI_PROVIDER_CHARACTERISTICS ProviderCharacteristics =
{
  0,
  sizeof(NPI_PROVIDER_CHARACTERISTICS),
  ProviderAttachClient,
  ProviderDetachClient,
  ProviderCleanupBindingContext,
  {
    0,
    sizeof(NPI_REGISTRATION_INSTANCE),
    &EXNPI_NPIID,
    &ProviderModuleId,
    0,
    &NpiSpecificCharacteristics
  }
};

// Context structure for the provider module's registration
typedef struct PROVIDER_REGISTRATION_CONTEXT_ {
  .
  . // Provider-specific members
  .
} PROVIDER_REGISTRATION_CONTEXT, *PPROVIDER_REGISTRATION_CONTEXT;

// Structure for the provider's registration context
PROVIDER_REGISTRATION_CONTEXT ProviderRegistrationContext =
{
  .
  . // Initial values for the registration context
  .
};

Модуль поставщика обычно инициализирует себя в своей функции DriverEntry . Задачи main инициализации для модуля поставщика:

  • Укажите функцию Unload . Операционная система вызывает эту функцию, когда модуль поставщика выгружается из системы. Если модуль поставщика не предоставляет функцию выгрузки, модуль поставщика не может быть выгружен из системы.

  • Вызовите функцию NmrRegisterProvider , чтобы зарегистрировать модуль поставщика в NMR.

Пример:

// Prototype for the provider module's unload function
VOID
  Unload(
    PDRIVER_OBJECT DriverObject
   );

// Variable to contain the handle for the registration
HANDLE ProviderHandle;

// DriverEntry function
NTSTATUS
  DriverEntry(
    PDRIVER_OBJECT DriverObject,
    PUNICODE_STRING RegistryPath
    )
{
  NTSTATUS Status;

  // Specify the unload function
  DriverObject->DriverUnload = Unload;

  .
  . // Other initialization tasks
  .

  // Register the provider module with the NMR
  Status = NmrRegisterProvider(
    &ProviderCharacteristics,
    &ProviderRegistrationContext,
    &ProviderHandle
    );

  // Return the result of the registration
  return Status;
}

Если модуль поставщика является поставщиком более одного NPI, он должен инициализировать независимый набор структур данных и вызывать NmrRegisterProvider для каждого NPI, который он поддерживает. Если сетевой модуль является одновременно модулем поставщика и клиентским модулем (то есть поставщиком одного NPI и клиентом другого NPI), он должен инициализировать два независимых набора структур данных, один для интерфейса поставщика и один для клиентского интерфейса, и вызвать nmrRegisterProvider и NmrRegisterClient.

Модуль поставщика не требуется для вызова NmrRegisterProvider из функции DriverEntry . Например, в ситуации, когда модуль поставщика является подкомпонентом сложного драйвера, регистрация модуля поставщика может происходить только при активации подкомпонента модуля поставщика.

Дополнительные сведения о реализации функции Unload модуля поставщика см. в разделе Выгрузка модуля поставщика.