how to construct Completion routine in winsock kernel ?
I found a code but i do want alternative solutions.
or Can anybody explain what’s happening ?
[Below Completion routine]
static
NTSTATUS
NTAPI
CompletionRoutine(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp,
__in PKEVENT CompletionEvent
)
{
ASSERT( CompletionEvent );
KeSetEvent(CompletionEvent, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
[Below actual function call]
KeInitializeEvent(&CompletionEvent, SynchronizationEvent, FALSE);
IoReuseIrp(Irp, STATUS_UNSUCCESSFUL);
IoSetCompletionRoutine(Irp, CompletionRoutine, &CompletionEvent, TRUE, TRUE, TRUE);
//
// Create the socket
//
Status = WskProvider->Dispatch->WskSocket(
WskProvider->Client,
AF_INET,
SOCK_STREAM,
IPPROTO_TCP,
WSK_FLAG_CONNECTION_SOCKET,
NULL,
NULL,
NULL,
NULL,
NULL,
Irp);
if (Status == STATUS_PENDING) {
KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
Status = Irp->IoStatus.Status;
}
if (!NT_SUCCESS(Status)) {
DbgPrint(“MakeHttpRequest(): WskSocket() failed with status 0x%08X\n”, Status);
return Status;
}
WskSocket = (PWSK_SOCKET)Irp->IoStatus.Information;
SocketDispatch = (PWSK_PROVIDER_CONNECTION_DISPATCH)WskSocket->Dispatch;
KeResetEvent(&CompletionEvent);
IoReuseIrp(Irp, STATUS_UNSUCCESSFUL);
IoSetCompletionRoutine(Irp, CompletionRoutine, &CompletionEvent, TRUE, TRUE, TRUE);
//
// Bind the socket
//
Status = SocketDispatch->WskBind(
WskSocket,
(PSOCKADDR)LocalAddress,
0,
Irp);
if (Status == STATUS_PENDING) {
KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
Status = Irp->IoStatus.Status;
}
if (!NT_SUCCESS(Status)) {
DbgPrint(“MakeHttpRequest(): WskBind() failed with status 0x%08X\n”, Status);
CloseWskSocket(SocketDispatch, WskSocket);
return Status;
}
DbgPrint(“MakeHttpRequest(): Connecting to the %u.%u.%u.%u:%u…\n”,
RemoteAddress->sin_addr.S_un.S_un_b.s_b1,
RemoteAddress->sin_addr.S_un.S_un_b.s_b2,
RemoteAddress->sin_addr.S_un.S_un_b.s_b3,
RemoteAddress->sin_addr.S_un.S_un_b.s_b4,
HTONS(RemoteAddress->sin_port));
KeResetEvent(&CompletionEvent);
IoReuseIrp(Irp, STATUS_UNSUCCESSFUL);
IoSetCompletionRoutine(Irp, CompletionRoutine, &CompletionEvent, TRUE, TRUE, TRUE);
//
// Establish a connection with the destination host
//
Status = SocketDispatch->WskConnect( // You can use WskSocketConnect() instead of sequence
WskSocket, // of WskSocket(), WskBind(), WskConnect() calls
(PSOCKADDR)RemoteAddress,
0,
Irp);
if (Status == STATUS_PENDING) {
KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
Status = Irp->IoStatus.Status;
}
if (!NT_SUCCESS(Status)) {
DbgPrint(“MakeHttpRequest(): WskConnect() failed with status 0x%08X\n”, Status);
CloseWskSocket(SocketDispatch, WskSocket);
return Status;
}
DbgPrint(“MakeHttpRequest(): Connected, sending the request…\n”);
KeResetEvent(&CompletionEvent);
IoReuseIrp(Irp, STATUS_UNSUCCESSFUL);
IoSetCompletionRoutine(Irp, CompletionRoutine, &CompletionEvent, TRUE, TRUE, TRUE);
//
// Now we can send the request
//
Status = SocketDispatch->WskSend(
WskSocket,
HttpRequest,
0,
Irp);
if (Status == STATUS_PENDING) {
KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
Status = Irp->IoStatus.Status;
}
if (!NT_SUCCESS(Status)) {
DbgPrint(“MakeHttpRequest(): WskSend() failed with status 0x%08X\n”, Status);
CloseWskSocket(SocketDispatch, WskSocket);
return Status;
}
if (Irp->IoStatus.Information != HttpRequest->Length) {
DbgPrint(“MakeHttpRequest(): Sent %u bytes of the request instead of %u bytes\n”,
Irp->IoStatus.Information, HttpRequest->Length);
CloseWskSocket(SocketDispatch, WskSocket);
return Status;
}
DbgPrint(“MakeHttpRequest(): %u bytes of the request sent successfully\n”, HttpRequest->Length);
DbgPrint(“MakeHttpRequest(): Receiving the answer…\n”);
//
// Receive the server’s answer
//
Status = ReceiveHttpResponse(SocketDispatch, WskSocket, HttpResponse);
if (NT_SUCCESS(Status)) {
DbgPrint(“MakeHttpRequest(): Received %u bytes of data\n”, HttpResponse->Length);
}
CloseWskSocket(SocketDispatch, WskSocket);
return Status;
}