Condividi tramite


Abilitazione e disabilitazione delle funzioni di callback degli eventi

Un'applicazione Winsock Kernel (WSK) può implementare funzioni di callback degli eventi che il sottosistema WSK chiama in modo asincrono per notificare all'applicazione quando si verificano determinati eventi in un socket. Un'applicazione WSK può fornire una struttura di tabella di invio client al sottosistema WSK ogni volta che crea un socket o accetta un socket in un socket in ascolto. Questa tabella di invio contiene puntatori alle funzioni di callback dell'applicazione WSK per il nuovo socket. Se un'applicazione WSK non implementa funzioni di callback di eventi per un socket specifico, non è necessario fornire una struttura di tabella di invio client al sottosistema WSK per tale socket.

Tutte le funzioni di callback degli eventi di un socket, ad eccezione delle funzioni WskInspectEvent e WskAbortEvent di un socket in ascolto, possono essere abilitate o disabilitate usando l'opzione socket SO_WSK_EVENT_CALLBACK. Un'applicazione WSK può abilitare più funzioni di callback eventi in un socket contemporaneamente. Tuttavia, un'applicazione WSK deve disabilitare singolarmente ogni funzione di callback degli eventi.

Nell'esempio di codice seguente viene illustrato come un'applicazione WSK può usare l'opzione socket SO_WSK_EVENT_CALLBACK per abilitare le funzioni di callback degli eventi WskDisconnectEvent e WskReceiveEvent in un socket orientato alla connessione.

// Function to enable the WskDisconnectEvent and WskReceiveEvent
// event callback functions on a connection-oriented socket
NTSTATUS
  EnableDisconnectAndRecieveCallbacks(
    PWSK_SOCKET Socket
    )
{
  PWSK_PROVIDER_CONNECTION_DISPATCH Dispatch;
  WSK_EVENT_CALLBACK_CONTROL EventCallbackControl;
  NTSTATUS Status;

  // Get pointer to the socket's provider dispatch structure
  Dispatch =
    (PWSK_PROVIDER_CONNECTION_DISPATCH)(Socket->Dispatch);

  // Specify the WSK NPI identifier
  EventCallbackControl.NpiId = &NPI_WSK_INTERFACE_ID;

  // Set the event flags for the event callback functions that
  // are to be enabled on the socket
  EventCallbackControl.EventMask =
    WSK_EVENT_DISCONNECT | WSK_EVENT_RECEIVE;

  // Initiate the control operation on the socket
  Status =
    Dispatch->WskControlSocket(
      Socket,
      WskSetOption,
      SO_WSK_EVENT_CALLBACK,
      SOL_SOCKET,
      sizeof(WSK_EVENT_CALLBACK_CONTROL),
      &EventCallbackControl,
      0,
      NULL,
      NULL,
      NULL  // No IRP for this control operation
      );

  // Return the status of the call to WskControlSocket()
  return Status;
}

Nell'esempio di codice seguente viene illustrato come un'applicazione WSK può usare l'opzione socket SO_WSK_EVENT_CALLBACK per disabilitare le funzioni di callback degli eventi WskReceiveEvent in un socket orientato alla connessione.

// Prototype for the disable disconnect IoCompletion routine
NTSTATUS
  DisableDisconnectComplete(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp,
    PVOID Context
    );

// Function to disable the WskDisconnectEvent event
// callback functions on a connection-oriented socket
NTSTATUS
  DisableDisconnectCallback(
    PWSK_SOCKET Socket
    )
{
  PWSK_PROVIDER_CONNECTION_DISPATCH Dispatch;
  PIRP Irp;
  WSK_EVENT_CALLBACK_CONTROL EventCallbackControl;
  NTSTATUS Status;

  // Get pointer to the socket's provider dispatch structure
  Dispatch =
    (PWSK_PROVIDER_CONNECTION_DISPATCH)(Socket->Dispatch);

  // Allocate an IRP
  Irp =
    IoAllocateIrp(
      1,
      FALSE
      );

  // Check result
  if (!Irp)
  {
    // Return error
    return STATUS_INSUFFICIENT_RESOURCES;
  }

  // Set the completion routine for the IRP
  IoSetCompletionRoutine(
    Irp,
 DisableDisconnectComplete,
    Socket,  // Use the socket object for the context
    TRUE,
    TRUE,
    TRUE
    );

  // Specify the WSK NPI identifier
  EventCallbackControl.NpiId = &NPI_WSK_INTERFACE_ID;

  // Set the event flag for the event callback function that
  // is to be disabled on the socket along with the disable flag
  EventCallbackControl.EventMask =
    WSK_EVENT_DISCONNECT | WSK_EVENT_DISABLE;

  // Initiate the control operation on the socket
  Status =
    Dispatch->WskControlSocket(
      Socket,
      WskSetOption,
      SO_WSK_EVENT_CALLBACK,
      SOL_SOCKET,
      sizeof(WSK_EVENT_CALLBACK_CONTROL),
      &EventCallbackControl,
      0,
      NULL,
      NULL,
      Irp
      );

  // Return the status of the call to WskControlSocket()
  return Status;
}

// Disable disconnect IoCompletion routine
NTSTATUS
  DisableDisconnectComplete(
    PDEVICE_OBJECT DeviceObject,
    PIRP Irp,
    PVOID Context
    )
{
  UNREFERENCED_PARAMETER(DeviceObject);

  PWSK_SOCKET Socket;

  // Check the result of the control operation
  if (Irp->IoStatus.Status == STATUS_SUCCESS)
  {
    // The WskDisconnectEvent event callback
    // function is now disabled

    // Get the socket object from the context
    Socket = (PWSK_SOCKET)Context;

    // Perform the next operation on the socket
    ...
  }

  // Error status
  else
  {
    // Handle error
    ...
  }

  // Free the IRP
  IoFreeIrp(Irp);

  // Always return STATUS_MORE_PROCESSING_REQUIRED to
  // terminate the completion processing of the IRP.
  return STATUS_MORE_PROCESSING_REQUIRED;
}

Per i socket di ascolto, le funzioni di callback degli eventi WskInspectEvent e WskAbortEvent sono abilitate solo se l'applicazione WSK abilita la modalità di accettazione condizionale nel socket. Un'applicazione WSK abilita la modalità di accettazione condizionale in un socket in ascolto impostando l'opzione socket SO_CONDITIONAL_ACCEPT per il socket prima di associarlo a un indirizzo di trasporto locale. Per altre informazioni su come impostare le opzioni del socket, vedere Esecuzione di operazioni di controllo in un socket.

Dopo aver abilitato la modalità di accettazione condizionale in un socket di ascolto, non è possibile disabilitare le funzioni di callback dell'evento WskInspectEvent e WskAbortEvent del socket. Per altre informazioni sull'accettazione condizionale delle connessioni in ingresso nei socket in ascolto, vedere Ascolto e accettazione delle connessioni in ingresso.

Un socket di ascolto può abilitare automaticamente le funzioni di callback degli eventi nei socket orientati alla connessione accettati dalla funzione di callback dell'evento WskAcceptEvent del socket in ascolto. Un'applicazione WSK abilita automaticamente queste funzioni di callback abilitando le funzioni di callback degli eventi socket orientate alla connessione nel socket in ascolto. Per altre informazioni su questo processo, vedere SO_WSK_EVENT_CALLBACK.

Se un'applicazione WSK abilita sempre determinate funzioni di callback eventi in ogni socket creato, l'applicazione può configurare il sottosistema WSK per abilitare automaticamente tali funzioni di callback degli eventi usando l'operazione di controllo client WSK_SET_STATIC_EVENT_CALLBACKS . Le funzioni di callback dell'evento abilitate in questo modo sono sempre abilitate e non possono essere disabilitate o riattivate in un secondo momento dall'applicazione WSK. Se un'applicazione WSK abilita sempre alcune funzioni di callback degli eventi in ogni socket creato, l'applicazione deve usare questo metodo per abilitare automaticamente tali funzioni di callback degli eventi perché restituirà prestazioni molto migliori.

Nell'esempio di codice seguente viene illustrato come un'applicazione WSK possa usare l'operazione di controllo client WSK_SET_STATIC_EVENT_CALLBACKS per abilitare automaticamente la funzione di callback dell'evento WskReceiveFromEvent nei socket datagram e nella funzione di callback degli eventi WskReceiveEvent nei socket orientati alla connessione.

// Function to set static event callbacks
NTSTATUS
  SetStaticEventCallbacks(
    PWSK_APP_BINDING_CONTEXT BindingContext,
    )
{
  WSK_EVENT_CALLBACK_CONTROL EventCallbackControl;
  NTSTATUS Status;

  // Specify the WSK NPI identifier
  EventCallbackControl.NpiId = &NPI_WSK_INTERFACE_ID;

  // Set the event flags for the event callback functions that
  // are to be automatically enabled on every new socket
  EventCallbackControl.EventMask =
    WSK_EVENT_RECEIVE_FROM | WSK_EVENT_RECEIVE;

  // Perform client control operation
  Status =
    BindingContext->
      WskProviderDispatch->
        WskControlClient(
          BindingContext->WskClient,
          WSK_SET_STATIC_EVENT_CALLBACKS,
          sizeof(WSK_EVENT_CALLBACK_CONTROL),
          &EventCallbackControl,
          0,
          NULL,
          NULL,
          NULL  // No IRP for this control operation
          );

  // Return status of client control operation
  return Status;
}

Se un'applicazione WSK usa l'operazione di controllo client WSK_SET_STATIC_EVENT_CALLBACKS per abilitare automaticamente alcune funzioni di callback degli eventi, è necessario farlo prima di creare qualsiasi socket.