Partager via


Inscription d’une application de noyau Winsock

Inscription d’objet client WSK

Une application WSK (Winsock Kernel) doit s’inscrire en tant que client WSK en appelant la fonction WskRegister . WskRegister exige que l’application WSK initialise et passe un pointeur vers l’interface de programmation réseau (NPI) de son client WSK (structure WSK_CLIENT_NPI ) et un objet d’inscription WSK (structure WSK_REGISTRATION ) qui sera initialisé par WskRegister lors du retour réussi.

L’exemple de code suivant montre comment une application WSK peut s’inscrire en tant que client WSK.

// Include the WSK header file
#include "wsk.h"

// WSK Client Dispatch table that denotes the WSK version
// that the WSK application wants to use and optionally a pointer
// to the WskClientEvent callback function
const WSK_CLIENT_DISPATCH WskAppDispatch = {
  MAKE_WSK_VERSION(1,0), // Use WSK version 1.0
  0,    // Reserved
  NULL  // WskClientEvent callback not required for WSK version 1.0
};

// WSK Registration object
WSK_REGISTRATION WskRegistration;

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

  .
  . 
  .

  // Register the WSK application
  wskClientNpi.ClientContext = NULL;
  wskClientNpi.Dispatch = &WskAppDispatch;
  Status = WskRegister(&wskClientNpi, &WskRegistration);

  if(!NT_SUCCESS(Status)) {
      .
      .
      .
      return Status;
  }

  .
  . 
  .
}

Une application WSK n’est pas nécessaire pour appeler WskRegister à partir de sa fonction DriverEntry . Par exemple, si une application WSK est un sous-composant d’un pilote complexe, l’inscription de l’application peut se produire uniquement lorsque le sous-composant d’application WSK est activé.

Une application WSK doit conserver la structure WSK_CLIENT_DISPATCH passée à WskRegister valide et résidente en mémoire jusqu’à ce que WskDeregister soit appelé et que l’inscription ne soit plus valide. La structure WSK_REGISTRATION doit également être conservée valide et résider dans la mémoire jusqu’à ce que l’application WSK cesse d’appeler les autres fonctions d’inscription WSK. L’exemple de code précédent conserve ces deux structures dans la section de données globales du pilote, conservant ainsi les données de structure résidant en mémoire jusqu’à ce que le pilote soit déchargé.

Capture NPI du fournisseur WSK

Une fois qu’une application WSK s’est inscrite en tant que client WSK auprès de WskRegister, elle doit utiliser la fonction WskCaptureProviderNPI pour capturer le NPI du fournisseur WSK à partir du sous-système WSK afin de commencer à utiliser l’interface WSK.

Étant donné que le sous-système WSK n’est peut-être pas encore prêt lorsqu’une application WSK tente de capturer le NPI du fournisseur WSK, la fonction WskCaptureProviderNPI permet à l’application WSK d’interroger ou d’attendre que le sous-système WSK soit prêt comme suit :

  • Si le paramètre WaitTimeout est WSK_NO_WAIT, la fonction retourne toujours immédiatement sans attendre.

  • Si WaitTimeout est WSK_INFINITE_WAIT, la fonction attend que le sous-système WSK soit prêt.

  • Si WaitTimeout est une autre valeur, la fonction retourne soit lorsque le sous-système WSK est prêt, soit lorsque le temps d’attente, en millisecondes, atteint la valeur waitTimeout, selon la première éventualité.

Important Pour éviter d’affecter négativement le démarrage d’autres pilotes et services, une application WSK qui appelle WskCaptureProviderNPI à partir de sa fonction DriverEntry ne doit pas définir le paramètre WaitTimeout sur WSK_INFINITE_WAIT ou un temps d’attente excessif. En outre, si une application WSK démarre très tôt dans la phase de démarrage du système, elle doit attendre que le sous-système WSK soit prêt dans un thread de travail différent de celui dans lequel DriverEntry s’exécute .

Si l’appel à WskCaptureProviderNPI échoue avec STATUS_NOINTERFACE, l’application WSK peut utiliser la fonction WskQueryProviderCharacteristics pour découvrir la plage des versions NPI WSK prises en charge par le sous-système WSK. L’application WSK peut appeler WskDeregister pour annuler l’inscription de son instance d’inscription actuelle, puis s’inscrire à nouveau à l’aide d’un autre WSK_CLIENT_DISPATCH instance qui utilise une version WSK NPI prise en charge.

Lorsque WskCaptureProviderNPI retourne correctement, son paramètre WskProviderNpi pointe vers un NPI de fournisseur WSK ( WSK_PROVIDER_NPI) prêt à être utilisé par l’application WSK. La structure WSK_PROVIDER_NPI contient des pointeurs vers l’objet client WSK ( WSK_CLIENT) et la table de répartition WSK_PROVIDER_DISPATCH des fonctions WSK que l’application WSK peut utiliser pour créer des sockets WSK et effectuer d’autres opérations sur l’objet client WSK. Une fois que l’application WSK a terminé d’utiliser les fonctions WSK_PROVIDER_DISPATCH, elle doit libérer le NPI du fournisseur WSK en appelant WskReleaseProviderNPI.

L’exemple de code suivant montre comment une application WSK peut capturer le NPI du fournisseur WSK, l’utiliser pour créer un socket, puis le libérer.

// WSK application routine that waits for WSK subsystem
// to become ready and captures the WSK Provider NPI
NTSTATUS
  WskAppWorkerRoutine(
    )
{
  NTSTATUS Status;
  WSK_PROVIDER_NPI wskProviderNpi;
 
  // Capture the WSK Provider NPI. If WSK subsystem is not ready yet,
  // wait until it becomes ready.
  Status = WskCaptureProviderNPI(
    &WskRegistration, // must have been initialized with WskRegister
    WSK_INFINITE_WAIT,
    &wskProviderNpi
    );

  if(!NT_SUCCESS(Status))
  {
    // The WSK Provider NPI could not be captured.
    if( Status == STATUS_NOINTERFACE ) {
      // WSK application's requested version is not supported
    }
    else if( status == STATUS_DEVICE_NOT_READY ) {
      // WskDeregister was invoked in another thread thereby causing
      // WskCaptureProviderNPI to be canceled.
    } 
    else {
      // Some other unexpected failure has occurred
    }

    return Status;
  }

  // The WSK Provider NPI has been captured.
  // Create and set up a listening socket that accepts
   // incoming connections.
  Status = CreateListeningSocket(&wskProviderNpi, ...);

  // The WSK Provider NPI will not be used any more.
  // So, release it here immediately.
  WskReleaseProviderNPI(&WskRegistration);

  // Return result of socket creation routine
  return Status;

}

Une application WSK peut appeler WskCaptureProviderNPI plusieurs fois. Pour chaque appel à WskCaptureProviderNPI qui retourne correctement, il doit y avoir un appel correspondant à WskReleaseProviderNPI. Une application WSK ne doit pas effectuer d’autres appels aux fonctions dans WSK_PROVIDER_DISPATCH après l’appel de WskReleaseProviderNPI.