Registrera ett Winsock Kernel-program

Registrering av WSK-klientobjekt

Ett Winsock Kernel-program (WSK) måste registreras som en WSK-klient genom att anropa funktionen WskRegister. WskRegister kräver att WSK-programmet initierar och skickar en pekare till WSK-klientens NPI (Network Programming Interface)(en WSK_CLIENT_NPI-struktur) och ett WSK-registreringsobjekt (en WSK_REGISTRATION struktur) som initieras av WskRegister vid lyckad retur.

Följande kodexempel visar hur ett WSK-program kan registreras som en WSK-klient.

// 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;
  }

  .
  . 
  .
}

Ett WSK-program krävs inte för att anropa WskRegister inifrån dess DriverEntry- funktion. Om ett WSK-program till exempel är en underkomponent för en komplex drivrutin kan registreringen av programmet endast ske när WSK-programmets underkomponent aktiveras.

Ett WSK-program måste behålla strukturen WSK_CLIENT_DISPATCH, som skickas till WskRegister, giltig och lagrad i minnet tills WskDeregister anropas och registreringen inte längre är giltig. Den WSK_REGISTRATION-strukturen måste också hållas giltig och laddad i minnet tills WSK-applikationen upphör att anropa de andra WSK-registreringsfunktionerna. I det föregående kodexemplet behålls dessa två strukturer i det globala dataavsnittet i drivrutinen, vilket behåller strukturdata resident i minnet tills drivrutinen avladdas.

Insamling av NPI för WSK-leverantör

När ett WSK-program har registrerats som en WSK-klient med WskRegistermåste den använda funktionen WskCaptureProviderNPI för att kunna avbilda WSK-providerns NPI från WSK-undersystemet för att börja använda WSK-gränssnittet.

Eftersom WSK-undersystemet kanske ännu inte är klart när ett WSK-program försöker avbilda WSK-providerns NPI kan WskCaptureProviderNPI--funktionen göra det möjligt för WSK-programmet att avsöka eller vänta på att WSK-undersystemet blir klart på följande sätt:

  • Om parametern WaitTimeout är WSK_NO_WAIT returnerar funktionen alltid omedelbart utan att vänta.

  • Om WaitTimeout är WSK_INFINITE_WAIT väntar funktionen tills WSK-undersystemet blir klart.

  • Om WaitTimeout är något annat värde returnerar funktionen antingen när WSK-undersystemet blir klart eller när väntetiden i millisekunder når värdet för WaitTimeout, beroende på vilket som inträffar först.

Viktigt För att undvika att andra drivrutiner och tjänster påverkas negativt bör ett WSK-program som använder WskCaptureProviderNPI från funktionen DriverEntry inte ställa in parametern WaitTimeout till WSK_INFINITE_WAIT eller en för lång väntetid. Om ett WSK-program startar mycket tidigt i systemstartfasen bör det också vänta tills WSK-undersystemet blir klart i en annan arbetstråd än den där DriverEntry körs.

Om anropet till WskCaptureProviderNPI- misslyckas med STATUS_NOINTERFACE kan WSK-programmet använda funktionen WskQueryProviderCharacteristics för att identifiera intervallet för WSK NPI-versioner som stöds av WSK-undersystemet. WSK-programmet kan anropa WskDeregister för att avregistrera sin aktuella registreringsinstans och sedan registrera igen med hjälp av en annan WSK_CLIENT_DISPATCH instans som använder en WSK NPI-version som stöds.

När WskCaptureProviderNPI- returneras korrekt pekar dess WskProviderNpi-parametern på en NPI för WSK-providern ( WSK_PROVIDER_NPI) som är redo att användas av WSK-programmet. Den WSK_PROVIDER_NPI strukturen innehåller pekare till WSK-klientobjektet ( WSK_CLIENT) och den WSK_PROVIDER_DISPATCH dispatch-tabellen med WSK-funktioner som WSK-programmet kan använda för att skapa WSK-socketar och utföra andra åtgärder på WSK-klientobjektet. När WSK-programmet har slutförts med WSK_PROVIDER_DISPATCH-funktionerna måste det frigöra WSK-providerns NPI genom att anropa WskReleaseProviderNPI.

Följande kodexempel visar hur ett WSK-program kan avbilda WSK-providerns NPI, använda den för att skapa en socket och sedan släppa den.

// 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;

}

Ett WSK-program kan anropa WskCaptureProviderNPI mer än en gång. För varje anrop till WskCaptureProviderNPI som återkommer framgångsrikt, måste det finnas ett motsvarande anrop till WskReleaseProviderNPI. Ett WSK-program får inte göra ytterligare anrop till funktionerna i WSK_PROVIDER_DISPATCH efter att ha anropat WskReleaseProviderNPI.