共用方式為


初始化和註冊提供者模組

提供者模組必須先初始化一些資料結構,才能向網路模組註冊器 (NMR) 。 這些結構包括 NPI_MODULEID 結構、 NPI_PROVIDER_CHARACTERISTICS 結構、 NPI_REGISTRATION_INSTANCE 結構 (包含在NPI_PROVIDER_CHARACTERISTICS結構) 內,以及提供者模組用於提供者模組註冊內容的結構。

如果提供者模組向 NMR 註冊為 網路程式設計介面提供者, (NPI) 定義 NPI 特定提供者特性,提供者模組也必須初始化 NPI 所定義的提供者特性結構的實例。

只要提供者模組向 NMR 註冊,所有這些資料結構都必須保持有效且駐留在記憶體中。

例如,假設 「EXNPI」 NPI 會在標頭檔 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;

下列示範如何將本身註冊為 EXNPI NPI 提供者的提供者模組,初始化所有這些資料結構:

// 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 函式 內自行初始化。 提供者模組的主要初始化工作如下:

  • 指定 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 的提供者,它必須初始化一組獨立的資料結構,並針對它支援的每個 NPI 呼叫 NmrRegisterProvider 。 如果網路模組同時是提供者模組和用戶端模組 (,它是一個 NPI 的提供者,另一個 NPI 的用戶端) ,則必須初始化兩組獨立的資料結構,一組用於提供者介面,另一個用於用戶端介面,然後同時呼叫 NmrRegisterProviderNmrRegisterClient

不需要提供者模組,才能從其 DriverEntry函式內呼叫NmrRegisterProvider。 例如,在提供者模組是複雜驅動程式的子元件的情況下,只有在啟用提供者模組子元件時,才會發生提供者模組的註冊。

如需實作提供者模組 的 Unload 函式的詳細資訊,請參閱 卸載提供者模組