Initialisieren und Registrieren eines Clientmoduls
Ein Clientmodul muss eine Reihe von Datenstrukturen initialisieren, bevor es sich bei der Network Module Registrar (NMR) registrieren kann. Zu diesen Strukturen gehören eine NPI_MODULEID-Struktur , eine NPI_CLIENT_CHARACTERISTICS-Struktur , eine NPI_REGISTRATION_INSTANCE-Struktur (die in der NPI_CLIENT_CHARACTERISTICS-Struktur enthalten ist) und eine Struktur, die vom Clientmodul definiert wird, das für den Registrierungskontext des Clientmoduls verwendet wird.
Wenn sich ein Clientmodul beim NMR als Client einer Netzwerkprogrammierschnittstelle (Network Programming Interface, NPI) registriert, die NPI-spezifische Clientmerkmale definiert, muss das Clientmodul auch eine instance der vom NPI definierten Clienteigenschaftenstruktur initialisieren.
Alle diese Datenstrukturen müssen gültig bleiben und sich im Arbeitsspeicher befinden, solange das Clientmodul beim NMR registriert ist.
Angenommen, die NPI "EXNPI" definiert Folgendes in der Headerdatei Exnpi.h:
// EXNPI NPI identifier
const NPIID EXNPI_NPIID = { ... };
// EXNPI client characteristics structure
typedef struct EXNPI_CLIENT_CHARACTERISTICS_
{
.
. // NPI-specific members
.
} EXNPI_CLIENT_CHARACTERISTICS, *PEXNPI_CLIENT_CHARACTERISTICS;
Im Folgenden wird gezeigt, wie ein Clientmodul, das sich selbst als Client der EXNPI-NPI registriert, alle diese Datenstrukturen initialisieren kann:
// Include the NPI specific header file
#include "exnpi.h"
// Structure for the client module's NPI-specific characteristics
const EXNPI_CLIENT_CHARACTERISTICS NpiSpecificCharacteristics =
{
.
. // The NPI-specific characteristics of the client module
.
};
// Structure for the client module's identification
const NPI_MODULEID ClientModuleId =
{
sizeof(NPI_MODULEID),
MIT_GUID,
{ ... } // A GUID that uniquely identifies the client module
};
// Prototypes for the client module's callback functions
NTSTATUS
ClientAttachProvider(
IN HANDLE NmrBindingHandle,
IN PVOID ClientContext,
IN PNPI_REGISTRATION_INSTANCE ProviderRegistrationInstance
);
NTSTATUS
ClientDetachProvider(
IN PVOID ClientBindingContext
);
VOID
ClientCleanupBindingContext(
IN PVOID ClientBindingContext
);
// Structure for the client module's characteristics
const NPI_CLIENT_CHARACTERISTICS ClientCharacteristics =
{
0,
sizeof(NPI_CLIENT_CHARACTERISTICS),
ClientAttachProvider,
ClientDetachProvider,
ClientCleanupBindingContext,
{
0,
sizeof(NPI_REGISTRATION_INSTANCE),
&EXNPI_NPIID,
&ClientModuleId,
0,
&NpiSpecificCharacteristics
}
};
// Context structure for the client module's registration
typedef struct CLIENT_REGISTRATION_CONTEXT_ {
.
. // Client-specific members
.
} CLIENT_REGISTRATION_CONTEXT, *PCLIENT_REGISTRATION_CONTEXT;
// Structure for the client's registration context
CLIENT_REGISTRATION_CONTEXT ClientRegistrationContext =
{
.
. // Initial values for the registration context
.
};
Ein Clientmodul initialisiert sich in der Regel innerhalb seiner DriverEntry-Funktion . Die Standard Initialisierungsaufgaben für ein Clientmodul sind:
Geben Sie eine Unload-Funktion an . Das Betriebssystem ruft diese Funktion auf, wenn das Clientmodul aus dem System entladen wird. Wenn ein Clientmodul keine Entladefunktion bereitstellt, kann das Clientmodul nicht aus dem System entladen werden.
Rufen Sie die NmrRegisterClient-Funktion auf, um das Clientmodul beim NMR zu registrieren.
Beispiel:
// Prototype for the client module's unload function
VOID
Unload(
PDRIVER_OBJECT DriverObject
);
// Variable to contain the handle for the registration
HANDLE ClientHandle;
// DriverEntry function
NTSTATUS
DriverEntry(
PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath
)
{
NTSTATUS Status;
// Specify the unload function
DriverObject->DriverUnload = Unload;
.
. // Other initialization tasks
.
// Register the client module with the NMR
Status = NmrRegisterClient(
&ClientCharacteristics,
&ClientRegistrationContext,
&ClientHandle
);
// Return the result of the registration
return Status;
}
Wenn ein Clientmodul ein Client mit mehr als einem NPI ist, muss es einen unabhängigen Satz von Datenstrukturen initialisieren und NmrRegisterClient für jeden unterstützten NPI aufrufen. Wenn ein Netzwerkmodul sowohl ein Clientmodul als auch ein Anbietermodul ist (d. h., es ist ein Client eines NPI und ein Anbieter eines anderen NPI), muss es zwei unabhängige Sätze von Datenstrukturen initialisieren, einen für die Clientschnittstelle und einen für die Anbieterschnittstelle, und sowohl NmrRegisterClient als auch NmrRegisterProvider aufrufen.
Ein Clientmodul ist nicht erforderlich, um NmrRegisterClient aus seiner DriverEntry-Funktion aufzurufen. In der Situation, in der ein Clientmodul ein Unterkomponenten eines komplexen Treibers ist, kann die Registrierung des Clientmoduls nur erfolgen, wenn die Clientmodulunterkomponente aktiviert wird.
Weitere Informationen zum Implementieren der Unload-Funktion eines Clientmoduls finden Sie unter Entladen eines Clientmoduls.