Executando operações de controle em um soquete
Depois que um aplicativo WSK (Winsock Kernel) tiver criado um soquete com êxito, ele poderá executar operações de controle no soquete. As operações de controle que podem ser executadas em um soquete incluem a configuração e a recuperação de opções de soquete e a execução de operações IOCTL de soquete.
Um aplicativo WSK executa operações de controle em um soquete chamando a função WskControlSocket . A função WskControlSocket é apontada pelo membro WskControlSocket da estrutura de expedição do provedor do soquete. A estrutura de expedição do provedor de um soquete é apontada pelo membro Dispatch da estrutura do objeto de soquete ( WSK_SOCKET) que foi retornada pelo subsistema WSK durante a criação do soquete.
O exemplo de código a seguir mostra como um aplicativo WSK pode definir a opção de soquete SO_EXCLUSIVEADDRUSE em um soquete de datagrama.
// Prototype for the control socket IoCompletion routine
NTSTATUS
ControlSocketComplete(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
);
// Function to set the SO_EXCLUSIVEADDRUSE socket option
// on a datagram socket
NTSTATUS
SetExclusiveAddrUse(
PWSK_SOCKET Socket
)
{
PWSK_PROVIDER_DATAGRAM_DISPATCH Dispatch;
PIRP Irp;
ULONG SocketOptionState;
NTSTATUS Status;
// Get pointer to the socket's provider dispatch structure
Dispatch =
(PWSK_PROVIDER_DATAGRAM_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,
ControlSocketComplete,
Socket, // Use the socket object for the context
TRUE,
TRUE,
TRUE
);
// Set the socket option state to 1 to set the socket option
SocketOptionState = 1;
// Initiate the control operation on the socket
Status =
Dispatch->WskControlSocket(
Socket,
WskSetOption,
SO_EXCLUSIVEADDRUSE,
SOL_SOCKET,
sizeof(ULONG),
&SocketOptionState,
0,
NULL,
NULL,
Irp
);
// Return the status of the call to WskControlSocket()
return Status;
}
// Control socket IoCompletion routine
NTSTATUS
ControlSocketComplete(
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)
{
// 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;
}
Para obter mais informações sobre cada uma das opções de soquete com suporte, consulte Opções de soquete do WSK.
O exemplo de código a seguir mostra como um aplicativo WSK pode executar a operação IOCTL do soquete SIO_WSK_SET_REMOTE_ADDRESS em um soquete de datagrama.
// Prototype for the control socket IoCompletion routine
NTSTATUS
ControlSocketComplete(
PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context
);
// Function to perform the SIO_WSK_SET_REMOTE_ADDRESS socket
// IOCTL operation on a datagram socket
NTSTATUS
SetRemoteAddress(
PWSK_SOCKET Socket,
PSOCKADDR RemoteAddress
)
{
PWSK_PROVIDER_DATAGRAM_DISPATCH Dispatch;
PIRP Irp;
NTSTATUS Status;
// Get pointer to the socket's provider dispatch structure
Dispatch =
(PWSK_PROVIDER_DATAGRAM_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,
ControlSocketComplete,
Socket, // Use the socket object for the context
TRUE,
TRUE,
TRUE
);
// Initiate the IOCTL operation on the socket
Status =
Dispatch->WskControlSocket(
Socket,
WskIoctl,
SIO_WSK_SET_REMOTE_ADDRESS,
0,
sizeof(SOCKADDR_IN), // AF_INET
RemoteAddress,
0,
NULL,
NULL,
Irp
);
// Return the status of the call to WskControlSocket()
return Status;
}
// Control socket IoCompletion routine
NTSTATUS
ControlSocketComplete(
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)
{
// 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;
}
Para obter mais informações sobre cada uma das operações IOCTL de soquete com suporte, consulte Operações IOCTL do soquete WSK.