拡張インターフェイスの登録

Winsock カーネル (WSK) アプリケーションは、ソケットを正常に作成した後、WSK サブシステムによってサポートされている 1 つ以上の拡張インターフェイスにそのソケットを登録できます。 WSK アプリケーションは、WSK サブシステムがアタッチ時にアプリケーションに返した WSK_PROVIDER_DISPATCH 構造の Version メンバーを調べることにより、WSK サブシステムでサポートされている拡張インターフェイスのセットを決定します。

各拡張インターフェイスは、WSK NPI に依存しない NPI によって定義されます。 ただし、拡張インターフェイスの NPI では NPI 固有の特性がサポートされないことに注意してください。

WSK アプリケーションは、ソケットで SIO_WSK_REGISTER_EXTENSION ソケット IOCTL 操作を実行することによって拡張インターフェイスに登録します。 ソケット IOCTL 操作の実行について詳しくは、「ソケットでの制御操作の実行」をご覧ください。

WSK アプリケーションが、WSK サブシステムによってサポートされていない拡張インターフェイスのソケットを登録しようとすると、SIO_WSK_REGISTER_EXTENSION ソケット IOCTL 操作は STATUS_NOT_SUPPORTED を返します。

たとえば、次のコード例のように拡張インターフェイスが定義されるとします。

const NPIID EXAMPLE_EXTIF_NPIID = {...};

typedef struct _EXAMPLE_EXTIF_PROVIDER_DISPATCH {
  .
  . // Function pointers for the functions that are
  . // defined by the extension interface.
  .
} EXAMPLE_EXTIF_PROVIDER_DISPATCH, *PEXAMPLE_EXTIF_PROVIDER_DISPATCH;

typedef struct _EXAMPLE_EXTIF_CLIENT_DISPATCH {
  .
  . // Function pointers for the callback functions
  . // that are defined by the extension interface.
  .
} EXAMPLE_EXTIF_CLIENT_DISPATCH, *PEXAMPLE_EXTIF_CLIENT_DISPATCH;

次に、WSK アプリケーションが接続指向ソケットのこの拡張インターフェイスに登録する方法を示します。

// Client dispatch structure for the extension interface
const EXAMPLE_EXTIF_CLIENT_DISPATCH ExtIfClientDispatch = {
  .
  . // The WSK application's callback functions
  . // for the extension interface
  .
};

// Context structure type for the example extension interface
typedef struct _EXAMPLE_EXTIF_CLIENT_CONTEXT
{
  const EXAMPLE_EXTIF_PROVIDER_DISPATCH *ExtIfProviderDispatch;
  PVOID ExtIfProviderContext;
    .
    .  // Other application-specific members
    .
} EXAMPLE_EXTIF_CLIENT_CONTEXT, *PEXAMPLE_EXTIF_CLIENT_CONTEXT;

// Function to register the example extension interface
NTSTATUS
  RegisterExampleExtIf(
    PWSK_SOCKET Socket,
    PEXAMPLE_EXTIF_CLIENT_CONTEXT ExtIfClientContext
    )
{
  PWSK_PROVIDER_CONNECTION_DISPATCH Dispatch;
  WSK_EXTENSION_CONTROL_IN ExtensionControlIn;
  WSK_EXTENSION_CONTROL_OUT ExtensionControlOut;
  NTSTATUS Status;

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

  // Fill in the WSK_EXTENSION_CONTROL_IN structure
  ExtensionControlIn.NpiId = &EXAMPLE_EXTIF_NPIID;
  ExtensionControlIn.ClientContext = ExtIfClientContext;
  ExtensionControlIn.ClientDispatch = &ExtIfClientDispatch;

  // Initiate the IOCTL operation on the socket
  Status =
    Dispatch->WskControlSocket(
      Socket,
      WskIoctl,
      SIO_WSK_REGISTER_EXTENSION,
      0,
      sizeof(WSK_EXTENSION_CONTROL_IN),
      &ExtensionControlIn,
      sizeof(WSK_EXTENSION_CONTROL_OUT),
      &ExtensionControlOut,
      NULL,
      NULL  // No IRP used for this IOCTL operation
      );

  // Check result
  if (Status == STATUS_SUCCESS)
  {
    // Save provider dispatch table and provider context
    ExtIfClientContext->ExtIfProviderDispatch =
      (const EXAMPLE_EXTIF_PROVIDER_DISPATCH *)
        ExtensionControlOut.ProviderDispatch;
    ExtIfClientContext->ExtIfProviderContext =
      ExtensionControlOut.ProviderContext;
  }

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

WSK アプリケーションは、ソケットごとに拡張インターフェイスに登録されます。